Bootloader Relocation Challenges in ARM Cortex-M3: Absolute Addressing and Interrupt Vector Handling

Relocating a bootloader from Flash to RAM on an ARM Cortex-M3 processor, such as the STM32F103RB, presents several technical challenges. The primary issue revolves around the presence of absolute addresses in the compiled code, which complicates the relocation process. While the ARM Cortex-M3 architecture predominantly uses PC-relative addressing, certain sections of the code, particularly the interrupt vector table and literal pools, rely on absolute addresses. This behavior is exacerbated by the limited range of PC-relative addressing in Thumb-2 instructions, which is constrained to ±4095 bytes. Additionally, the bootloader’s use of interrupts for UART, CAN, and timers necessitates careful handling of the interrupt vector table during relocation.

The goal is to copy the bootloader from Flash (0x08000000 to 0x08003FFF) to RAM (0x20004000), update the interrupt vectors to reflect the new RAM addresses, and then jump to the SystemInit function in RAM. However, the presence of absolute addresses in the compiled code means that a straightforward memory copy operation is insufficient. These absolute addresses must be identified and adjusted to reflect the new RAM location. Furthermore, the interrupt vector table, which is typically located at the beginning of the Flash memory, must be relocated and updated to ensure that interrupts are correctly handled after the bootloader is moved to RAM.

Linker Script Configuration and Scatter Loading for Bootloader Relocation

One of the key tools for addressing the challenges of bootloader relocation is the linker script, particularly the scatter file in the Keil uVision IDE. The scatter file defines the memory layout of the application, specifying where different sections of the code and data should be placed in memory. By carefully configuring the scatter file, it is possible to control the placement of the bootloader code and data in both Flash and RAM, as well as generate symbols that indicate the start and end addresses of the bootloader sections.

The scatter file typically includes a load region (LR_IROM1) that defines the Flash memory area where the bootloader is initially stored, and an execution region (ER_IROM1) that specifies the Flash memory area where the code will execute. Additionally, a RAM region (RW_IRAM1) is defined for the execution of the bootloader in RAM. The scatter file also includes sections for reset handlers, root sections, and other code and data sections. By modifying the scatter file, it is possible to instruct the linker to generate symbols such as |Load$$bootloader$$Base| and |Image$$bootloader$$Length|, which can be used to determine the start and end addresses of the bootloader in Flash and RAM.

The __main function in the startup code plays a crucial role in the relocation process. This function is responsible for initializing the C runtime environment, including copying the RW data from Flash to RAM. By leveraging the scatter file and the __main function, it is possible to automate the relocation of the bootloader to RAM. However, this approach requires a deep understanding of the scatter file syntax and the behavior of the __main function.

Implementing Bootloader Relocation: Step-by-Step Guide

To successfully relocate the bootloader from Flash to RAM, the following steps should be taken:

  1. Modify the Scatter File: Update the scatter file to define the load and execution regions for the bootloader in both Flash and RAM. Ensure that the scatter file includes sections for the reset handler, root sections, and other necessary code and data sections. Generate symbols for the start and end addresses of the bootloader sections using the |Load$$bootloader$$Base| and |Image$$bootloader$$Length| syntax.

  2. Update the Startup Code: Modify the startup code to include a custom function that copies the bootloader from Flash to RAM. Use the symbols generated by the scatter file to determine the start and end addresses of the bootloader sections. Ensure that the custom function is called before the __main function to ensure that the bootloader is relocated before the C runtime environment is initialized.

  3. Adjust Absolute Addresses: Identify and adjust any absolute addresses in the bootloader code that reference Flash memory. This may involve modifying the interrupt vector table to reflect the new RAM addresses. Use the scatter file and linker-generated symbols to ensure that the absolute addresses are correctly updated.

  4. Handle Interrupts: Update the interrupt vector table to reflect the new RAM addresses. Ensure that the interrupt handlers are correctly mapped to the new addresses in RAM. This may involve modifying the startup code to update the vector table offset register (VTOR) to point to the new location of the interrupt vector table in RAM.

  5. Jump to the Relocated Bootloader: After the bootloader has been successfully relocated to RAM and the interrupt vector table has been updated, jump to the SystemInit function in RAM. Ensure that the stack pointer and program counter are correctly set to the new RAM addresses.

  6. Verify the Relocation: Use debugging tools to verify that the bootloader has been correctly relocated to RAM and that all absolute addresses have been adjusted. Ensure that interrupts are correctly handled and that the bootloader functions as expected in RAM.

By following these steps, it is possible to successfully relocate a bootloader from Flash to RAM on an ARM Cortex-M3 processor. However, this process requires a deep understanding of the linker script, scatter file syntax, and the behavior of the __main function. Additionally, careful attention must be paid to the handling of absolute addresses and the interrupt vector table to ensure that the bootloader functions correctly in its new location in RAM.

Conclusion

Relocating a bootloader from Flash to RAM on an ARM Cortex-M3 processor is a complex task that requires careful planning and execution. The presence of absolute addresses in the compiled code, combined with the limited range of PC-relative addressing in Thumb-2 instructions, presents significant challenges. However, by leveraging the scatter file and linker-generated symbols, it is possible to automate the relocation process and ensure that the bootloader functions correctly in RAM. Additionally, careful handling of the interrupt vector table and absolute addresses is essential to ensure that interrupts are correctly handled and that the bootloader functions as expected in its new location. With the right approach and a deep understanding of the underlying architecture, it is possible to successfully relocate a bootloader from Flash to RAM on an ARM Cortex-M3 processor.

Similar Posts

Leave a Reply

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