A number of use cases can be envisioned with LFU. They are listed below. A, B, C, D, and so on refer to firmware versions.
- A→B →C →D →E
- This is the typical use-case we prepare for
- A serves as a reference image to build B, B as a reference image for C, and so on
- A→B →A →B →A
- Another use-case we may encounter, where for testing purposes, or in the field if you want to revert to the original image if a problem is found with the new image
- A will serve as a reference image to build B, so when you switch from A to B you can use the Compiler’s warm initialization routine. Because A was provided as reference, the compiler knows the variables differences between A and B, and it will place the variables unique to B in a “TI.update” section. This is the only section that will be initialized by the compiler in its __TI_auto_init_warm() routine when LFU switching from A to B
- When switching from B to A, the situation is different. A was built standalone, so it does not have a “.TI.update” section, the compiler does not know which variables are unique to A (relative to B), so __TI_auto_init_warm() will not do anything
- Is this use-case feasible? Yes, the user can still switch from B back to A. Just that the user cannot leverage the Compiler’s __TI_auto_init_warm() to initialize any variables unique to A. The user will need to use Macros to manually initialize these unique variables in main() of A. For example, if A is in Flash Bank0, and B in Flash Bank1, A can have initialization code in main() like this:
#ifdef BANK0
[initialize variables unique to A]
#endif - In fact, the current LFU example is illustrates A-B-A-B switching. The difference is that in the current example, B has new variables compared to A, but A does not have any unique variables compared to B. Also remember that the warm start routine provided by the compiler is not being used, so even the switch from A to B uses manual initialization
- Skipped updates – assume field locations don’t update firmware versions as they become available, but skip updates. For example:
Field_location_1: A→B →C →D →E
Field_location_2: A →C →D →E
Field_location_3: A→B → D →E
Is this use-case feasible? No. There are two issues.
- One, LFU by nature is incremental. So, each image builds on the other. The .TI.update section generated by the compiler is specific to the reference elf used in generating that image. If the user wants to update relative to an older image, then manual effort would be involved in understanding the variable differences between those 2 images, and manual initialization of the unique variables would need to be performed. A bigger issue is state. Suppose B introduced a new variable “var_x” that then became a common variable across all future images. And the user is updating from A to D. Now, D assumes var_x is a common variable because it is present in C, and therefore doesn’t initialize it. However, relative to A, var_x is new. So not initializing it can cause problems.
- Two, with our implementation, the user also needs to be aware of the specific Bank the image is targeted to. So, in this example, A, C, E would be on Bank0, and B, D would be on Bank1. So, it would not be possible to update from A to C as indicated in Field_location_2.
- If the user builds the new firmware without using the old firmware as reference, there is no
guarantee that common global variables will remain at the same
addresses, so state cannot be preserved. So the application behavior may
be unexpected after the LFU switchover., unless the entire C
initialization routine is executed during the switchover. This may be
too time consuming and exceed available LFU switchover time.