cancel
Showing results for 
Search instead for 
Did you mean: 

Firmware updates and flash banks on an STM32L496

cambesol
Visitor
Hello Forum,
 
I have a question regarding OTA and toggling between flash banks on a STM32L496. I have read many forum posts on here relating to this and I have reached a point where I need assistance as debugging iteratively is taking a lot of time.
 
I am developing a firmware update process that has the update code as part of the application, not as part of the bootloader. Serial messages are received containing the binary data (derived from a *.bin image) and are written to the flash bank which is currently not in use.
 
The part has a flash memory layout as follows:
Flash AreaMemory start address Size Name
BANK 10x0800 00002k page 0
 0x0800 08002k page 1
 0x0800 10002k page 2
 ...  
 0x0807 F8002k page 255
BANK 20x0808 00002k page 256
 0x0808 08002k page 257
 0x0808 10002k page 258
 ...  
 0x080F F8002kpage 511
 
If I have freshly reprogrammed the part using the ST-Linkv2 programmer, the code checks which bank the image is running from as follows:
 
uint32_t fb_mode = LL_SYSCFG_GetFlashBankMode();
if (fb_mode == 0)
{
    /* Running from BANK 1 */
}
else
{
   /* Running from BANK 2 */
}
 
I then erase all 255 pages of the flash bank which I am not running in. Once this completes successfully, I write sequentially to the bank I want to run from after the OTA is completed. Without labouring the point, if I was running from Bank 1, then I would perform the following pseudo operations:
 
HAL_StatusTypeDef status = HAL_OK;
uint64_t *ptr = buffer; /* Contiguous array of 256 bytes of binary image. */
 
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, 0x08080000, *ptr++);
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, 0x08080800, *ptr++);
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, 0x08081000, *ptr++);
 
This is performed in a loop and the pointer is updated to match the wrte-size. The point I am trying to make is the addresses of the writes are dendent on which block the image is running from.
 
If I was running from flash bank 2, I would expect the following:
 
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, 0x08000000, *ptr++);
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, 0x08000800, *ptr++);
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, 0x08001000, *ptr++);
 
Here we are writing directly to Bank 1. After this is completed, I would update the flash Options Bytes as follows:
 
/* Get the current configuration */
HAL_FLASHEx_OBGetConfig(&obConfig);
uint32_t fb_mode = LL_SYSCFG_GetFlashBankMode();
if (fb_mode == 0) {
/* Explicitly boot from Bank 2 following reset
* as we are running from Bank 1. 
*/
    obConfig.USERConfig = OB_BFB2_ENABLE;
}
else {
/* Explicitly boot from Bank 1 following reset
* as we are running from Bank 2. 
*/
    obConfig.USERConfig = OB_BFB2_DISABLE;
}
/* Initiating the modifications */
result = HAL_FLASH_Unlock();
/* program if unlock is successful */
if (result == HAL_OK) {
    result = HAL_FLASH_OB_Unlock();
}
/* Program if unlock is successful. */
if ((READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) == RESET)) {
    result = HAL_FLASHEx_OBProgram(&obConfig);
}
/* No return as the last call triggers a reset. */
 
The problem I have is that this sequence works perfectly until the second OTA and at that point I cannot write to the Bank 1 first address. I have read on these forums that OTA updates should always be written to Bank 2 and the swapping is provided automatically by the OB_OFB2_ENABLE/DISABLE mechanism. I just need to confirm that this is the case or do I inspect the fb_mode value and write to the flash bank which I am not running from.
 
Thank you for any help that you can offer.
0 REPLIES 0