A bootloader is a light-weight application that manages the boot and update process of a microcontroller-based product. The bootloader is used to authenticate and verify existing application images and new images that are part of the firmware update process. While a bootloader is typically written as a baremetal application, if the start-up needs are sophisticated enough, a developer might consider integrating an RTOS in a bootloader. In this post, we will explore several tips for building a bootloader using an RTOS along with the advantages and disadvantages.A bootloader is a light-weight application that manages the boot and update process of a microcontroller-based product. The bootloader is used to authenticate and verify existing application images and new images that are part of the… Click To Tweet
Before we begin, let me start by setting how often I have seen this done. Over the last decade, I’ve written over 20+ bootloaders. Out of all those bootloaders, I’ve had two where I’ve used an RTOS in the bootloader. These two projects were the exceptions where the customer had some “special sauce” that they wanted in the bootloader for their application. The developers managing those features wanted an RTOS to simplify things. What’s interesting to keep in mind is that some of these considerations will also apply to issues with using an RTOS on a multicore microcontroller.
RTOS in a Bootloader Consideration #1 – Flash Usage
A typical real-time operating system will use somewhere between 20 kilobytes and 32 kilobytes of flash storage space. On a modern microcontroller with 1 megabyte of flash space, it’s hardly even a consideration; However, on a resource constrained device where there may only be 64 kilobytes or 128 kilobytes of flash memory, integrating an RTOS with the bootloader may seem like it is not an option. The reason is that the RTOS with be integrated twice and use twice as much flash memory.A simple trick to avoid program duplication when using an #RTOS in a #bootloader is to put the RTOS in its own section. The bootloader and application code can then link to one RTOS library. Click To Tweet
Obviously, we want to minimize code duplication. There is a simple trick that developers can use to avoid the duplication. Instead of pulling the RTOS into the bootloader, compile the RTOS as a library. With the RTOS compiled as a library, modify the linker file for the bootloader and the application to place the RTOS library into the same area of flash memory. Both the bootloader and the application will be able to access the RTOS, but they will be sharing it instead of having their own copy.
Using an RTOS in your bootloader and your application code will increase the complexity of certain pieces of your system. For example, when I am debugging my system, I need to make sure that the RTOS library is loaded into the appropriate memory regions. I may need to adjust my programming parameters so that the RTOS section is not erased. I might even need to program the RTOS separately depending on the capability of the tools that I am using.
RTOS in a Bootloader Consideration #2 – Increased System Complexity
Additional complexity can also occur with the boot process. When I load an RTOS into memory from the bootloader and start to run the code, I’ve dramatically changed the state of the processor, memory, and the onboard peripherals. If we decide to jump to the application, we typically want to make the processor appear to the application like the processor just started up. Undoing everything that the RTOS did to the processor may be impossible. Which means we must manage how to successfully pass the CPU cleanly to the application code. This activity is not necessarily trivial.
There may be other complexities that come into play such as managing the boot time. With an RTOS, there may be a slight increase in boot time. It’s probably minimal, but something to consider.
RTOS in a Bootloader Consideration #3 – A Frozen RTOS Version
When the RTOS is integrated into the application code, we can update our RTOS as part of the firmware update process. If the RTOS is being used by both the application and the bootloader, it becomes much more complex and difficult to update the RTOS to a new version. Most systems will just freeze the RTOS version. That might be okay; however, what if there is a bug in the RTOS that later needs to be fixed? Now a service technician needs to get physical access to the system.
Developers need to carefully evaluate whether using a frozen RTOS version for their application is okay or not. For a space system or medical device, this might be preferred anyways. For a consumer electronics device where the RTOS closely integrates to a TCP/IP stack or other vulnerable libraries, that may not be preferable. You’ll have to decide what your own risk tolerance is.
It isn’t very common to write a bootloader that uses an RTOS. It can be done, and there can be advantages to it depending on your application. However, using an RTOS in the bootloader usually adds additional complexity to the system. The complexity comes from adjustments that must be made to program the device, to debug it, how the memory map is set up, and the system boot times. We’ve seen that there are adjustments that can be made to mitigate these. At the end of the day, you need to ask yourself the following questions:
- Will using an RTOS simplify maintenance?
- What benefits does the bootloader get from using an RTOS?
- Are the complexities worth the value that is provided long-term?
If you can justify the RTOS use with these questions, then it might be a good idea to integrate an RTOS with your bootloader.