Wireless programming without SPI flash

Started by bobleponge, June 20, 2014, 05:46:02 PM

bobleponge

Hi,

  I've found a thread with similar title, but not the same intend.
I wonder if it's possible to wireless program a moteino without a SPI flash, and instead use the AVR's internal flash ?
Usually, my sketches never overcome half the flash size, thus writing the pages unused with a later version of the program would work, no?

What I'm thinking of is like that:
// 1) Split the flash space in two 15.5kB / 15.5kB area virtually
void (*NextInst)() = 0;
byte flashPos = !!EEPROM.read<byte>(VERSION_OF_CODE_TO_USE_ADDR); // Either 0 or 1 (15.5KB)
// 2) In setup() do something like this:
void setup()
{
    NextInst = flashPos * 0x3E00;
    if (getPC() > NextInst+100)  NextInst(); // Absolute jump to this function if required

    // Set up radio here
    [...]
}

int getPC() 
{
    // Small trick to get program counter to figure out from where we run
    int a = *(&a + 2); // Read the return address that's 2 bytes after the stack variable
    return a;
}

// In the flash receiving code do something like:
void receiveFlashCode()
{
    while (pageAddr < 0x3E00 * !flashPos)
    {
        // Receive flash content and accumulate a page in buf
        [...]
        boot_program_page(pageAddr, buf); // See http://www.nongnu.org/avr-libc/user-manual/group__avr__boot.html for how to flash the flash
        pageAddr += SPM_PAGESIZE;
    }
    // Now, update the EEPROM to use the new position on next boot
    EEPROM.write(VERSION_OF_CODE_TO_USE_ADDR, !flashPos);
    // Reset
    watchdogTrigger();
}


The basic idea is to alternate between 2 sketches, loaded depending on the EEPROM last written value.
This has the big advantage that you don't need a SPI flash chip (or at least, you can use it completely in your sketch), and you still have a failsafe if your new sketch fails (you can call NextInst function pointer anytime)

However, I wonder if the AVR code is position independant or not (I would expect not), so copying the binary from the HEX file to the new position would work ? If it is, then how to fix the position in the code with some linker trick for the functions ?
Did anyone tested this kind of pattern ?

tve

It's actually possible to write a bootloader that allows wireless updating without external flash and without using up half the flash or eeprom. See https://github.com/jcw/jeeboot. That project is not yet ready for prime time, but I'm using it for my own projects. The #1 issue with any such scheme is producing a portable server component because everyone attaches their nodes differently to their host. In my case I use jeenodes+ethershields as RF/UDP gateways and so my boot server speaks UDP. But that's not a common set-up.

Felix

I think the real #1 issue is a dropped packet or aborted transmission and your node becomes unusable.
The FLASH chip is also very cheap and provides a real MAC id which can be very handy.
Why scratch your left ear with your right foot?

bobleponge

Since we have 2 copies of the FW, then no, it'd not break (provided we only write the EEPROM's valid IMG flag when the new copy is received flashed and crc'ed correctly). Other advantage is that it does not consume the SPI chip power since none required. I agree that it's a bit of NIH/redo work. Thanks for the Jeeboot link.

Felix

EEPROM is 1K, you need at least 31K if space to store an image before you replace the flash memory.

bobleponge

You did not get the idea. The idea is to store 2 versions in FLASH, with some code to change either version (one at addr 0, the other at addr 0x3E00).
The EEPROM is only there to say which version to load (a boolean is enough). Since most sketches are well below 15kB, you can store 2 in the internal flash, it's a viable alternative.

Typically, in the main, read the EEPROM, if it says load version 0, then set a function pointer to x and call that, else set the function pointer to y and call that.
It's exactly like what you're doing with SPI flash, but without a SPI flash, using the AVR's internal flash instead.

Felix

Go for it, that would work. But only if your sketches are less than 15.5K.

tve

Quote from: Felix on June 22, 2014, 08:28:10 AM
I think the real #1 issue is a dropped packet or aborted transmission and your node becomes unusable.
The FLASH chip is also very cheap and provides a real MAC id which can be very handy.
Why scratch your left ear with your right foot?
If you actually look at jeeboot you will see that a lost packet does not at all make the node unusable. The boot protocol is very robust and fits into the bootloader section, so you have most of the flash available for the sketch. No need to have two banks of flash for sketches.

Felix

Quote from: tve on July 04, 2014, 02:49:09 AM
If you actually look at jeeboot you will see that a lost packet does not at all make the node unusable. The boot protocol is very robust and fits into the bootloader section, so you have most of the flash available for the sketch. No need to have two banks of flash for sketches.

Maybe I'm missing something but JCW clearly states this:
QuoteOnce an upgrade has been started, there is no way back but to complete it, since the code will be invalid as soon as even one byte is changed in flash memory.