Writing to flash from the application

Budvar10: @krupskiI have to disagree a bit. Serial uploading is more comfortable, faster and without need of additional device. If you are developing or tune the APP it is really useful. So, I do not think it is not for "power user".

If I'm using a 328p like an UNO and want the serial port connected to an external UART, I need to disconnect the UART from the serial port in order to program via bootloader. If I flash it with my ICSP, then no problems (and I save those precious 512 bytes). :)

BTW, the comment about saving 512 bytes is sarcasm directed at those who refuse to use the floating point library or printf because it consumes an extra bit of flash (even though their sketch doesn't use all the flash anyway).

Need to be out of target region for write, not in the boot region exactly. Does it?

Needs to be executing from the boot region. Section 7.1 of the current datasheet:

Program Flash memory space is divided in two sections, the Boot Program section and the Application Program section. Both sections have dedicated Lock bits for write and read/write protection. The SPM instruction that writes into the Application Flash memory section must reside in the Boot Program section.

There's an exception for the ATmega48 and many of the ATtiny chips that don't have support for a separate "bootloader section" - in those cases, the BOOTRST fuse is replaced by a SELFPRGEN fuse, which enables SPM use from anywhere in the flash memory.

Thank you @westfw and @krupski. I hope, it will be useful also for OP.

DrAzzy:
Not at all - just get out your ISP programmer and bootload with MiniCore to get modern optiboot and you’re in business.

This is something I want people to be able to download and use so that’s a no-go.

krupski:
How can flash write code running in the application section work when a write to the application section “pulls the rug out from under” your code during the write?

I wasn’t going to write code, I was going to write data in the upper areas of flash, away from where the code is.

@fungus, I made ArduinoOTA library which supports ATmega with more then 64kB of flash. The bin file uploaded from IDE is stored in the upper half of the flash and then Optiboot 7 bootloader enhanced with my copy_flash_pages function, loads the binary at run location and resets the MCU.

To use this, people must flash the modified Optiboot. For Arduino Mega I created a hardware definition for Arduino, which the user downloads and unzips and then selects "Mega 2560 (Optiboot)" in Tools menu and flashes the bootloader. Of course it requires a programmer or "Arduino as ISP". Quite many people do it and use the ArduinoOTA library with Mega.

(Worrying about the proliferation of features in the bootloader, I haven't merged the "copy flash pages" feature into the "official" optiboot. I probably won't.)

fungus: I wasn't going to write code, I was going to write data in the upper areas of flash, away from where the code is.

There is no reason that this cannot be done. Your program simply needs a small "stub" of code located in the boot section. Your update routine would work something like this:

  • User sends a certain serial command to initiate an update.
  • Your code replies with an acknowledge code.
  • User sends data that you store in a ram buffer (i.e. an array).
  • Your code sends the address of the array to the small stub program located in the boot area and calls the stub.
  • The stub writes the data to the designated flash in the application area (which works because this code is in the boot section).
  • The stub finishes and returns to your main program.
  • You send an "update complete" response to the user.
  • If there is more to write you repeat this whole sequence.

Of course you will need to send and receive some sort of checksums or CRCs to insure data integrity, but the above is the basic idea how to make it work.

Hope this helps

Edit to add: You know that writing to flash requires that an entire page be written, right?

To modify bytes within a page, you need to program the flash this way:

  • Read a complete flash page to a buffer.
  • Modify the appropriate byte(s) in the buffer.
  • Erase the flash page.
  • Write the buffer back to the flash page.
  • (optional) Compare the flash page with the buffer to be sure it wrote OK.

Some thing I do in my bootladers is to set OSCCAL to 0x00 before writing EEPROM or flash.

Since the programming time is controlled by the internal R/C oscillator, I like to set it to the slowest speed in order to "cook" the write a bit more.

Then, OSCCAL can be set back to the proper value (not needed if you reset since OSCCAL is set back to normal with each reset).

Juraj: @fungus, I made ArduinoOTA library which supports ATmega with more then 64kB of flash. The bin file uploaded from IDE is stored in the upper half of the flash and then Optiboot 7 bootloader enhanced with my copy_flash_pages function, loads the binary at run location and resets the MCU.

To use this, people must flash the modified Optiboot. For Arduino Mega I created a hardware definition for Arduino, which the user downloads and unzips and then selects "Mega 2560 (Optiboot)" in Tools menu and flashes the bootloader. Of course it requires a programmer or "Arduino as ISP". Quite many people do it and use the ArduinoOTA library with Mega.

What the OP wants to do does not even require a bootloader. Also, since code to write a flash page already exists in any bootloader, all that's really needed is to call existing code within a bootloader.

A simple way to do it is to take existing bootloader source, make the appropriate addersses EXTERN, or place the addresses at the end of the bootloader and let your app read them.

Before I stopped using bootloaders, I did exactly the above to enable writing to flash in the application section.

Of course, the lock bits need to be left unprogrammed in order to read and write the sections (only disable WRITES to the boot section).

What the OP wants to do does not even require a bootloader.

However, you can't get it to work on a "stock" Arduino without extra equipment and relatively complex procedures. Which was also a desirable goal.

@fungus: Do you have to write to flash? Are you trying to write executable code or just data? If it's just data, could you write it to EEPROM instead of flash?