2021-10-12 01:28 AM
Dear ST community
I've been trying to implement the BLE_RfWithFlash example from the STM32WBCube package into my BLE application.
When trying to write/erase flash, the MCU disconnects the BLE client and triggers a hard fault. If I run the application in debug mode, it works sometimes when stepping through the code.
The basic idea is that a BLE characteristic callback triggers the MCU the save configuration data into flash page 85/0x08055000
Information:
MCU: STM32WB55CE (& CG)
STM32WBCube package: ver. 1.12.0
Firmware: BLE full stack
BLE interface: Arduino BLE for stm32wb
OS: Freertos alongside BLE callbacks
Application:
I've used the flash_driver.c/.h from the package example (only added HW semaphore IDs to header since I have no editable hw_conf.h).
I've wrapped the flash driver in a C++ class for readability. The function interacting with the driver:
#define FLASH_PAGE_NUMBER 0x55 // 85
#define FLASH_BASE_ADDRESS 0x08055000
// _eeprom_buffer is an std::array
...
void EEPROM::commit_buffer() {
if (this->_dirtyBuffer) {
// erase flash page 85
FD_EraseSectors(FLASH_PAGE_NUMBER, 1);
// write new data into flash page 85
FD_WriteData(
FLASH_BASE_ADDRESS, (uint64_t *)this->_eeprom_buffer.data(), FLASH_PAGE_SIZE / sizeof(uint64_t));
this->_dirtyBuffer = false;
}
}
(inspired by https://github.com/khoih-prog/FlashStorage_STM32)
Things I've tried without luck:
Hope someone can point me in the right direction - I've been stuck on application note AN5289 for some time now as well as the related issues on the forum.
2021-10-13 02:47 AM
Hello,
Unfortunately, a regression on the BLE timing protection versus flash erase/write processing from CPU1 has been introduced in v1.12.0 wireless binaries.
Please make sure to update to v1.12.1. You only need to update the CPU2 wireless binary to v1.12.1 and keep your current V1.12.0 package on CPU1 although it is always better to move to the last version ( but not mandatory).
Regards.
2021-10-20 04:58 AM
Hi @Christophe Arnal
I've now updated all the firmware to v1.12.1 package, both FUS and BLE_full_stack.
My application doesn't disconnect the BLE client anymore :thumbs_up:
Unfortunately the flashing problem still persists.
I am able to write data using FD_WriteData() from flash_driver.h, but ONLY after a manual sector erase using STM32CubeProgrammer.
It seems FD_EraseSectors() never erases the flash when going through code with debugger. The application only rarely goes into Hard Fault, but by the looks of it the trigger is HAL_FLASH_LOCK().
I do see the code being stuck in ProcessSingleFlashOperation() if following lines are not commented out:
static SingleFlashOperationStatus_t ProcessSingleFlashOperation(FlashOperationType_t FlashOperationType,
uint32_t SectorNumberOrDestAddress,
uint64_t Data) {
...
/**
* When the PESD bit mechanism is used by CPU2 to protect its timing, the PESD bit should be polled here.
* If the PESD is set, the CPU1 will be stalled when reading literals from an ISR that may occur after
* the flash processing has been requested but suspended due to the PESD bit.
*
* Note: This code is required only when the PESD mechanism is used to protect the CPU2 timing.
* However, keeping that code make it compatible with the two mechanisms.
*/
while (LL_FLASH_IsActiveFlag_OperationSuspended())
;
...
/**
* In most BLE application, the flash should not be blocked by the CPU2 longer than FLASH_TIMEOUT_VALUE (1000ms)
* However, it could be that for some marginal application, this time is longer.
* In that case either HAL_FLASHEx_Erase() or HAL_FLASH_Program() will exit with FLASH_TIMEOUT_VALUE value.
* This is not a failing case and there is no other way than waiting the operation to be completed.
* If for any reason this test is never passed, this means there is a failure in the system and there is no other
* way to recover than applying a device reset.
*
* Note: This code is required only when the PESD mechanism is used to protect the CPU2 timing.
* However, keeping that code make it compatible with the two mechanisms.
*/
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY))
;
EDIT: I have set SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) in my main setup function that runs before RTOS and BLE initialization.
Could this be more related to application rather than the co-processors?
Regards
2021-10-21 05:36 AM
Hello,
Usually, the application is not able to erase the sectors because the BLE connection interval is too short. You need at least 25ms radio idle time to be able to erase a sector.
In our BLE_Ota application, the sectors are erased before the BLE connection is setup.
That would be good if you could check if the semaphore CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID is not kept locked by the CPU2. ( this would confirm the assumption and explain why you are not able to erase).
Regards.