Other Parts Discussed in Thread: C2000WARE
This thread will discuss the best practices for custom bootloading on the following devices:
- F2807x
- F2837xS
- F2837xD
- F28004x
- F2838x
- F28002x
- F28003x
- F280013x
- F280015x
- F28P65x
- F28P55x
- F28E12x
Other Parts Discussed in Thread: C2000WARE
This thread will discuss the best practices for custom bootloading on the following devices:
ROM Bootloaders: Code loading utilities provided in the device's Boot ROM, restricted to only program RAM.
Flash Kernels: Code loading intermediate loaded by the ROM Bootloader into RAM first, then used to program the on-chip flash.
Flash Bootloaders: Custom bootloader stored in on-chip flash to program flash contents directly.
Secondary Bootloader (SBL): Second-stage bootloader that runs after the primary boot flow in the ROM, intended to perform more complex actions (configure specific peripherals, verify code integrity, etc.).
Please refer to SPRUJH3 to understand bootloading offerings on C28x MCUs.
Given that the ROM bootloaders are limited to program the RAM only, flash kernels are employed as an intermediate to program firmware into the flash by leveraging the Flash API. Flash kernels are loaded into the RAM by ROM bootloader first and execution is transferred to the flash kernel. Then, the flash kernel can receive and download the application firmware to flash. More details can be found in Section 3.2 of SPRUJH3.
TI offers flash kernel examples for the following peripherals and device families:
| SCI |
F2802x, F2803x, F2805x, F2806x, F2833x F2807x, F2837xD, F2837xS, F28004x, F2838x, F28002x, F28003x, F280013x, F280015x, F28P65x, F28P55x, F28E12x |
SPRABV4 |
| DCAN | F28003x, F28P65x, F280015x | SPRAD51 |
| MCAN | F28003x, F28P65x, F28P55x | SPRAD51 |
| USB | F2837xD | SPRACO7 |
Instead of using a RAM kernel, which has to be re-downloaded every Power-On Reset (POR) using the ROM bootloaders, users can alternatively store a bootloader in the flash. On reset, the device can be configured to boot directly to flash to load/program code directly. This eliminates the need to download a flash kernel first with the ROM bootloaders by storing a bootloader in the flash (to persist after POR).
The general recommendation is to modify the flash kernel's linker command file to execute from the flash instead of RAM (refer to Section 5.2 of SPRUJH3 for steps).
There are also Live Firmware Update (LFU) solutions for certain device families, which have flash bootloaders implemented for reference:
| F28002x | C2000Ware_XX_XX_XX_XX\driverlib\f28002x\examples\flash\flash_kernel_ex3_sci_flash_kernel | SPRUIU8 |
| F28003x | C2000Ware_XX_XX_XX_XX\driverlib\f28003x\examples\flash\flash_kernel_ex3_sci_flash_kernel | SPRUIU9, TIDUEY4 |
| F28004x | C2000Ware_XX_XX_XX_XX\driverlib\f28003x\examples\flash\flashapi_ex2_sci_kernel | SPRUIU8, TIDUEY4 |
| F28P55x | C2000Ware_XX_XX_XX_XX\driverlib\f28p55x\examples\flash\flash_kernel_ex3_sci_flash_kernel | SPRUIU9 |
| F28P65x | C2000Ware_XX_XX_XX_XX\driverlib\f28p65x\examples\c28x_dual\flash_kernel\can_flash_lfu_sbl_multi_f28p65x | SPRUIU8, TIDUEY4 |
To enable seamless transfer of control from old firmware to new firmware multi-bank flash support is a critical feature. The flash technology used on C28x devices does not permit simultaneous reads and writes to a given flash bank, so this model allows one bank to execute firmware, and other bank(s) to be programmed. Please consult the Flash Memory Map section in the Data Sheet for device-specific flash organization.
With this in mind:
In summary, for the single flash bank use-case: a portion of the bootloader, a portion of the application (depending on if LFU is required), and the entire Flash API library (contained within the bootloader) needs to run from RAM.
Please refer to Section 2 in SPRUJH3 for details on how to configure the device boot configuration registers in the DCSM user OTP.
If using a custom bootloader stored the flash, then "Boot to Flash" should be configured. Please ensure that the flash boot option pertains to the correct flash entry point (generally the bootloader's codestart).
Please refer to this exhaustive E2E FAQ on C2000 Flash API Usage: [FAQ] FAQ on Flash API usage for C2000 devices
Each device family has a device-specific Flash API reference guide, linked in C2000Ware at: C2000Ware_XX_XX_XX_XX\libraries\flash_api\device_family\docs
In multi-bank configurations, it is recommended for there to be redundancy in firmware to ensure the device can recover if power-failure is encountered during firmware update. This can be accomplished using bank selection logic (described below).
In short, the 'KEY' value indicates if the flash bank's firmware is valid after program/verification procedures are complete. If this value is not written due to an interruption, then the device will not boot to the incomplete firmware and instead branch to the older, valid firmware version. Then, the user can re-attempt to program the new firmware.
When branching from the bootloader to the application, the user should be performing a branch to the codestart of the application (to execute the application's codestartbranch.asm routine). If performing a LFU, then the user may need to branch to different entry points to perform various LFU functions. Generally, the most important thing is that the target branch address is absolute.
Below are a few methods to perform a branch:
For jumping to a specific absolute flash address, inline assembly can be used to employ the LB instruction:

Source: SPRU430
Code Example:
asm(" LB 0x080000"); // Long Branch to addressA function pointer can be cast and called:
((void(*)())(0x80000))(); // Direct jump to 0x80000
Bank selection logic allows the bootloader to determine which, if any, of the flash banks are programmed with valid application firmware, and which bank contains the most recent application firmware version. Thus, bank selection logic is the entry point of the software system, that is, it should be branched to first from the Boot ROM on reset. Please note that only one flash bank needs to store the bank selection logic.
In the LFU examples released by TI, bank selection logic is implemented using the following metadata (stored at a reserved location in each flash bank):
On device reset, execution starts at the default boot to flash entry point, 0x80000, which is where the bank selection logic function is located. This function checks for valid applications in the flash banks, picks the recent most version, and branches to the corresponding firmware version’s entry point (codestart). The entry point is the gateway to the C runtime initialization routine and main() of the application.
Please refer to SPRUIU8, SPRUIU9, and TIDUEY4 for more details on the bank selection implementation.