Mega2560 bootloader kludge

If you try using the 'monitor' built-in the bootloader by typing 3 '!' immediately after hitting the reset button on the Arduino mega2560 you will see a bunch of garbage on the screen, every time you type a character. Well the program has a bug (several bugs), for those technically inclined, the RAMPZ I/O register is initialized to '0' instead of '3' in the PrintFromPROGMEM() routine. I have a kludge that will allow you to use the monitor with proper prompts! You need a 'C' ino file and a '.S' assembler file (note the capital 'S') to fix the problem. You will then be able to examine the bootloader. To examine your program, you have to update the '.org' statement so that the strings start at 0xE0E4, with the mostly empty kludge program, 0x110 has to be subtracted, the bigger the program the bigger the offset to subtract, thanks to the compiler/assembler/linker(check the hex file it tells you where the stuff is loaded in memory). Create a kludge project in the arduino IDE and upload it to your mega2560. Then you can use to IDE's Serial Monitor to send !!! after a reset on the mega (be quick, a very short timeout disables the !!! escape) Set the speed of the Serial Monitor to 115200. I included a sample usage using the Tera terminal emulator. Enjoy!

kludge.ino

extern "C"
 {
   void start();
 }
 
 void setup() {
   start();
   // your program here, remember to update the '.org'
 }
 
 void loop() {
   // your program here
 }

kludge.S

 .global start
 start:
   ret
 .org  (0xe0e4 - 0x110)   ;this is a byte address and 
                        ;somehow the compiler/assembler 
                        ;locates it at 0xE1F4, hence the 
                        ; " - 0x110 " to end up at 0xE0E4!!!
 mix:
   .ascii  "ATmega2560\0", \
           "Arduino explorer stk500V2 by MLS\0", \
           "Bootloader>\0", \
           "Huh?\0", \
           "Compiled on = \0", \
           "CPU Type    = \0", \
           "__AVR_ARCH__= \0", \
           "AVR LibC Ver= \0", \
           "GCC Version = \0", \
           "CPU ID      = \0", \
           "Low fuse    = \0", \
           "High fuse   = \0", \
           "Ext fuse    = \0", \
           "Lock fuse   = \0", \
           "Mar  7 2013\0", \
           "1.6.8\0", \
           "4.3.5\0", \
           "V#   ADDR   op code     instruction addr   Interrupt\0", \
           "no vector\0", \
           "rjmp  \0", \
           "jmp \0", \
           "What port:\0", \
           "Port not supported\0", \
           "Must be a letter\0", \
           " \0", \
           "Writting EE\0", \
           "Reading EE\0", \
           "EE err cnt=\0", \
           "PORT\0", \
           "0=Zero addr\0", \
           "?=CPU stats\0", \
           "@=EEPROM test\0", \
           "B=Blink LED\0", \
           "E=Dump EEPROM\0", \
           "F=Dump FLASH\0", \
           "H=Help\0", \
           "L=List I/O Ports\0", \
           "Q=Quit\0", \
           "R=Dump RAM\0", \
           "V=show interrupt Vectors\0", \
           "Y=Port blink\0", \
           "*\0"

Partial sample of 'hex' file showing where the strings should be in flash memory, skipping lots of lines before and after.

...
3598 :10E0D0000000000000000000000000000000000040
3599 :10E0E0000000000041546D656761323536300041F3
3600 :10E0F000726475696E6F206578706C6F72657220DE
3601 :10E1000073746B3530305632206279204D4C530099
3602 :10E11000426F6F746C6F616465723E004875683F52
3603 :10E1200000436F6D70696C6564206F6E203D200048
3604 :10E130004350552054797065202020203D20005FF9
3605 :10E140005F4156525F415243485F5F3D2000415658
...

Hmmm. This certainly catches my attention. Does the standard bootloader have this back door? It is not something I want to leave available to end users...

Oh yeah. Don't you remember the "my sketch that happens to include three exclamation points won't upload" problems? If the STK500v2 bootloader wasn't buggy, you'd be able to enter the "monitor mode" after any RESET.

It is not something I want to leave available to end users...

Why not? It's not like the flash on your ATmega is secure at all. And an upload doesn't erase unused pages in flash, so any sketch could access that code.

".org" is pretty useless in the Arduino environment; the linker potentially relocates everything. Thus needing to "guess" at the offset needed.

You can always load optiboot instead of stk500boot; there's no monitor in optiboot.

(although I have vague recollections of the stk500 bootloader being updated to not include the monitor, for space reasons. Has OP tried this on a recent, genuine, Mega board?)

That is the bootloader the Arduinos ATmega2560 are shipped with. The Unos have the optiboot bootloader which has only the loader part, as far as a quick look at the "c" code tells me. You can find the source code for bootloaders of different Arduinos (on Windows) at: D:\Program Files (x86)\Arduino\hardware\arduino\avr\bootloaders. The Optiboot would need some changes to address the 256kb of the atmega2560, i.e. use the 'elpm' AVR instruction to address beyond 64kb.

I am not 100% sure about that...

The board I tested on is an Elegoo...

Just tried it on a genuine Arduino Mega, same bootloader, hooked up to a Raspberry Pi and using the Serial Monitor in the IDE. And it doesn't have the bug... It printed everything correctly. Buggy Elegoo but fine genuine Arduino? I created a program to disassemble an 'hex' file and the compared the code in the Elegoo with the code in the hex file and they are the same??? Now I will have to check if the genuine Arduino Mega has a fixed bootloader....

Double checked and this is the buggy line in the bootloader hex file:
:10E38000C0F308959C01260F311DC901A0E0B0E043
the line should end in "A3E0B0E0??" (not sure about the checksum, I think 40) The A0E0 is E0A0 (little endian) and is a "ldi r26,0x0' and it should be E0A3: 'ldi r26,0x3'. r26 is then loaded in the I/O register RAMPZ to form an 18 bit address that points in the bootloader area (0x1F000-0x1FFFF) for the 'elpm' instruction: 'extended load program memory'.

Mystery solved. In the IDE ../bootloaders/stk500v2 folder there are 2 hex files:

stk500boot_v2_mega2560.hex (21kb)
Mega2560-prod-firmware-2011-06-29.hex (23kb)

The smaller file (21kb) is the bootloader found in the Elegoo Mega. The bigger file (23kb) is the bootloader found in the Genuine Arduino Mega. The difference between the files is that the bigger file has the names of the interrupts for display when the 'V' (List interrupt vectors) command is issued and it also loads the proper value in the RAMPZ register. BTW if "ENABLE_MONITOR" is not "#define" in the 'C' code the monitor code will be bypassed. But why would you do that? Reduce the size of the bootloader to make more room for the user? How many users have used 256kb of flash?

[quote="nandgate, post:9, topic:1036399"]
The difference between the files is that the bigger file has the names of the interrupts for display when the 'V' (List interrupt vectors) command is issued and it also loads the proper value in the RAMPZ register. [/quote]
Interesting. The source code certainly looks wrong. While it's using pgm_read_xxx_far(), I don't see it passing any value for the high byte other than zero. :frowning:

Reduce the size of the bootloader so that it fits in the (maximum) boot region size (8k)
See Code too big when compiled with gcc4.3.2 · Issue #3 · msproul/Arduino-stk500v2-bootloader · GitHub
(MSproul's code is somewhat different than the Arduino trunk. It has ... different bugs :frowning: I thought MSproul was maintaining this bootloader, but it doesn't look like anything has happened in a long time. (Not that Arduino is very good at importing changes. Optiboot is up to version 8+, and Arduino is still shipping v4.4))

I wonder where Mega2560-prod-firmware-2011-06-29.hex comes from?

There is a conditional switch in the 'C' code to include the interrupt vector names or not. That hex file was generated with the names included. There are 38 bytes (19 words) left unused in the bootloader in that hex file, some compilers might go overboard. I assumed the 'prod' portion of the name stood for 'Production'... well the genuine Arduino Mega is using it and it doesn't have the RAMPZ bug!

Here are the metrics collected during compile for the 2 hex files:

Mega2560-prod-firmware-2011-06-29.hex
AVRLib version: 1.6.7
GCC version: 4.3.3
Compile date: Sep 9 2010

stk500boot_v2_mega2560.hex
AVRLib version: 1.6.8
GCC version: 4.3.5
Compile date: Mar 7 2013

If it was reliable, I would use it to help people, e.g. LED problem? Run Y=port blink. EEPROM bad? Run EEPROM test.. etc.

Instead of upload this sketch that sketch etc...

Heh. Both .hex files are older than the source code :slight_smile: :frowning:

The last update comment I can find is on line 88 of the 'C' source and reads:
//* Jan 1, 2012 Issue 544: stk500v2 bootloader doesn't support reading fuses

Is there a different source for stk500boot.c?

There have been some edits since then, apparently not recorded in the source.

So I'll repeat - We don't know what source the "current" .hex files were compiled from :frowning:

The github version and the file found in the Arduino distribution folder are the same. It appears that the changes after 2012 are not documented in the file itself but rather as comments in git. I compiled the file with MicroChip Studio 7.0 (formerly known as Atmel Studio) and set up the options to create a ".lss" file of the assembler generated, IMHO that code will never work. The .hex file were obviously generated by a different compiler. Microchip Studio 7.0 uses avr/gnu 5.4.0 P.S. I had to make significant changes to stk500v2 compiled by avr/gnu to end up with something that stands a chance to work.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.