A bootloader is a small program that runs when a microcontroller (MCU) first powers up. It is responsible for initializing hardware, setting up memory, and loading the main application program into memory so it can execute. The bootloader acts as a bridge between power on and running the main program.
Main Functions of an MCU Bootloader
The primary jobs a bootloader performs include:
- Initialize system hardware – At power on, the MCU is in an unknown state. The bootloader configures clocks, memory, peripherals, and any external hardware to get the system into a known good state before loading the application.
- Check and initialize memory – The bootloader verifies and configures RAM and flash memory where the application will be stored. This includes verifying the integrity of the memory and setting up memory regions.
- Load the application program – The bootloader finds, extracts, and copies the application program from its storage location (usually external flash or ROM) into RAM or internal flash for execution.
- Jump to the application – After loading the application into memory, the bootloader jumps to the start of the application code and begins executing it.
- Provide update capabilities – Many bootloaders allow for field application firmware updates by having the ability to overwrite existing firmware with new versions sent from an external host.
- Handle errors – If the bootloader encounters invalid memory, corrupted application firmware, or other errors during the boot process, it can handle the errors appropriately through notification or recovery.
Bootloader Types
There are several common types of embedded system bootloaders:
- ROM bootloader – A simple bootloader burned into internal MCU ROM during manufacturing. Always available but not updatable.
- Flash bootloader – More complex bootloader stored in internal flash memory, allowing it to be updated but occupying application space.
- External bootloader – Stores the bootloader on an external flash chip, external EEPROM or microSD card for recovery purposes.
- Remote bootloader – A network capable bootloader that can load application firmware sent from a remote host.
Bootloader Storage Locations
The bootloader must be stored in non-volatile memory so it can run each time on power on before loading the main application. Common storage locations include:
- Mask ROM – A pre-programmed ROM region inside the MCU containing a simple bootloader from the factory.
- Internal flash – The bootloader can be programmed into a dedicated flash section reserved for it.
- External flash – For complex bootloaders and recovery purposes, external flash like EEPROM offers better updatability.
- SD card – The bootloader can be loaded from a FAT formatted SD card as the first code executed.
Bootloader Operation Flow
A typical MCU bootloader sequence involves the following steps:
- MCU reset occurs, CPU starts executing instructions from the bootloader located in mask ROM or internal flash.
- Bootloader initializes system clocks, memory, peripherals, and any external hardware into a known ready state.
- Bootloader verifies and configures memory areas to be used for the application program.
- Bootloader copies the application program from its storage location into RAM or internal flash.
- Bootloader jumps to the start of the application program and begins executing it.
- Application program takes over, main() or other startup routines begin running.
In Application Programming vs Standalone Bootloader
Bootloader code can be implemented and executed in two ways:
- In Application – The bootloader code is part of the application firmware and executes as part of the app each time. Simple but less flexible.
- Standalone – The bootloader stored separately from application code and runs first before loading the application. More complex but allows field updates.
Standalone bootloaders require a separate storage region or external memory to be updatable without affecting application code.
Bootloader Design Considerations
Key factors to consider when implementing an MCU bootloader:
- Size – Smaller is better to leave space for the application. A few KB to tens of KB is typical.
- Complexity – Determine needed features vs size/performance tradeoffs. External storage offers more flexibility.
- Security – Crypto authentication of application firmware is recommended to prevent malicious code.
- Communications – Wired (UART, USB, I2C, SPI) or wireless (WiFi, Bluetooth, Zigbee, etc) for remote updates.
- Speed – As fast as possible while performing needed tasks. Delays could disrupt applications.
Example Bootloader Operation
Here is an example boot process for an ARM Cortex-M4 MCU with a flash bootloader:
- On power on, the CPU fetches the flash bootloader instructions from the reserved bootloader section of internal flash.
- The bootloader configures the system clock tree for max supported speed of 180MHz using the internal PLL and oscillators.
- It enables SRAM memory controllers and checks SRAM memory integrity by writing and verifying test patterns.
- Flash memory controllers are configured and the application binary region is checked for a valid checksum to verify integrity.
- A valid application is detected, so it is copied from flash to SRAM for execution.
- After loading the application, the bootloader jumps to the application entry point and begins executing.
- The application’s main() function runs initialization routines then enters the main program loop.
Advantages of Using a Bootloader
Reasons to use a bootloader in an embedded system:
- Allows safe application firmware updates without bricking device
- Recovery mechanism if corrupt application firmware is detected
- Initialize hardware without needing application code
- Upgrade application remotely over-the-air for deployed devices
- Switch between multiple application images
- Interfaces available before application loads
- Customize startup sequence and hardware config
Disadvantages of Using a Bootloader
Potential downsides to bootloaders:
- Increased memory requirements for bootloader storage
- Added development time and complexity
- Boot time latency added before application load
- Potential security issues if not properly implemented
- Requires hardware design considered for storage and communications
- Risk of bricking device if corrupted bootloader
- Faulty bootloader could prevent any application from running
Conclusion
In summary, an MCU bootloader is a small program that runs first when a microcontroller powers on to initialize hardware, check memory integrity, load the main application firmware into execution memory, and safely jump to the application code. Bootloaders provide advantages such as enabling remote updates but comes at the cost of added memory usage, latency, complexity, and security considerations. Careful design is needed to balance application requirements with bootloader capabilities.