Skip to main content
Associate III
January 16, 2025
Solved

EEPROM Emulated Timing (x-cube-eeprom)

  • January 16, 2025
  • 4 replies
  • 1370 views

I am running a bluetooth application using freeRTOS on a Nucleo-WB55 (STM32WB55RG). I am in the process of implementing Emulated EEPROM (X-Cube-EEPROM) to store som data. 
After implementing eeprom emulated in a ble_heartrate_freertos example I have had problems understanding the execution of the Emulated EEPROM operation after a pagetransfer + cleanup (obs. for simplicity I use EE_CleanUp here)


Without BLE activated (in SingleCore mode) EEPROM Emulated write and pagetransfer+cleanup looks just fine:

Nikolaj_TL_0-1737036301238.png

Pagetransfer + cleanup takes ~40-50ms
 Nikolaj_TL_1-1737036338860.png

With BLE activated (in DualCore Mode) the following EEPROM operation occupies much more time than expected:
Nikolaj_TL_2-1737036512206.png

Pagetransfer + cleanup still takes ~40-50ms, but a long delay is introduced in the next EEPROM operation:

Nikolaj_TL_0-1737037736034.png

 

 

Here is an example of the additional delay introduced in the following EEPROM (after a pagetransfer + cleanup) operation: 
Nikolaj_TL_3-1737036590271.png


Here is the code:

 

 

int main(void)
{
 ...

 osKernelInitialize();
 defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
 APPE_Init();
 
 EEPROM_Emul_Init(); 
 EEPROMTimer_Id = osTimerNew(EEPROM_Emul_Simple, osTimerPeriodic, (void *)0, NULL);
 osTimerStart(EEPROMTimer_Id, 50); 
 
 /* Start scheduler */
 osKernelStart();
 
 /* We should never get here as control is now taken by the scheduler */
 while (1) { }
}

 

 

 

 

 

static void EEPROM_Emul_Simple()
{
 HAL_GPIO_TogglePin(DEBUG1_Gpio_Port, DEBUG1_Pin);
 static uint32_t VarValue = 1;
 static uint32_t Index = 1;
 static EE_Status ee_status = EE_OK;
 
 taskENTER_CRITICAL(); // Exit of critical section in FreeRTOS (disables interrupts)
 
 /* Wait for the flash semaphore to be free */ 
 if (HAL_HSEM_IsSemTaken(CFG_HW_FLASH_SEMID)) {
 taskEXIT_CRITICAL(); // exit of critical section in FreeRTOS
 
 HAL_GPIO_TogglePin(DEBUG3_Gpio_Port, DEBUG3_Pin);
 return;
 }
 if (HAL_HSEM_Take(CFG_HW_FLASH_SEMID, HSEM_PROCESS_1) != HAL_OK) {
 taskEXIT_CRITICAL(); // exit of critical section in FreeRTOS
 
 HAL_GPIO_TogglePin(DEBUG3_Gpio_Port, DEBUG3_Pin);
 return;
 }
 
 HAL_FLASH_Unlock(); /* Unlock the Flash Program Erase controller */
 
 /* ----------- WRITE ----------- */
 /* Toggle LED to show the EEPROM operations are effectively running */
 BSP_LED_Toggle(LED_BLUE);

 ee_status = EE_WriteVariable32bits(Index, Index*VarValue);
 /* If flash is used by CPU2 */
 if (ee_status == EE_FLASH_USED) {
 /* Lock the Flash Program Erase controller and release the semaphore */
 HAL_FLASH_Lock();
 HAL_HSEM_Release(CFG_HW_FLASH_SEMID, HSEM_PROCESS_1);
 taskEXIT_CRITICAL(); // exit of critical section in FreeRTOS
 
 HAL_GPIO_TogglePin(DEBUG3_Gpio_Port, DEBUG3_Pin);
 return;
 } 
 
 /* Start cleanup mode, if cleanup is needed */
 if ((ee_status & EE_STATUSMASK_CLEANUP) == EE_STATUSMASK_CLEANUP) {ErasingOnGoing = 0; ee_status |= EE_CleanUp();}
 if ((ee_status & EE_STATUSMASK_ERROR) == EE_STATUSMASK_ERROR) {Error_Handler();}
 
 /* Prepare the static parameters for the next time next the function is called by the FreeRTOS */
 Index++;
 if (Index >= (NB_OF_VARIABLES + 1)) {
 VarValue++;
 Index = 1;
 }
 
 /* Lock the Flash Program Erase controller and release flash semaphore if needed */
 HAL_FLASH_Lock();
 HAL_HSEM_Release(CFG_HW_FLASH_SEMID, HSEM_PROCESS_1);
 taskEXIT_CRITICAL(); // exit of critical section in FreeRTOS
 
 HAL_GPIO_TogglePin(DEBUG1_Gpio_Port, DEBUG1_Pin);
 return;
}

 

 

 

 

 

 

 

Best answer by Lubos KOUDELKA

Hello @Nikolaj_TL,

cores on STM32WB are independent, CPU1 is not able to directly wake-up CPU2. 
Difference in write and page transfer is the need for erase during page transfer and SHCI_C2_FLASH_EraseActivity command. As AN5289 is stating:
"When CPU1 sends the system command SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON), CPU2  immediately takes Sem7 until the next radio event, preventing any flash erase or write operations during this period."

Best regards,
Lubos

4 replies

Lubos KOUDELKA
ST Employee
January 23, 2025

Dear Nikolaj,
I believe justification of your behavior is in synchronization between cores during flash access as described in AN5289, chapter 4.7.1 CPU2 timing protection. Before flash erase, CPU1 shall send command SHCI_C2_FLASH_EraseActivity (ERASE_ACTIVITY_ON) and wait for Sem7. As CPU2 is sleeping, Sem7 will be released by CPU2 during next connection/advertising event. This may cause delay up to size of connection/advertising interval, delay may change depending how long before CPU2 wakeup CPU1 start waiting for Sem7 (as your picture is showing).

Would this hypothesis fit your connection/advertising interval? Could you please verify your CPU1 is really waiting for Sem7?

Thank you, best regards,
Lubos

 

Associate III
February 11, 2025

Hello @Lubos KOUDELKA

You are right CPU1 is waiting on Sem7 (tested by toggling a GPIO). This happens due to a page erase after a page transfer. Is It possible to wake cpu2 from sleep to make it hand over the semaphore before it wakes by the connection/advertising event. 

Another issue which bothers me is that write operations also vary in length. From what I understand cpu1 should request the sem2 & sem7 both when it needs to write data and when it needs to make page transfers (as descriped in 4.7.1 (through the algorithm shown in Figure 10). But I do not see long wait times for semaphore7 when cpu1 writes variables in flash, only when it needs to make pagetransfer and therby erase a page. 
How can this be?

Lubos KOUDELKA
Lubos KOUDELKABest answer
ST Employee
February 20, 2025

Hello @Nikolaj_TL,

cores on STM32WB are independent, CPU1 is not able to directly wake-up CPU2. 
Difference in write and page transfer is the need for erase during page transfer and SHCI_C2_FLASH_EraseActivity command. As AN5289 is stating:
"When CPU1 sends the system command SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON), CPU2  immediately takes Sem7 until the next radio event, preventing any flash erase or write operations during this period."

Best regards,
Lubos

Associate III
February 24, 2025

Thank you @Lubos KOUDELKA 

How would you then make CPU1 get Sem7 , when BLE (CPU2) is in Low Power advertising min period: 30s, max period: 90s. 
CPU1 could be waiting for quite some time before writing to eeprom.