Skip to content

Add support for Arduino Nano Every / ATtmega4809#93

Open
moonzephyr386 wants to merge 2 commits intokalymos:masterfrom
moonzephyr386:atmega4809
Open

Add support for Arduino Nano Every / ATtmega4809#93
moonzephyr386 wants to merge 2 commits intokalymos:masterfrom
moonzephyr386:atmega4809

Conversation

@moonzephyr386
Copy link

This adds support for the Arduino Nano Every, with a ATmega4809 based board.

It doesn't appear to have been wildly popular, but I had a couple around and I thought it would be interesting to add support for it to the PsNee. It is pin compatible with the Arduino Nano, so the pinout would be the same as the Nano.

The ATmega4809 can run with an oscillator speed of 20 MHz or 16 MHz. The Nano Every comes with the fuses set for 16 MHz operation by default, so I left it like that. The CPU divider registry does have to be set at boot to prevent it from running with its default clock divider of 1:6. We also need to clear the interrupt flag on every timer interrupt, those where the only two changes needed to add support for it that fall outside of MUC.h.

I tested this successfully on a PAL SCPH-7502 / PU-22. Unfortunately I don't have any Japanese PS1, so I wasn't able to test the BIOS patch.

This PR also has a fix for the board detection loop: when testing I found that interrupts / timers add a massive overhead to the delay functions, so lows were being undercounted. In my Nano and Nano Every, _delay_ms(200) would actually take about 600 us of wall time. With this fix, the low count is now very consistent and matches the expected count of ~2500 (I have a PU-22).

Adds support for the Arduino Nano Every, with a ATmega4809 based,
of the megaAVR family.
_delay_us is wildly inaccurate when there's interrupts happpening,
(namely timers), with a sleep of 200us of CPU time actually taking
500us or more.

Other locations either already use the accurate timer or have the
timer off.
@kalymos
Copy link
Owner

kalymos commented Sep 11, 2025

Hi,

That's a really nice job you've done there.

I don't plan on integrating these commits immediately. I'd like to publish a version where I've reimplemented the code to have serial debugging output. It's almost ready to be published, but I still need to test it.

Then I will gladly integrate your modifications for the next version, but there are two things that will still need to be resolved before publication, firstly that I provide myself with a copy of the board to be able to test it (that should not be the hardest part) and to integrate it into the project's board manager (psneecore). In this way I could guarantee identical implementation to the other board, and that the tutorial is correct in all cases.

I hope you find my position reasonable, and that you will continue to collaborate on this project.

@moonzephyr386
Copy link
Author

moonzephyr386 commented Sep 12, 2025

Of course! It's not a problem in the slightest. I just wanted to get this out there instead of it just staying with me and being of no use to anyone else. It should hopefully be useful for other megaAVR Series-0 chips.

And like I said, I didn't have the means to test BIOS injection. I mapped the ports and attempted to guess the corresponding instructions, but it's highly likely it is nonfunctional.

A few interesting notes on the Nano Every that I didn't notice when I started this:

If you want to buy an official Arduino, the Nano Every is the cheapest one available in the classic form factor, if you don't count the new brand new Nano R4, which doesn't use an ATmega at all. It's also very well stocked (probably because it's not that popular!) This may not mean much as Nano clones are cheaper even, but for people who want to source official boards (and not have to deal with CH340 drivers or fake FTDI chips), it's a pretty good choice and now that I think about it, the reason why I had a couple around to begin with.

The other one, which should be a pretty big advantage for the PsNee: the Nano Every doesn't contain any bootloader on the ATmega4809, so it boots up instantly by default, meaning people won't need to program it via ISP even when they need the BIOS patch! ATmega programming is handled via the onboard SAMD11 chip, which is a fully fledged programmer that can program the ATmega via UPDI and boots in parallel with it. The Nano Every has no standard ISP header pins at all, actually, if you want to reprogram the SAMD11 you would need a SWD programmer, but no one should need one, as the ATmega fuses can be programmed via USB via the SAMD11 just fine.

Fuse setting happens on every upload via the Arduino IDE. In fact, boards.txt sets:

  • BOOTEND to 0x00 (no bootloader, ATmega boots the sketch directly)
  • OSCCFG to 0x01 (run oscillator at 16 MHz)
  • SYSCFG0 to 0xC9 (no CRC check during reset, reset pin to reset and EEPROM not erased on chip erase)

See Section 7.8 – Fuses. Potentially the only extra fuse we'd like to set for PsNee would be the 6th fuse, SYSCFG1, to decrease the start-up delay from the default 64ms to 0. I've managed to do this with a platform.txt and boards.txt modification.

It's also funny you mention wanting to add serial debugging, I've added it myself when doing this for debugging and that's how I discovered the lows count discrepancy in board detection, but I left them outside this PR and was pondering raising it as a separate PR to not clutter this one. I'll wait for your changes as they seem more thorough, although the only reason to use SoftwareSerial would be for ATtiny, right? We have hardware UART on all of the ATmegas, raw chip or Arduino.

@kalymos
Copy link
Owner

kalymos commented Sep 13, 2025

I completely understand your goal in using this version of nano, and it makes perfect sense. The goal that had been followed until now was more of an idea focused on availability and ease of access to the component, which is certainly less "virtuous".

Until now, I hadn't looked at the Series-0 programming system at all, which actually seems more interesting than the ISP. The only drawback I see is that I should include an additional procedure in the wiki, which I tried to keep as obscure as possible.

Regarding fuses, there is one fuse that turned out to be necessary: ​​the one that allows you to specify a minimum voltage for booting. Without it, BIOS patches tend not to work because they intervene very early during boot.

Indeed, adding a Serial output makes the code a little more difficult to see, but I placed it entirely in your functions which are in the config file, and in compilation parameters. The main interest of this debug output is to have all the information from the DATA line. The use of SoftwareSerial is indeed for ATtinys.

If you want to take a look at my working version, it finds the https://github.com/kalymos/PsNee/tree/PSNee-8.7.0

@kalymos
Copy link
Owner

kalymos commented Oct 16, 2025

I finally received the board. I ran a few quick tests. The region code injection works fine for me, but the BIOS patch injection doesn't.
One of the first avenues I'll explore to be sure I rule this out is to look at how the fuses are initialized when programming the board.
Then I'll have to make some observations with the logic analyzer to see if the bit masking is happening at the right time.
Next, I'll need to understand the form of the manufacturer's language to use.
You won't mind if I do it once I have the courage...

@moonzephyr386
Copy link
Author

Yeah, of course, not a problem in the slightest! Like I said, I don't have a PS1 that needs BIOS patches, so that code was completely untested. Really appreciate you looking at this!

Fuse initialization should be quite straightforward. For the Nano Every, the Arduino IDE programs the fuses every time you upload a sketch. If you go to platform.txt under megaavr, you can see under tools.avrdude.upload.pattern and tools.avrdude.program.pattern how the fuses get programmed. You probably want to set fuse 6, SYSCFG1 (Start-Up Time Setting), as its default is 64 ms. I just added "-Ufuse6:w:0x00:m" to all pattern arguments to set it to 0ms startup and that gets programmed on every upload, but if you want, you can make it a variable and set it via the corresponding boards.txt.

Same applies to other fuses. Hope that helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants