Rewrite existing application flash with new hex file on Arduino Mega2560?

Hi. I am in unfamiliar territory so please be a little forgiving :). I have a .hex file (generated by the Arduino IDE) for a simple Blink program written for the Arduino Mega2560 board that I am working with right now. it is 4362 bytes in size exactly. I want to write a program that does the following:

  1. load this entire hex file into (flash) memory.
  2. rewrite the current application code in flash with the hex file that was loaded in step 1, so that...
  3. the bootloader can pick up this newly flashed hex file (Blink) the next time the Arduino is reset.

So far with my limited knowledge I have been able to cobble together the following program with avr/boot.h whose documentation provided a function boot_program_page that I more or less have a good understanding of and decided to use as is:

#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/boot.h>       // contains functions for SPM operations

// Hex code for the blink program
#include "hexfile.h"

// Function that writes a page to flash in SPM (taken from: https://www.nongnu.org/avr-libc/user-manual/group__avr__boot.html)
void bootProgramPage (uint32_t page, uint8_t *buf)
{
    uint16_t i;                // Loop index for iterating using 16-bit address offsets
    uint8_t sreg;              // 8-bit word for saving 8-bit status registers before restoring

    sreg = SREG;               // Store current state of the status register for later restoring
    cli();                     // Clear interrupts so that following critical section is not interrupted
    eeprom_busy_wait();        // Wait for eeprom operations to complete
    boot_page_erase(page);     // Erase page (prepare it) before writing
    boot_spm_busy_wait();      // Wait until page is erased
    for (i=0; i<SPM_PAGESIZE; i+=2)     // Fill page buffer with contents from hexfile to write to application flash
    {
        // Take two bytes at a time and combine them into a single 16-bit word (AVR is little endian)
        uint16_t w = *buf++;
        w += (*buf++) << 8;
        boot_page_fill (page + i, w);
    }
    boot_page_write (page);   // Write buffer to flash page (in SPM)
    boot_spm_busy_wait();     // Wait for write operation to complete
    boot_rww_enable ();       // Reenable RWW-section again (We need this if we want to jump back to the application after bootloading)
    SREG = sreg;              // Re-enable interrupts (if they were ever enabled)
}

void setup()
{
  Serial.begin(115200);
  Serial.println("Writing program to flash...");
  bootProgramPage(0x0000, hexcode); // write to page at 0x0000 ?? (not really sure on this one)
  Serial.print("Done.");
  // now i press the reset button on the arduino
}

void loop()
{
}

Here hexfile.h contains all the 4362 bytes for the hex file in a uint8_t array (which I generated using a python script from the actual hex file...not the best idea perhaps but I'll address it later.)

const uint8_t hexcode[] PROGMEM = {0x3a, 0x31,...

The code runs but pressing reset simply restarts THIS program itself, NOT the blink sketch. I'm clearly doing something wrong...my guesses are i am writing to the wrong address in application flash. Maybe the whole idea is flawed. Any suggestions are welcome. Thanks for your time.

on the ATmega2560, only the bootloader can write into the flash memory.
the Optiboot 8 has a function that can do it. there is a .h file which declares a function call to this function in the bootloader.
but it s just the start. you need a way for running application to move the new application. but the application runs from the flash so it can't overwrite itself. so I added a function to Optiboot which does this.
it is used here
https://github.com/JAndrassy/ArduinoOTA/blob/master/src/InternalStorageAVR.cpp

1 Like

Thanks for the response. I really had lost hope given how niche this appears to be. I am not familiar with optiboot. From what I understand, I need to first replace the default arduino bootloader with optiboot somehow on the mega and then use optiboot's libraries for doing what I am trying to achieve instead of avr-libc's avr/boot.h, is that correct? Also I'll need to use the function that you linked to?

I didn't link to the function. I linked to an example of the use of the function.

You can burn the modified Optiboot with MegaCore and then use this .h file
https://github.com/JAndrassy/ArduinoOTA/blob/master/src/utility/optiboot.h

1 Like

now I can do things like this

@Delta_G not really a problem on the Mega. it has the largest flash in the classic ATmega family. it has even an extra register to access the upper half of the flash.

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