Booting a Cortex-M1 processor with an RTX real-time operating system (RTOS) application requires careful configuration of the processor’s boot sequence and memory layout. This process allows an RTX application to be remotely updated without having to re-flash the entire processor firmware image.
Overview of Cortex-M1 Boot Process
The Cortex-M1 boot process consists of several stages:
- Processor reset – The processor comes out of reset and loads the stack pointer and vector table base address from fixed locations in flash memory.
- Bootloader code execution – The reset vector points to the start of the bootloader code which executes first.
- Application code execution – The bootloader code will configure the processor and then jump to the start of the application code.
To enable bootloading of an RTX RTOS application, the bootloader must be configured to know where the application image is located in flash memory. This allows it to jump to the correct application entry point after the boot process.
Configuring the Bootloader
Several steps are required to configure the Cortex-M1 bootloader for bootloading an RTX application:
- Set aside a separate flash memory region for the bootloader code. This could be the lowest addresses in flash for example.
- Set aside another flash region for storing the RTX application image. This will contain the .text, .data, .bss etc sections.
- Implement logic in the bootloader to check for the presence of a valid application image in the flash application region.
- If a valid image is found, configure the vector table and memory regions for the application.
- Jump to the application entry point to begin execution.
Some key considerations when implementing the bootloader logic:
- The bootloader must not overwrite the application region on startup.
- Flash regions must not overlap between the bootloader and application image.
- The processor vector table must be reconfigured by the bootloader for the application.
- SRAM usage must be coordinated between the bootloader and application.
Structuring the Flash Memory Layout
A sample flash memory layout which supports bootloading might look like: +————————–+ | Bootloader | 0x00000000 +————————–+ | | | | | | | | +————————–+ | .text | 0x00020000 +————————–+ | .data | +————————–+ | .bss | +————————–+
Here the bootloader code occupies the lower 32KB of flash from 0x00000000 to 0x00007FFF.
The application .text, .data and .bss sections are placed from 0x00020000 onwards.
This layout prevents overlap between the bootloader and application flash regions.
Validating the Application Image
To check for a valid application image, the bootloader must validate the contents of the application flash region. Some examples of checks which could be performed:
- Magic number at fixed offset to mark valid image.
- Checksum or CRC over the executable code.
- Digital signature to verify integrity and authenticity.
- Version number field matching expected value.
The bootloader can then look for the magic number or checksum at the appropriate offset within the application region to determine if a valid image is present.
Configuring Memory Regions
Prior to jumping to the application, the Cortex-M1 memory regions must be configured appropriately. This includes:
- The vector table base address register must be set to the start of the application vector table.
- The Memory Protection Unit (MPU) must be configured to grant access to application flash and RAM regions.
- The stack pointer must be set up pointing to application RAM.
Reconfiguring the vector table is critical otherwise the application will jump back to the bootloader’s vectors on exceptions. The MPU must allow access to .text, .data and .bss memory areas.
Jumping to Application Code
Once the bootloader has validated the application image, the final step is to jump to the application entry point. Some considerations:
- The entry point is typically the Reset_Handler function in the application vector table.
- Registers may need saving/restoring across the jump.
- Stack pointer must be switched from bootloader to application stack.
This step transfers control over the Cortex-M1 from the bootloader to the application. The application will continue initialization by calling its SystemInit and main functions.
Updating the Application Image
With the bootloader configured properly, updated application images can be remotely sent to the device and programmed into the application flash region. For example:
- Application image is built with updated code/data.
- Image is sent to device via OTAP/OFTP protocols.
- Flash programming writes image to application region.
- Device is reset, restarting the boot process.
- Bootloader finds new valid image and boots it.
This allows the Cortex-M1 application to be upgraded without re-flashing the entire device firmware. The bootloader is left intact across image updates.
Integrating with RTX RTOS
RTX adds further complexity since it initializes the Cortex-M1 kernel, systems resources and RTOS objects. The key considerations for integration include:
- Bootloader must not use any RTX functions since kernel is uninitialized.
- RX initialization code must execute prior to bootloader jumping to main().
- RTX code must be linked in the application image, not the bootloader.
- Kernel awareness in both bootloader and application for consistency.
Real-time threads, mutexes, timers, etc. will start running after the bootloader jumps to application entry point. The application is then responsible for loading/starting other RTOS tasks as needed.
Debugging the Bootloading Process
Debugging bootloading requires working through both the bootloader and application execution flows. Issues to look out for include:
- Processor halting in bootloader prior to application jump.
- Memory faults and access violations during application load.
- Faulty stack initialization causing application crashes.
- Incorrect vector table configuration trapping processor in bootloader.
- Memory collisions between bootloader and application.
Debugging works best with JTAG/SWD hardware assistance to halt and trace through instruction execution. Watchpoints can track memory writes during image validation and MPU setup steps.
Conclusion
Implementing bootloading allows a Cortex-M1 processor to remotely update application firmware without affecting the bootloader. This provides field upgradability without requiring physical access to re-flash devices. Care must be taken to validate and properly execute the application image within the constraints of the bootloader environment.
Integrating the bootloading process with an RTX RTOS application adds further complexity with managing the kernel initialization and transition to the application. But with careful planning, an RTX real-time application can benefit from remote updating capabilities.