stefanrueger / urboot

Small AVR bootloader using urprotocol
GNU General Public License v3.0
55 stars 8 forks source link

Dual boot with SPI EEPROM #21

Closed Floessie closed 1 year ago

Floessie commented 1 year ago

Hi Stefan,

I'm watching the urboot integration into MiniCore from the sidelines. One really useful feature to me seems the OTA updatability with an external SPI flash. The documentation for this feature is relatively sparse, but if I'm not mistaken, indeed only SPI flash is supported, not SPI EEPROM.

Are there any plans to extend dual boot to SPI EEPROM? If not, what SPI flash ICs can you recommend (preferably in PDIP-8)?

Thanks, Flössie

stefanrueger commented 1 year ago

Are there any plans to extend dual boot to SPI EEPROM?

No plans, I am afraid, unless there is a persuasive PR :wink:

I have been using Winbond W25Q128FVSSIG SPI flash memory (16 MB), W25Q64FVSIG spi flash memory (8 MB) and the dirt cheap GD25Q05 SPI flash memory (64 kB) which has a smaller footprint but does not leave space for logging etc and wouldn't even work for AVR with flash beyond 64 kB. Most SPI flash memory should work. I heard the Anarduino and Moteino board with their respective SPI flash memories (S25FL128S, W25X40) work too. The code only uses universal commands https://github.com/stefanrueger/urboot/blob/15ced5922bcc657b711eb3ba9a9f20fa92924a9a/src/urboot.c#L1445-L1449 I'd be surprised if a (standard) SPI flash memory wouldn't be able to cope with that.

documentation for this feature is relatively sparse

Correct. There isn't much beyond documentation of the make options about the DUAL option. You may be able to glean a bit more by checking out the comments in urboot.c.

I guess @MCUdude won't include pre-compiled dual-boot bootloaders per default, principally because a) the board needs to have SPI flash, and b) more importantly the bootloader needs to know the CS line of the attached SPI device (which if you don't know that in advance explodes the space of pre-compiled bootloaders). There are pre-compiled dual-boot bootloaders for some boards in the urboot.hex repository for the ATmega1284P and ATmega328P parts and the moteino, moteinomega, anarduino and ur* boards.

So, most likely, you'd need to make/compile your own dual-boot urboot bootloader. Good luck with testing and let me know how you get on.

Floessie commented 1 year ago

Thanks, Stefan!

I'd be surprised if a (standard) SPI flash memory wouldn't be able to cope with that.

Great! These are BTW the exact lines, I was staring on. The question came to my mind, when I checked the 25LC1024 commands and found only 0x20 missing. But nevermind, the SPI flash chips are cheaper anyway, albeit not PDIP for prototyping.

I guess @MCUdude won't include pre-compiled dual-boot bootloaders per default, principally because a) the board needs to have SPI flash, and b) more importantly the bootloader needs to know the CS line of the attached SPI device (which if you don't know that in advance explodes the space of pre-compiled bootloaders).

Yes, I read that in another discussion.

Anyway, classic AVRs are hard to find nowadays, and I'll switch to AVR64DD28 as my bread-and-butter controller.

So, most likely, you'd need to make/compile your own dual-boot urboot bootloader. Good luck with testing and let me know how you get on.

No problem.

Thanks again for your work and quick response!

Best, Flössie

stefanrueger commented 1 year ago

found only 0x20 missing

If your SPI EEPROM does not have a (4k) sector erase command it might have a page erase or a block erase? Best case would be that 0x20 can just be replaced with another erase command. Only the first few bytes on the SPI device need erasing after flashing the AVR to ensure the next reset won't program the AVR again.

PDIP for prototyping

Winbond should have PDIP packages for SPI flash, not? Other than that I've used break-out boards for 8-Pin SOIC parts.

winbond-break-out

DRSDavidSoft commented 10 months ago

@stefanrueger Thanks for having this functionality in Urboot! I'm going to design a PCB to test out this feature and was wondering if there is any requirement other than specifying the CS pin during make? I couldn't find any documentation on this.

Additionally, I had two questions:

  1. How would the bootloader detect that the program containing on the SPI flash is already copied onto the onboard flash, and avoid re-programming? Does it utilize a flag or something similar?
  2. Can I enter the bootloader using WDT, instead of tying the RESET pin to a GPIO pin and pulling it low? That would free up a pin. I know in the original Optiboot the reason for this was to avoid boot loops on WDT, but I was wondering if I could somehow set a register or the EEPROM to a value that would flag the bootloader not to jump to the application code directly.
stefanrueger commented 10 months ago

I'm going to design a PCB to test out this feature

Urboot expects HW pull-ups for the CS inputs of all other devices on the I2C bus (radio, sensors, ...); otherwise a floating CS pin of one of those devices could make it active during dual-boot and interfere with the SPI flash memory. If it's just for testing you can use some existing board and add an SPI break-out board (eg, one that's depicted above) with short wires.

requirement other than specifying the CS pin during make

Here two examples for creating a dual-boot bootloader for Anarduino and Moteino boards that you can buy:

$ make MCU=atmega328p URPROTOCOL=1 SFMCS=AtmelPD5 LED=AtmelPB1 DUAL=1 FRILLS=7 NAME=anarduino-dual
$ make MCU=atmega328p URPROTOCOL=1 SFMCS=AtmelPB0 LED=AtmelPB1 DUAL=1 FRILLS=7 NAME=moteino-dual

How would the bootloader detect that the program containing on the SPI flash is already copied onto the onboard flash

It doesn't. If the first few bytes of the SPI flash is a jmp or rjmp instruction (indicating a vector table of a sketch), the AVR flash below the bootloader is programmed from the external SPI flash. Once copied over, the first block of the SPI flash is deleted, which avoids re-programming.

Can I enter the bootloader using WDT, instead of tying the RESET pin to a GPIO pin and pulling it low?

Yes: the dual-boot part of the bootloader is entered from WDT, indeed. Every time a WDT happens, the external SPI flash is checked for existence of a program and, if so, burns that onto the AVR flash (and deletes the first block of the external SPI fash); if not then the bootloader jumps to the application. Pro-tip: your application should fill the external SPI flash from top to bottom, so that the vector table of the program is written last upon which it can issue a WDT to force re-flashing via the bootloader.

In contrast, pulling reset low will enter the "traditional" bootloader part that programs flash via connected serial I/O (just like normal urboot or optiboot). A dual-boot bootloader can do both (hence, dual).