Reducing the bootloader’s ROM footprint

The recommended way to get started with the OpenBLT bootloader is to first find a demo program, which is based on a microcontroller similar to the one in your system. Once you have gotten familiar with your selected demo bootloader, you can port it to your own system. The demo bootloader most likely supports more functionality than needed. This article explains how to scale down the bootloader configuration, with the goal of reducing the bootloader’s ROM footprint.

The example described in this article, references the Olimex STM32-P103 demo programs. These programs are configured for building with the GNU ARM Embedded toolchain and a Makefile. They were taken from OpenBLT version 1.5.0. The configuration of the default demo bootloader supports quite a bit: Firmware updates via UART, CAN and SD-card, resulting in a ROM footprint of about 20 kb. This article demonstrate how to reduce the ROM footprint of this demo bootloader from 20 kb to 4 kb.

Bootloader reconfiguration

Step 1

The first step in reducing the ROM footprint of the bootloader is by disabling those firmware update communication interfaces that are not needed. By default, the Olimex STM32-P103 demo bootloader supports firmware updates via UART, CAN and SD-card. In this article the assumption is made that only firmware updates via UART is desired. The same logic applies if you prefer to perform firmware updates via a different communication interface.

Open configuration header-file “blt_conf.h” in your code editor of choice. This file is located in directory: “./Target/Demo/ARMCM3_STM32F1_Olimex_STM32P103_GCC/Boot/”.

To only enable firmware updates via UART, locate the following lines:

#define BOOT_COM_CAN_ENABLE             (1)
#define BOOT_COM_UART_ENABLE            (1)
#define BOOT_FILE_SYS_ENABLE            (1)

And change them to:

#define BOOT_COM_CAN_ENABLE             (0)
#define BOOT_COM_UART_ENABLE            (1)
#define BOOT_FILE_SYS_ENABLE            (0)

After saving the changed configuration header-file “blt_conf.h” and rebuilding the demo bootloader (command: “make clean all”), the ROM size is now 4624 + 108 = 4732 bytes.

Step 2

Increasing the optimization level of the compiler can result in a further reduction of the bootloader’s ROM footprint. In this example the GNU ARM Embedded toolchain and a Makefile handle the building of the bootloader. Open file “makefile” in your preferred text editor. This file is located in the same directory as the “blt_conf.h” configuration header file. Locate the line:

OPTFLAGS    = -Og

And change it to:

OPTFLAGS    = -Os

The function of the “-Os” compiler optimization level is to reduce the code size of the object-file generated during compilation, which is exactly what we want. After saving the changed Makefile and rebuilding the demo bootloader, the ROM size is now 3900 + 108 = 4008 bytes.

Flash layout table update

The bootloader’s flash layout table manages which sectors of the flash memory device can be modified by the bootloader. It is important that the sectors where the bootloader itself resides, are not present in the flash layout table. Otherwise, the bootloader itself could be erased, which is something to prevent at all times.

After reducing the bootloader´s ROM footprint, more flash memory becomes available for the user program that is programmed by the bootloader. The flash layout table needs an update to make sure the bootloader can erase and program the flash memory that is now available to the user program.

The flash layout table is implemented as an array called flashLayout[]. It is part of the bootloader’s flash driver.

Method 1

Open the flash driver source-file “flash.c” in your code editor of choice. For an STM32F1 based microcontroller, this file is located in directory: “./Target/Source/ARMCM3_STM32F1/”.

Locate the following lines:

static const tFlashSector flashLayout[] =
{
  /* { 0x08000000, 0x02000,  0},    flash sector  0 - reserved for bootloader */
  /* { 0x08002000, 0x02000,  1},    flash sector  1 - reserved for bootloader */
  /* { 0x08004000, 0x02000,  2},    flash sector  2 - reserved for bootloader */
  { 0x08006000, 0x02000,  3},    /* flash sector  3 - 8kb                     */

And change them to:

static const tFlashSector flashLayout[] =
{
  /* { 0x08000000, 0x02000,  0},    flash sector  0 - reserved for bootloader */
  { 0x08002000, 0x02000,  1},    /* flash sector  1 - 8kb                     */
  { 0x08004000, 0x02000,  2},    /* flash sector  2 - 8kb                     */
  { 0x08006000, 0x02000,  3},    /* flash sector  3 - 8kb                     */

This effectively shrinks the flash memory that is reserved for the bootloader from 24 kb to 8 kb. After making this change, save the “flash.c” file and build the bootloader. The ROM footprint reduced bootloader is now all done.

Note that the entries in the flash layout table are aligned to the segments of the actual flash memory device hardware. It is therefore not advised to change the segment sizes, as these are hardware-defined. Only change which lines are commented out or not. For an STM32F1 microcontroller this means that the smallest size that can be reserved for the bootloader is 8 kb, even though the ROM footprint reduced bootloader would currently fit in 4 kb.

Method 2

There is an alternative method for changing the flash layout table. The bootloader supports a feature for overriding the flash driver’s flash layout table with one specified in an external source-file called “flash_layout.c”. This enables you to update the flash layout table, without having to modify anything in the source code of the bootloader itself. The benefit of this method is that it lowers the effort of updating the bootloader to a new version in the future, because you won’t have to merge your changes to the flash layout table.

Here is the procedure for updating the flash layout table, when you prefer this method. Open configuration header-file “blt_conf.h” in your code editor of choice and add the following macro:

#define BOOT_FLASH_CUSTOM_LAYOUT_ENABLE (1)

Next, create a new source-file called “flash_layout.c” inside the application part of the bootloader, e.g. “./Target/Demo/ARMCM3_STM32F1_Olimex_STM32P103_GCC/Boot/”. You can copy over the flashLayout[] array from the flash driver and use it as a foundation. The Olimex STM32-P103 has a total of 128 kb and the first 8 kb should be reserved for the bootloader. This results in the following contents for “flash_layout.c”:

static const tFlashSector flashLayout[] =
{
  /* { 0x08000000, 0x02000,  0},    flash sector  0 - reserved for bootloader */
  { 0x08002000, 0x02000,  1},    /* flash sector  1 - 8kb                     */
  { 0x08004000, 0x02000,  2},    /* flash sector  2 - 8kb                     */
  { 0x08006000, 0x02000,  3},    /* flash sector  3 - 8kb                     */
  { 0x08008000, 0x02000,  4},    /* flash sector  4 - 8kb                     */
  { 0x0800A000, 0x02000,  5},    /* flash sector  5 - 8kb                     */
  { 0x0800C000, 0x02000,  6},    /* flash sector  6 - 8kb                     */
  { 0x0800E000, 0x02000,  7},    /* flash sector  7 - 8kb                     */
  { 0x08010000, 0x02000,  8},    /* flash sector  8 - 8kb                     */
  { 0x08012000, 0x02000,  9},    /* flash sector  9 - 8kb                     */
  { 0x08014000, 0x02000, 10},    /* flash sector 10 - 8kb                     */
  { 0x08016000, 0x02000, 11},    /* flash sector 11 - 8kb                     */
  { 0x08018000, 0x02000, 12},    /* flash sector 12 - 8kb                     */
  { 0x0801A000, 0x02000, 13},    /* flash sector 13 - 8kb                     */
  { 0x0801C000, 0x02000, 14},    /* flash sector 14 - 8kb                     */
  { 0x0801E000, 0x02000, 15},    /* flash sector 15 - 8kb                     */
};

After adding this flashLayout[]array, save the “flash_layout.c” file and build the bootloader. The ROM footprint reduced bootloader is now all done. Note that there is no need to compile the “flash_layout.c” source-file when building the bootloader. The flash driver automatically includes it. In fact, it would result in compile errors if you would try to individually compile the “flash_layout.c” source-file.

User program reconfiguration

Now that the bootloader’s ROM footprint has been reduced, there is one last step to take to make it all work. In the previous section, the flash memory reserved for the bootloader was shrunk from 24 kb to 8 kb. These extra 16 kb are now available to the user program. To make use of this, the start address of the user program needs to be moved 16 kb as well.

The Olimex STM32-P103 demo user program is by default configured to start at memory address 0x08006000. This should be changed to 0x08002000. This change is made in the linker descriptor file of the user program. For the Olimex STM32-P103 demo user program, this is file “stm32f103rb_flash.ld”, which can be found in directory: “./Target/Demo/ARMCM3_STM32F1_Olimex_STM32P103_GCC/Prog”.
Open the “stm32f103rb_flash.ld” linker descriptor file and locate the following line:

ROM  (rx) : ORIGIN = 0x08006000, LENGTH = 128K-24K

Change it to:

ROM  (rx) : ORIGIN = 0x08002000, LENGTH = 128K-8K

This moves the start address of the user program to 0x08002000and makes 16 kb more flash memory available to the user program. Finish everything off by saving the changes and rebuilding the user program.

Conclusion

This article outlined the steps for reducing the bootloader’s ROM footprint, including the reconfiguration of the user program to make use of the newly available flash memory.

To explain these steps in more detail, the Olimex STM32-P103 demo programs were taken to show you how the ROM footprint reduction is achieved. In the example mentioned in this article, the bootloader’s ROM footprint could be reduced from 20488 bytes to 4008 bytes (-80%).

Although the Olimex STM32-P103 demo programs were used as an example, the described steps apply to all OpenBLT based bootloaders.

 

Follow and like us:
RSS
YouTube
YouTube
LinkedIn
This entry was posted in OpenBLT and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

two + four =