Backup Arduino Nano Every

Hi,

I got a nano every board with a sketch/hex already on it.
I would like to first backup that sketch/hex locally and then try to disassemble it in order to be able to understand what the code does (I have a vague idea) and hopefully to improve it.

The most I could accomplish using Google, ChatGPT, yandex, etc. was to end up running the following command, which doesn't seem to work (I've built the avrdude from source on Ubuntu 22.04, following this tutorial):

# /usr/local/bin/avrdude -vv -p atmega4809 -c jtag2updi -r -b 115200 -P /dev/ttyACM0 -U flash:r:board.hex:i

Avrdude version 8.0-20250311 (8c4b69ac)
Copyright see https://github.com/avrdudes/avrdude/blob/main/AUTHORS

System wide configuration file is /usr/local/etc/avrdude.conf
User configuration file /root/.avrduderc does not exist

Touching serial port /dev/ttyACM0 at 1200 baud
Waiting for new port... using same port /dev/ttyACM0
Using port            : /dev/ttyACM0
Using programmer      : jtag2updi
Programmer baud rate  : 115200
JtagmkII_open_pdi()
JtagmkII_getsync() attempt 1 of 10: sending sign-on command: 
Error jtagmkII_recv_frame() jtagmkII.c 575: timeout
Warning jtagmkII_getsync() jtagmkII.c 650: attempt 1 of 10: sign-on command: status -1
JtagmkII_getsync() attempt 2 of 10: sending sign-on command: 
Error jtagmkII_recv_frame() jtagmkII.c 575: timeout
Warning jtagmkII_getsync() jtagmkII.c 650: attempt 2 of 10: sign-on command: status -1
JtagmkII_getsync() attempt 3 of 10: sending sign-on command: 
Error jtagmkII_recv_frame() jtagmkII.c 575: timeout
Warning jtagmkII_getsync() jtagmkII.c 650: attempt 3 of 10: sign-on command: status -1
JtagmkII_getsync() attempt 4 of 10: sending sign-on command: 
Error jtagmkII_recv_frame() jtagmkII.c 575: timeout
Warning jtagmkII_getsync() jtagmkII.c 650: attempt 4 of 10: sign-on command: status -1
JtagmkII_getsync() attempt 5 of 10: sending sign-on command: 
Error jtagmkII_recv_frame() jtagmkII.c 575: timeout
Warning jtagmkII_getsync() jtagmkII.c 650: attempt 5 of 10: sign-on command: status -1
JtagmkII_getsync() attempt 6 of 10: sending sign-on command: 
Error jtagmkII_recv_frame() jtagmkII.c 575: timeout
Warning jtagmkII_getsync() jtagmkII.c 650: attempt 6 of 10: sign-on command: status -1
JtagmkII_getsync() attempt 7 of 10: sending sign-on command: 
Error jtagmkII_recv_frame() jtagmkII.c 575: timeout
Warning jtagmkII_getsync() jtagmkII.c 650: attempt 7 of 10: sign-on command: status -1
JtagmkII_getsync() attempt 8 of 10: sending sign-on command: 
Error jtagmkII_recv_frame() jtagmkII.c 575: timeout
Warning jtagmkII_getsync() jtagmkII.c 650: attempt 8 of 10: sign-on command: status -1
JtagmkII_getsync() attempt 9 of 10: sending sign-on command: ^[[A^[[A^C

Is there any documentation on this topic so I can avoid annoying you guys on this forum? If not, is this even possible and does anyone have any idea how to do this properly?

Thanks in advance.

You really cannot pull a program back off a device.

If the processor is running the code it is not in HEX, the processor would not understand it, it is in binary. Anything reading and displaying that code would convert it to HEX or other suitable format. When it was programed it could have been in HEX format but it would have been converted to binary before writing to the processor memory,

A lot depends on the processor. Many but not all processors incorporate facilities to prevent exactly what you are trying to do. If the code has a copyright notice it may not be legal to copy it.

Hm, are you sure? Just searching this forum, I see a lot of posts where people are mentioning they are able to write/read their arduino's flash and eeprom memory... It seems like a reasonable thing to expect that if you write something to that memory, you should be able to read it back as well... I understand the format would not be in the form of the c/c++ code (human readable), but I would expect at least some form of binary data related to the sketch to be readable from arduino...

I would like to see those posts. Do you have links for them? Did the posts happen to have instructions for doing this?

Arduino microcontrollers use industry standard (not unique or exclusive to Arduino) microcontroller IC devices. This means that they usually have the option to block reading the firmware back out. Also, it is rare for someone to need to read the firmware. For such small software files, recreating the firmware from scratch will probably be quicker and easier than translating the binary code into human readable code. The exception to this is those who want an exact copy of someone else’s intellectual property.

I use Avrdudess to read and write files from/to AVR/Arduinos. It's basically a Windows GUI for avrdude. Works great and yes it can read the flash and give you a hex file

If you downloaded AVRdude 8.0 from github there should be a avrdude.pdf file that explains how to use avrdude.

Hi @mladen074.

The USB interface ("MuxTO") chip on the Nano Every board has two distinct functionalities:

  • USB to serial bridge
  • UPDI programmer

The chip is normally running in the serial bridge mode, so we must send it a special signal in order to cause it to switch to the UPDI mode that is required to upload a sketch, or to read the binary from flash as you are attempting to do.

That special signal is to open the port, configured for 1200 baud communication, then close it again. This is known as the "1200 bps touch".

You correctly added the -r flag to your avrdude command, which causes it to perform that touch:

So all should be well. However, we do know that an insufficient "1200 bps touch" can cause the error you encountered:

That report is about a deficiency in the "1200 bps touch" produced by Arduino IDE, which does not use AVRDUDE's -r flag to produce the touch (because the -r flag was added only recently). So it isn't certain that there is a similar deficiency in AVRDUDE's touch implementation. But it is worth considering as a possible cause.

Unfortunately the distributed Linux builds of AVRDUDE don't have -r flag support (not built with libserialport) and I don't have time right now to get set up for building AVRDUDE myself with -r flag support. So I wasn't able to test this myself. However, I did verify that I was able to read the binary from my Nano Every board without -r by using a Python script to perform the "1200 bps touch" prior to running the avrdude command.

I used the Python script provided by a community member here. However, I discovered that it did not work reliably until I added a short delay between the opening and the closing of the port. Here is my updated script:

#!/usr/bin/python3
# Based on https://github.com/arduino/ArduinoCore-megaavr/issues/124#issuecomment-1330763422
#   Run this script to reset the Arduino Nano Every
#   eg. sudo python3 mcu_reset.py
#
# Note: You must install pyserial first; i.e. sudo pip3 pyserial

import serial
import os, sys, time
# total arguments
n = len(sys.argv)
if n >= 2:
    port = sys.argv[1]
else:
    port = '/dev/ttyACM0'

print("Port: {}".format(port))

#re-enable hupcl temporarily (necessary for arduino reset using serial port)
os.system('sudo /bin/stty -F {} hupcl'.format(port))

try:
    #perform Arduino Nano Every reset "handshake"
    ser = serial.Serial()
    ser.baudrate = 1200
    ser.port = port
    ser.open()
    time.sleep(0.5)
    ser.close()

except serial.SerialException:
    print("Error: serial.SerialException")
    exit()

(note the time.sleep(0.5) at line 28)

I saved the file as touch.py, then ran this command from the folder where I saved the file:

python3 touch.py /dev/ttyACM0 && /usr/local/bin/avrdude -vv -p atmega4809 -c jtag2updi -b 115200 -P /dev/ttyACM0 -U flash:r:board.hex:i

The flash was read into a file named board.hex as expected.

So give that a try.

The option, yes, and it is certain that this is done on any consumer device. However, this is not a consumer device. This is an Arduino board. Do you really believe it is likely that someone would bother to set the lock fuses on an Arduino Nano Every?

Thank you a lot @ptillisch ! You definitely understand the issue enough to be able to resolve it. I've downloaded the hex file successfully, and I'll probably post a new issue on the avrdude tracker to let them know how to tweak their "-r" option to work properly, just like in your case with this small delay. Thank you a lot for helping me, as I was really stuck at this point. Much appreciated!

Thank you also to others who also tried to help with their comments. I'm really amazed this community has such a support behind it, where people can really quickly get the answers they're looking for. Kudos for that!

You are welcome. I'm glad you were successful in reading the hex file!

If you like, I'm sure the forum members would be interested in hearing about how things go for you with the disassembly.

Regards, Per

Save this page as a favorite. I'd like to know how this goes. I wouldn't mind seeing how whatever it is that you can drill out looks like - the readability of the result.

Since the topic of this post was how to backup the currently running sketch on Arduino Nano Every, it seems we would have to go off-topic too much if we try to cover the entire process. But, I'll post the steps that I think might help us get to the point where we can have something usable, in terms of the source code.

The disassembly part was surprisingly easy, comparing to backing up the hex file. I've followed (among others) a tutorial from here, so a simple command like this did the trick:

avr-objdump -j .sec1 -d -m avr board.hex > board.dump

We can see all the code/data sections in the hex file, using: avr-objdump -h board.hex
in my case, i only had one, default: sec1

Note that I also dumped the raw content of the flash using:
python3 touch.py && /usr/local/bin/avrdude -vv -p atmega4809 -c jtag2updi -r -b 115200 -P /dev/ttyACM0 -U flash:r:board.raw:r

which I've used to find some human-readable strings inside, in order to get some hints about what the code could be all about: strings board.raw

There usually appear some familiar-looking strings which could point us in the right direction, like some constant strings or error messages or so.

Now, the most difficult part is, of course, to decompile the disassembled code back into the C++ for Arduino, considering that the compilation process does some optimizations, which change the original source code, before creating the actual assembly code. Depending on which decompiler we use, the quality of the output will differ. There are some online decompilers as well, like this one, but all in all, I haven't found any Arduino specific decompiler.

What is interesting, though, is that, just by tweaking the default Arduino IDE compile sketch process and placing some markers in the resulting output binary, we could probably be able to make the decompile process easier...

Anyway, the best recommendation I read so far, was from this SO answer, in essence, suggesting that we could do incremental compilation of an empty sketch, compare it with the compiled/assembled/disassembled result and keep adding lines to the source code, trying to get to the point as close to the original one that we disassembled in the first place. It does sound like a tedious process, but that's by design, I guess.

That being said, thank you all one more time for your help, it's really appreciated.

In order to make all relevant information available to any who are interested in this subject, I'll share a link to @mladen074's report to the AVRDUDE developers: