TIDUEY4D August 2022 – December 2022
The key considerations when preparing firmware for LFU are operational continuity and LFU switchover time. Operational continuity is achieved through persistence of state, which means keeping common static and global variables in RAM at the same addresses between firmware versions, and avoiding re-initialization of those variables when the new firmware takes effect. Compiler support for LFU is used to enable persistence of state.
Activating the new firmware involves branching from old firmware to the LFU entry point of the new firmware, execute the compiler's LFU initialization routine, arrive inside main() of the new image, and perform any additional initialization. This is where interrupts are briefly disabled, initialization that needs interrupts to be disabled is performed (e.g. Interrupt vector updates, function pointer updates), before interrupts are re-enabled. This last time interval is defined as the LFU switchover time.
LFU is simplified when there is hardware support to swap Flash banks [2], where either Flash bank can be mapped to a fixed address space, considered the Active bank. The Inactive bank is mapped to a different address space, and is the bank that is updated. C2000™ MCUs do not currently support Flash bank swap, so the user will need to keep track of the Flash bank where application firmware will be resident, and make the necessary assignments and adjustments in a linker command file.
Function pointers and Interrupt vectors need to be re-initialized inside main(), since their locations will be different between Flash banks. C2000™ MCUs support a large number of interrupt vectors (typically 192), so it is not practical to re-initialize all of them. Usually, only a few are used, and the rest are assigned to a default vector. The F28003x device contains LFU specific hardware features (Interrupt vector swapping, RAM block swapping) that enable reduction in the LFU switchover time.
If there are changes to array sizes or addition of variables to a structure, the user needs to manage these appropriately, by using pragmas early in the development cycle to place arrays and structures at fixed locations, but with sufficient headroom to account for their potential growth in future firmware. With this approach, only newly added fields need to be initialized.