The idea started few months ago when I had to create a RF node for my farm (I'm growing hazel trees). Because I'm pretty far from my field (about 200 km), I have to work remotely a lot, currently I'm concerned with the monitoring of the area and also I need useful data: soil moisture, air and soil temperature and so on in order to know when to intervene locally and to water the plants (the hazel trees are not pretentious plants, but considering the global warming it's critical to do this when the temperatures are going high).
So I created a RF node which is using the nrf24L01 chip and an AVR microcontroller, then this is connecting with a gateway (raspberry pi + nrf24L01) to establish the internet access. I thought it would be a cool idea to program my modules remotely, so this will allow to update my software without being physically there. That was the moment when I realized that we need a solid software that can fit multiple hardware and provides to the user a proper interface to access the RF communication and also provides support for self programming using the RF communication. Of course one solution is to use NRF5 series which have OTA support (Bluetooth or NFC) and other nice features, but also the price is higher and sometimes we need something light and easy to program or use especially when your code is wrote for AVR microcontrollers (anyway, I can integrate the NRF5 hardware in my software too).
We started to work in November 2019, the team name is CodingNight (each of us is working 8 hours per day as software engineers, so any free time is in the evening when we crack open few beers while coding). The first goal was to make a concept proof of this software, so the main functionality was the OTA update. To achieve this we started to write the bootloader and nrf24L01 radio library, also I had to create a working environment for AVR - we're using the Atmel Studio 7 for development and our current hardware is a ATmega16 microcontroller.
The first thing was to define the flash layout, so considering that our microcontroller has just 16kB of memory and the maximum BLS size is 2kB, we had to find a way to fit the radio library in this small space - it was almost impossible to have a minimal working library and also a functional bootloader in this given space. The solution was to use the user space for the radio library, then we thought that the same code can be used by the user application as well, why to duplicate some code in flash memory when we can share this between the bootloader and the application? Yes, this will affect the robustness of the bootloader, in practice the bootloader should be a small piece of program that is well written and it doesn't require frequent updates and the most important, it should't malfunction, considering that it is a very basic functionality of the microcontroller. In spite of this, we still considered that it worth to create this bootloader because later we can add some functionality to prevent problems (some recovery code to a stable version, etc).
After I finished the radio library implementation - I tried to keep it as light I could but it still resulted in almost 3.2kB of code using O1 optimization - finally I was able to define the flash layout for the ATmega16, and it looks like this:
Currently we're using 2kB just for self programming APIs, initialization code for radio library and flashing routine - the hand-shacking protocol between bootloader and flashing tool. The programming tool is a python script that just takes the application HEX file and split it down in radio packages and send it to a specific RF node. The programmer hardware consists of a RF node and a serial to USB device, so this allow you to run the python script from Linux / Windows.
I allocated 4kB for radio library and I placed this in user space - the BLS section is defined by microcontroller's fuse bits,...Read more »