Apparently I’ve come up to a point, when I want to do firmware upgrades for my home automation ‘over-the-air’. Since I’m using nRF24L01 dongles, I decided to write a bootloader for that.
While my pet antares project is slowly progressing towards the 0.2-rc2 release (honestly, really slowly), I’ve added the nice and shiny RF24 library (A port of maniacbug’s arduino library to pure C with no arduino dependences) to interface with nrf24L01 2.4Ghz dongles. I also fixed a few nasty race conditions out there on the way, but those are totally a different story.
So, what’s inside:
- Portable: Supports AVR out of the box, all other MCUs that are supported by antares can be easily added (STM32 is the next target).
- Hardware or software SPI for avr: you choose
- Configurable bootloader timeout, leave condition, etc.
- Secure: Bootloader can easily be disabled by a jumper.
- Easy: state-of-the-art menuconfig with all the options you might ever want to change.
Small. Bloated. Fits into 4KB (AVR) with all debugging disabled. I tried to make it as small as possible, playing with gcc flags you don’t want to know about, but this looks pretty much like the hard limit. Unless I want to make the code an unreadable, unportable assembly mess
- Reliable: Handles most of the cases when data, ack, or both are lost.
- Extensible: You can define your own partitions with your own memory programming routines without ever having to dive into the core of the bootloader or the protocol.
- Even if you decide to do so, the core state machine is dumb and simple and fits into less than 150 lines of code.
- OpenSource: GPLv2 FTW!
Okay, what about the programming dongle? For now I use my uISP with nRF24L01 mounted on top. Not the best solution, but works good enough. I relayed most of the RF24 API via usb, so the actual protocol handling is done on the PC side for added flexibility.
nrf24l01 are quite fast things, 2MBPS FTW! With a proper dongle the flash programming speed would be the bottleneck. For the sake of simplicity and ease of porting I didn’t make use of the IRQ line, so this might slow us down just a little bit. You know, doing things async is always faster. Still, flash or eeprom writing speed is not the bottleneck right now. VUSB’s performance is. For now it is sufficient for small things, but I really think to make a proper STM32-based USB dongle for that in future with proper buffering on the dongle side. This promises to be waaay faster, than the current slowpoke implementation. Here’s a little bit of those sucky performance measurements:
necromant@ilwyn:~/Dev/antares-playground/rf24-slave/rf24tool$ time ./rf24tool --part flash --file out.bin --read nRF24L01 over-the-air programmer (c) Necromant 2013-2014 <andrew [at] ncrmnt.org> Local Address: 00:01:02:03:03 Remote Address: 00:01:02:03:04 Channel: 76 Rate: 2MBPS PA Level: Max Waiting for target....FOUND! Target: rfboot-test Endianness: little Number of partitions: 2 0. eeprom size 1024 iosize 16 pad 0 1. flash size 32768 iosize 16 pad 128 Reading partition flash: 7ff0 32768/32768 cont 6 Done! Have a nice day! real 0m27.870s user 0m0.016s sys 0m0.072s
Say hello to the dialup speeds, did you miss ‘em?
Anyway, here goes the tasty stuff, published under GPLv2 License with ObDev’s exception:
Want to compile and use – See README.compiling
Want to start hacking on the bootloader? Fork on github, read the README.HACKING and don’t forget to send your merge requests.
Want to help out with something else (stm32-based dongle?), or just submit your own tool that works with the bootloader so that I can link to it? See ‘contact’ for my email.