cancel
Showing results for 
Search instead for 
Did you mean: 

What is the simplest approach for 1-bit shared memory between bootloader & application?

MFolk.1
Senior

I am trying to get an application to set a flag to non-volatile memory to communicate to the bootloader after reset to reprogram the application image. I am using the STM32L496 MCU.

EEPROM seems to be the weapon of choice, but our team has EEPROM on both the application and the bootloader configured to use "virtual eeprom" (which basically means it is actually using flash) and from what I can tell can only be used within their respective programs.

What would be beautiful is if the MCU had a spare non-volatile register (like the RCC_CSR register) that can be used to share a 1-bit flag between the applications to communicate when it is time to reprogram the image.

What is the simplest method for tackling this problem? Example?

Thanks,

Marshall

1 ACCEPTED SOLUTION

Accepted Solutions

You could move the stack pointer down and shrink the RAM by 16 bytes or whatever.

*((uint32_t *)0x20004FFF0) = 0xABBAACDC;

Between you writing it and doing an NVIC_SystemReset() and entering Reset_Handler is a pretty short walk. The MCU does not clear memory, startup code potentially can but only that visible to the linker.

The RTC has 128 bytes of backup registers, perhaps look at related examples and RM. The linker has no awareness of this memory

void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data);

uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister);

On parts like the L1 and L0 there is actual EEPROM if this needs to survive a power cycle, and you have not backup supply.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

9 REPLIES 9
Paul1
Lead

Assign 1 FLASH Page for configuration, page size is smallest independently erasable (often larger than smallest writable).

Some MCUs have bitwise and word-wise erasable sections for this, depends on the family you choose.

I wouldn't use a separate IC (EEPROM) unless this was going to be used often (>1000times in life of product), or you just can't reserve one page of FLASH because code uses every word.

Paul

Paul1
Lead

Alternate:

Include a CRC in application code, bootloader check application code and CRC on bootup to verify valid.

To force bootload simply corrupt the App code's CRC by zeroing it. (Need to ensure CRC is alway non-zero.

To force a non-zero CRC simply reserve an extra byte/word and fill it with 0xFF, then BL can check for 0xFF and CRC on boot, if both zero then do Bootload.

Simpler: Reserve one word at beginning or end of App FLASH, zero it to trigger BL. BL must know its address which is why beginning or end of FLASH is best, or just after App Vector table, or an unused vector in App vector table.

If it's a simple reset you can just store magic values in RAM, could use registers in RTC also.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

How would I store data to RAM and be able to recover it? Can you suggest a safe address for my application? This is the RAM allocation as defined in the linker file for both the bootloader and the application. Obviously the flash addresses are different. Do I allocate (aka "carve out") more memory?

0693W00000FDgskQAD.png

You could move the stack pointer down and shrink the RAM by 16 bytes or whatever.

*((uint32_t *)0x20004FFF0) = 0xABBAACDC;

Between you writing it and doing an NVIC_SystemReset() and entering Reset_Handler is a pretty short walk. The MCU does not clear memory, startup code potentially can but only that visible to the linker.

The RTC has 128 bytes of backup registers, perhaps look at related examples and RM. The linker has no awareness of this memory

void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data);

uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister);

On parts like the L1 and L0 there is actual EEPROM if this needs to survive a power cycle, and you have not backup supply.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Since the application is using the RTC peripheral, I am trying to get the RAM approach working first. However, it isn't saving the data.

Application Code:

uint8_t *ToReprogram = (uint8_t *)0x2004FFFF; // last byte of allocated RAM

PRINTF("ToReprogram: %d\n\r", *ToReprogram); // ToReprogram == 97

*ToReprogram = 1;

PRINTF("ToReprogram: %d\n\r", *ToReprogram); // ToReprogram == 1

NVIC_SystemReset(); // software reset -> Jump back to bootloader for reprogramming

Bootloader Code:

uint8_t *ToReprogram = (uint8_t *)0x2004FFFF; // last byte of allocated RAM

PRINTF("ToReprogram: %d\n\r", *ToReprogram); // ToReprogram == 97

What am I missing?

Never mind. I took your advice from the following post and it fixed the issue.

https://community.st.com/s/question/0D50X00009hmvGZSAY/help-storing-a-variable-in-ram-that-does-not-get-initialized-at-startup-for-watchdog-recovery

Specifically, I updated my linker file as such:

0693W00000FDhaZQAT.png

And does this work? The stack pointer must be aligned at least on 4 bytes.

It does work, but now that you say that I better do that so that I don't run the risk of overwriting whatever is in front of it. Thanks!