Possible to partially update boot EEPROM?
sccoupe
Posts: 118
The concept seems pretty straight forward to update the boot EEPROM (32kbyte). Keeping a boot loader at the beginning of the hex file that would never be over written seems to be the tricky part as the compiler may recompile things different with small changes. The thought was to have a boot loader portion of the code that would wait for a serial command to either execute the rest of the code or to go into an EEPROM write mode to start accepting serial data and writing it byte by byte to the EEPROM starting at the address that is at the end of the boot load code. Is this possible? I know that the entire EEPROM can easily be done this way, but if it fails then the device will no longer work. Leaving a boot loader intact would allow for further tries to field update code. Thoughts?
Comments
I'm pretty sure this sort of thing (preserving a bootloader) is possible but it's not possible to preserve a section of the lower 32K of the EEPROM.
IIRC, the systems doing this sort of thing keep the programs on a SD card and the EEPROM program is used to load the desired program from the SD card. It's also possible to have a program stored in upper EEPROM which gets loaded into RAM by the bootloader code.
To protect the EEPROM the write protect pin is held high (I think). I'm not sure how the program can be changed in the UPPER EEPROM if the WP is high. I don't think it can. I think if you write protect the EEPROM you can only write new programs to the SD card.
I'm pretty sure Cluso99 has a system which works well for this sort of stuff. I think there are other bootloader systems around. I think any bootloader which protects the part of the EEPROM has to have the whole EEPROM write protected. It's possible to have more than one EEPROM. You can use the address pins to assign it a different I2C address. You bootloader could write the new program to this alternate EEPROM which isn't write protected.
I'm not looking specifically to write protect the EEPROM, I'd just like to update part of it and leave a bootloader intact incase there are write issues. So, if I include a boost loader in my code, can this be kept in the first part of the hex file so that I can just start writing hex to the part after the boot loader, unless of course there is some kind of checksum that the propellor requires to be correct of it is to start running the code on the next reboot.
I'll just add an "I don't know" so you don't think I'm ignoring the question. It seems like something like this should be possible but I'll let someone more knowledgeable on the topic elaborate on how (if it's possible) it can be done.
The only thing which changes is where variables end up in the assembled binary. But as you don't need the object feature for the bootloader, you can simply replace var section variables by dat section variables in the bootloader code.
The challenge might be to find out where the bootloader ends and how to call the real program.
I think there are already concepts described in the forum of bootloaders which work a bit different. There the upper 32kB of the EEPROM contain the real code. The bootloader simply loads the full 32kB of upper EEPROM into HUB-RAM and starts that code in the SPIN interpreter. In case of an update it simply writes a 32kB image to upper EEPROM. In case of a broken EEPROM it is very likely that the lower part of EEPROM will still work and it is very unlikely that the EEPROM will repair itself ;o) So, in case of a failed write to upper EEPROM the bootloader might finally write thai image to lower EEPROM giving the customer some more time before the EEPROM has to be exchanged.
One nice feature of Spin binaries is that you can relocate them just by adding an offset to the 5 state variables in the header. The boot loader wouldn't even have to load the application from EEPROM since the Prop loader copies the entire 32K from the EEPROM to hub RAM prior to execution. Once you have verified the application program you can just do a COGINIT(0, $F004, app_ptr), where app_ptr contains the starting address of the application program. You would just need to reserve a small amount of space between the end of the boot program and the start of the application program to provide stack space for the boot loader.
EDIT: Another possibility is to put your boot loader at the end of memory by specifying a very large DAT area. The application would just be written to the DAT area in EEPROM. This would allow the application to reuse the space that the boot code was in for stack space.
This sounds exactly like what I need. Any example of this around as least as far as the 5 state variables you speak of? This sounds as if I can build the boot loader and load it in the EEPROM as one would a usual program. Then create the real program code and just send in the hex file to load the rest of the EEPROM via the boot loader. Once verified, reboot and call up the program with COGINIT(offset). Time to do some playing.
Compile hello.spin to hello.binary using the F8 key prior to compiling boot.spin.
There is a checksum (simple xor IIRC) at hub (=eeprom) $0005 IIRC.
You could either use the upper 32KB ofa 64KB eeprom, or the end section of the lower 32KB and then recalculate the checksum and rewrite it.
There a couple of threads that may have some info for you...
I posted a thread about using an 8KB 24C64 eeprom. It recalculates the checksum.
I posted a PropOS and it has a programming eeprom module, either lower or upper 32KB.
I use 1mb eeproms for the boot eeprom - they're electrically and programmatically compatible with the 256kb flavor when only reading or writing the first 25% so the device boots perfectly well. I use the other 756kb for persistent storage.
Depending on your application, I'd think carefully about writing directly over the program image in real-time as power failures may cause the entire EEPROM "page" to become corrupt if you get unlucky with timing.
I do firmware updates over the wire by writing the "new" firmware into the upper half of the EEPROM until it's all arrived and checksummed. Then I copy it from the upper half to the lower half in one thoughtfully coded loop. I do this for two reasons - first, there's no place to store the new firmware in memory because the memory is full of the current version of firmware; second, it completely solves problems with dropped communication half-way through the update; finally - this approach drastically minimizes the window during which I'm vulnerable to power failures that would cause my product to become a brick, although the process still requires around 1.5 seconds just for the writes, which happen at 3ms per 128 bytes.
I don't understand why you believe you need a separate boot loader at all?