This has been a long time coming, and the recent Elektro:camp meet-up has finally pushed me to figure out the remaining details and get it all working (on foam board!):
Bottom middle is a JeeLink, which acts as a “boot server” for the other two nodes. The JeeNode USB on the left and the JeeNode SMD on the right (with AA Power Board) both now have a new boot loader installed, called JeeBoot, which supports over-the-air uploading via the RFM12B wireless module.
The check for new firmware happens when pressing reset on a remote node (not on power-up!). This mechanism is already quite secure, since you need physical access to the node to re-flash it. Real authentication could be added later.
The whole JeeBoot loader is currently a mere 1.5 KB, including a custom version of the RF12 driver code. Like every ATmega boot loader, it is stored in the upper part of flash memory and cannot be damaged by sketches running amok. The code does not yet include proper retry logic and better low-power modes while waiting for incoming data, but that should fit in the remaining 0.5 KB. The boot loader could be expanded to 4 KB if need be, but right now this thing is small enough to fit even in an ATmega168, with plenty of room left for a decent sketch.
The boot algorithm is a bit unconventional. The mechanism is driven entirely from the remote nodes, with the central server merely listening and responding to incoming requests in a state-less fashion. This approach should offer better support for low-power scenarios. If no new code is available, or if the server does not respond quickly, the remote node continues by launching the current sketch. If the current sketch does not match its stored size and CRC (perhaps because of an incomplete or failed previous upload attempt), then the node retries until it has a valid sketch. That last part hasn’t been fully implemented yet.
The boot server node can be a JeeLink, which has enough memory on board to store different sketches for different remote nodes (not all of them need to be running the same code). But it could also be another RFM12B-based setup, such as a small Linux box or PC.
This first test server has just two fixed tiny sketches built in: fast blink and slow blink. It alternately sends either one or the other, which is enough to verify that the process works. Each time any node is reset, it’ll be updated with one of these two sketches. A far more elaborate server sketch will be needed for a full-fledged over-the-air updatable WSN.
But hey, it’s a start, and the hardest part is now done!
Great work jcw! This is a feature I’m really looking forward too.
Now I have to add a reset button to all my sensor nodes :-)
How long does it take to upload something like a roomnode sketch? It would also be great if it’s possible to initiate such a reset using software. Do you think this will be possible?
I think this can always be done in your custom sketch by activating the watchdog (if not activated before) and use an RF command to force the sketch into an endless while() loop.
Something like…
wdt_enable(WDTO_2S); while(1);
Also, have a look at https://github.com/codebendercc Their Bootloader features ethernet remote upload.
Wow, just.. wow. Great work! This will definitely make our life easier, updating firmware without removing nodes from all over the house. Just a reset button and a central repository with the appropriate sketches. And maybe, if we’ve a pin and some parts left to spare, add some over-the-air resetting as well?
Fantastic ! And what a coincidence. I have just started work on an RF bootloader. Now I will stop this for a while and first look into your solution. It seems better for me to stick to a ‘standard’ than always roll my own thing.
BR, Jörg.
PS: and yes, a reset over the air is essential for those nodes hidden in hard to reach places…
You can build in a reset over-the-air into your standard code if need be, but I don’t think it’s wise to build it in by default, because all kinds of security aspects come into play…
Nice work JCW! Now all we need is another post explaining your mechanism and decent server software :P
Yes, but if security is an issue, than just use a secret ‘magic number’ to force a reset or do not use this feature at all. For a temperature measuring node (or mostly all measuring nodes), security should not be a problem.
But as you said (parallel to my answer above) this is all in the hands of your custom sketch.
But it can still be irritating, if some prankster decides to flood the band, or send off deliberately confusing packets. They could do that from outside the house too, but then it would be jamming – which is illegal, I think.
The solution will be to build a custom reset function in the running sketch, i.e. do something you design yourself to make the node go into self-update mode. That way, security can be as high as you choose, while still supporting the physical reset if your sketch fails to get into self-update.
I spent some time looking into authentication mechanisms, but they all eat up memory, and they probably still wouldn’t be really secure since I’m no Bruce Schneier. With the reset button, it’s secure out of the box (I think).
Note that you can’t get yourself into an self-update state by forcing a watchdog reset, it really has to be a hardware reset. But I’m hoping to find a way to jump directly to the boot loader in some way, to get it to start the self-update check/sequence anyway.
Lots of details to work out. I’ll share the code once it is slightly more stable – no point trying it out while it’s really still changing in major ways, especially the little protocol used for this. Sorry to keep you waiting – should only be a matter of days.
‘Note that you can’t get yourself into an self-update state by forcing a watchdog reset, it really has to be a hardware reset.’
Is there really a difference between Watchdog reset and Power-On or external pin reset? I thought they would all end up in vector 1 at 0x0000 (or Boot reset address if BOOTRST is 0).
But as you said, you can also simply jump to the start of the bootloader section.
Yes, they all act as resets, but the boot loader specifically checks some status bits when entered. This way, neither a wicked neighbour cycling power to your house nor one trying to force your nodes into watchdog failures will let him (her?) enter self-upload state. Not truly an issue, but this sort of thing gives me more confidence that the solution is inherently secure. The weakest link, as they say…
Ah, ok. So this is a software feature in the bootloader code and not a ‘hard'(ware) limitation!
So for my ‘temperature measuring’ node I could decide to have the over-the-air reset enabled and for safety critical nodes this would be disabled.
Thank’s a lot !! I’m looking forward to test and implement this great new feature.
Very exciting…! This is a big leap to get a real sensor network going using JeeNodes! Chapeau! :)
Early preview – https://git.jeelabs.org/jeeboot (no docs yet, sorry).