Featured image of post Understanding Vector Table Relocation and Memory Mapping

Understanding Vector Table Relocation and Memory Mapping

Learn how to implement vector table relocation and memory mapping in a bootloader for the STM32F4 microcontroller. Understand why vector table relocation is essential for correct interrupt handling and system stability, and discover how to properly configure it within our bootloader.

Recap: What We Did Last Time

In the previous blog, we built a minimal bootloader that:

  1. Initialized the microcontroller peripherals.
  2. Indicated bootloader activity by blinking an LED.
  3. Jumped to the main application located at a specific address in the flash memory (e.g., 0x08004000).

While this was a good starting point, it didn’t address some critical elements required for a reliable bootloader.

What Was Missing?

Vector Table Relocation and Memory Mapping

One of the most important aspects we didn’t cover was vector table relocation and memory mapping. The STM32F4 microcontroller needs to know where to find the vector table containing pointers to interrupt handlers. If the main application starts at a different memory location than the bootloader, we must relocate the vector table to the correct address. Without this step, interrupts and exceptions won’t be handled correctly, potentially causing the system to crash.

Dynamic Vector Table Management

We also didn’t cover how to handle multiple applications or firmware versions, which requires dynamic relocation of the vector table based on application metadata.

Validation and Error Handling

The initial bootloader example didn’t include any mechanisms for validating the vector table or handling errors if relocation fails. These steps are crucial for ensuring that the bootloader doesn’t hand over control to a corrupted or invalid application.

Why Relocate the Vector Table in STM32F4?

The STM32F4 microcontroller starts execution with a vector table located at the beginning of flash memory (0x08000000). This vector table contains pointers to interrupt handlers and the reset vector. If our application is located at a different address (e.g., 0x08004000), the microcontroller will not automatically find the new vector table. Explicitly relocating the vector table ensures that interrupts and exceptions are managed correctly after the bootloader finishes, preventing system crashes and enhancing stability.

Steps to Relocate the Vector Table in STM32F4

To properly relocate the vector table, follow these steps:

Step 1: Define the Application Start Address

Define where our main application starts in flash memory:

1
#define APP_ADDRESS 0x08004000  // Address where the main application begins

This address indicates where the main application is located. In this example, the application starts at 0x08004000.

Step 2: Relocate the Vector Table

Adjust the Vector Table Offset Register (VTOR) to point to the new vector table location:

1
2
3
4
void Bootloader_RelocateVectorTable(void) {
    // Set VTOR to point to the base address of the application's vector table
    SCB->VTOR = APP_ADDRESS;
}

This function updates the VTOR to APP_ADDRESS, directing the microcontroller to use the vector table at the start of the main application.

Step 3: Integrate Vector Table Relocation into the Bootloader

Include the vector table relocation function in our bootloader code:

1
2
3
4
5
6
7
8
int main(void) {
    Bootloader_Init();
    Bootloader_BlinkLED(); // Optional: Indicate bootloader activity
    Bootloader_RelocateVectorTable(); // Relocate the vector table
    Bootloader_JumpToApp(); // Transfer control to the main application

    while (1); // This point should never be reached
}

Visualizing Memory Mapping for STM32F4

This diagram illustrates the memory layout, showing the bootloader at 0x08000000 and the application starting at 0x08004000. After the bootloader completes, it updates the VTOR to the application’s start address, ensuring proper handling of interrupts by the application.

Simplified Memory Layout for STM32F4

let’s clarify the addresses involved:

  • Old Address of VTOR:

    When the microcontroller starts up or resets, it uses the default vector table located at 0x08000000 . This is where the VTOR points to initially. This address corresponds to the start of the bootloader in our case.

  • New Address of VTOR:

    After the bootloader has completed its tasks and is ready to transfer control to the main application, it updates the VTOR to point to the base address of the main application’s vector table. For our setup, this new address is 0x08004000`. This is where the vector table of the main application starts.

Benefits of Vector Table Relocation

  1. Accurate Interrupt Handling: Ensures that our application’s interrupt service routines (ISRs) are correctly invoked.
  2. System Stability: Prevents crashes caused by unhandled interrupts.
  3. Modular Firmware Design: Facilitates easier updates and debugging by allowing each application to manage its vector table.

Additional Considerations for Bootloader Design

To enhance our bootloader, consider these additional aspects:

Handling Multiple Applications

For managing multiple applications, we can store metadata about each application’s vector table address. This allows dynamic relocation based on the selected application:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#define METADATA_ADDRESS 0x08008000  // Address for application metadata

uint32_t Read_App_VectorTable_Address(void) {
    return *(volatile uint32_t*)METADATA_ADDRESS;  // Read vector table address from metadata
}

void Bootloader_RelocateVectorTable(void) {
    uint32_t app_address = Read_App_VectorTable_Address();
    if (Validate_VectorTable(app_address)) {
        SCB->VTOR = app_address;  // Update VTOR to the correct vector table address
    } else {
        // Handle invalid vector table scenario
    }
}

Validation and Error Handling

Before relocating the vector table, validate the address to ensure it’s correct:

  1. Vector Table Validation: Check if the address is within the acceptable memory range and properly formatted.

    1
    2
    3
    4
    5
    6
    
    bool Validate_VectorTable(uint32_t address) {
        if (address < 0x08000000 || address > 0x080FFFFF) {
            return false;
        }
        return true;  // Implement additional validation as needed
    }
    
  2. Error Handling: Implement error handling to manage situations where vector table relocation fails, such as reverting to a default application or indicating an error state.

    1
    2
    3
    4
    5
    6
    7
    8
    
    void Bootloader_RelocateVectorTable(void) {
        uint32_t app_address = Read_App_VectorTable_Address();
        if (Validate_VectorTable(app_address)) {
            SCB->VTOR = app_address;  // Relocate vector table
        } else {
            // Handle relocation failure
        }
    }
    

Conclusion and What’s Next?

Relocating the vector table is a crucial step for any STM32F4 bootloader. Properly configuring the VTOR ensures that our application can manage interrupts and exceptions effectively, leading to a stable and reliable system. This technique is foundational for more advanced bootloader features, such as secure booting or remote firmware updates.

To further our knowledge and build on this guide, revisit the previous blog post and continue exploring ways to refine our bootloader project.

What’s Coming Next?

In the next chapter, we’ll dive deeper into how to secure our bootloader. We will cover various security measures, such as implementing cryptographic checks, using hardware security features, and designing a secure firmware update process. These steps are essential to protect our embedded system against unauthorized access and tampering.

Stay tuned to learn how to enhance the security of our bootloader and create a more robust and secure embedded system!

References and Further Reading

Mastering vector table relocation and memory mapping is essential for developing sophisticated and reliable embedded systems. Keep following for more in-depth content!

Built with Hugo
Theme Stack designed by Jimmy