STM32F2 MCUs use advanced 90 nm NVM process technology with an adaptive real-time memory accelerator
Over the past few years, microcontrollers have become an essential part of our daily lives. You may not notice it, but it's under the hood and doing some minimalistic tasks to improve our everyday lives. From a simple 8-bit chip that controls devices like our smart bulb and toasters to those powerful 32-bit Digital Signal Processors (DSP) in our TVs and set-top boxes, which enriches us with digital media and entertainment. Without microcontrollers, our lives would not only be less entertaining, but it will definitely lose the control that we enjoy so much. With the increasing demand increases the development of small microcontroller-based products, which is why Billions, not millions of microcontroller units, are sold every year.
Now the question is, what happens when billions of microcontroller-based products are manufactured and sold, and a firmware upgrade becomes the top priority? Does every sold unit need to be returned to the manufacturer every time there is a need for a firmware upgrade? The obvious answer to this question is absolutely not! And this is one of the most important reasons why a microcontroller-based system is shipped with a bootloader on board.
A bootloader is an application whose primary objective is to upgrade/modify system software without the intervention of specialized firmware upgrade tools. Bootloaders can have many functionalities, but it's mainly used to manage the application. They can also utilize different protocols such as UART, CAN, I2C, I2S, Ethernet, or USB to establish communication and initial a firmware upgrade. A good example would be the bootloader in the Arduino board, which is configured to flash the application software in the flash memory of the ATMega chip.
Understanding the Bootloader System
Bootloaders can come in many sizes and can be differentiated by what type of task they execute, but in general, the operation of a bootloader is relatively standard. There are three crucial parts in any bootloader: branching code, on startup, it decides whether to execute the bootloader code or the application code. This is done by checking a GPIO pin at start-up; however, such methodologies are used by manufacturers and developers. In a more complex system, the bootloader loads itself to the memory along with the application code, then it checks for initial parameters and system integrity. Once that's done, it goes back to executing the application code. This is why many bootloaders contain the branching code.
Even when the application is running, it's so designed that it can request a firmware upgrade, after which it takes care of the necessary system clean-ups; once that is done, it soft-resets the chip by putting known values to the watchdog register. Additionally, the application puts out all the necessary instructions for the branching code to put the device on bootloader mode.
Now when the bootloader loads into the memory, it starts initializing basic instruction and peripherals to prepare for a firmware upgrade. The peripherals typically are system clocks, interrupts and communication channels, and schedulers. These allow the bootloader to accept instruction from outside, and it starts the upgrade process; once done, it soft-resets the chip, and when it boots up again, it goes to the normal operation mode.
Let's conclude our article by gaining a little bit of knowledge about memory structure and its programming. To do this, we will take an example of an AVR microcontroller, but before that, let's clear out some specific terms which you may or may not be aware of. Every type of microcontroller comes with a non-volatile memory inbuilt that is used to store the program. The most commonly used memory is known as flash memory. It's broken down into different smaller sections. The smallest section of the process is referred to as a page. Pages combined and make a memory structure known as a sector. Sectors are arranged to form larger structures known as blocks. Every microcontroller is different in terms of how these blocks can be manipulated. But most microcontrollers will allow you to write a single byte at a time.
Bootloader in AVR:
An AVR comes with a memory that is divided into two sections, one application, one bootloader section. The application section contains application-specific code, and the bootloader section can contain a different variety of bootloaders. In an AVR, this section can be configured by setting up the fuses. We can set the required bootloader space as our requirements or set it to be used for application code. The flowchart below will give you a better idea about how data from UART is written into the memory of the AVR.
The above flow chart shows what happens when an AVR enters into the bootloader. First, it erases the page memory and gets new page content from UART, and then it fills the page buffer. After that is written, it waits for more pages from UART; If a new page is available, the process starts once again; if not, the program enters to the RWW (Read While Write) section and finishes the operation. This is an oversimplified version of the bootloader operation. If you want to learn more about the topic, you can refer to the self-programming guide by Microchip Technologies.