2016-12-12 07:23 AM
Question - What is the safest way to 'peek' at the STML152 program counter? Ideally something in the standard HAL files (so no ASM; I am working under AC6 in C). I wish my code to understand if it was loaded/is running in the lower 1 of 2 flash banks (? PC < 0x8004000), or in the upper 2 of 2 banks (PC > 0x8004000).
Background - this is a kind of dual boot issue, but not really. The L152 has 512K flash in 2 x 256K banks and we plan to load 2 similar images in the two 256K banks. We'll always boot from the lower bank image, but wish to load field fw upgrades into the upper bank image, understanding that the reflash might fail & need to be erased completely. The upper bank will be re-written by our own code (FW read from a special secure SPI token), and that loading code will be linked to load/run from the upper bank only.
The goal is to treat the lower bank as a 'factory default image', and the upper bank as a 'field written & perhaps broken image'. So we want a simple piece of code that basically does this IF test:
if(I am running in lower bank - aka: PC < X?)
then I am factory image
if(secure token is in place)
consider reflash of upper FW - means one needs to power-cycle with secure token in place to reflash
else
examine upper image for validity (crc, maybe digital hash signature)
if(upper image is valid)
then jump to it & run
else erase the invalid image & continue running the original factory image.
else I am field image (PC > X?), so just run & don't bother looking for second/upper image or token
So the goal is to load new fw from the secure token, while running in the lower/factory image. I can completely erase the upper bank and attempt to write. We assume if the write is aborted, we'd end up with a partial/invalid image and the above test-for-validity could detect the bad FW status & erase it. We plan to use flash protection to disable the normal STLink reflash for field units (so one would need to erase all flash to re-enable such fw loading).
#dual-bank #nucleo-l152re #stm-registersSolved! Go to Solution.
2016-12-12 07:47 AM
Not sure why everyone is afraid of assembler.
Something trivial that returns the link register, R0 is a return parameter, link
WhereAmI:
mov r0, lr
bx lr
uint32_t WhereAmI(void); // returns the caller return address
Or
extern void * __Vectors; // Keil
NVIC_SetVectorTable((u32)(&__Vectors), 0x0); // Smart Base Location
extern void * g_pfnVectors; // More GNU/GCC centric
NVIC_SetVectorTable((u32)(&g_pfnVectors), 0x0); // Smart Base Location
ie the address of the table tells you the basis.
Or think about how qsort() works, pointers to functions....
2016-12-12 07:47 AM
Not sure why everyone is afraid of assembler.
Something trivial that returns the link register, R0 is a return parameter, link
WhereAmI:
mov r0, lr
bx lr
uint32_t WhereAmI(void); // returns the caller return address
Or
extern void * __Vectors; // Keil
NVIC_SetVectorTable((u32)(&__Vectors), 0x0); // Smart Base Location
extern void * g_pfnVectors; // More GNU/GCC centric
NVIC_SetVectorTable((u32)(&g_pfnVectors), 0x0); // Smart Base Location
ie the address of the table tells you the basis.
Or think about how qsort() works, pointers to functions....
2016-12-12 07:51 AM
Absolute addresses in the vector table tend to make truely position independent code a challenge.
Generally I'd have a small loader that doesn't get erased validate an image before jumping to it. If the flash write fails to complete the CRC doesn't resolve, if the write gets corrupted, the CRC also doesn't resolve. Mission Accomplished.