cancel
Showing results for 
Search instead for 
Did you mean: 

Write/Erase flash results in hard faults in BLE application

KMeld.1
Associate III

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:

  • play around with connection and advertising interval
  • Use SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7)
  • Add task delays in driver.
  • play around with WaitedSemStatus_t FD_WaitForSemAvailable(WaitedSemId_t WaitedSemId); in driver.

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.

3 REPLIES 3
Christophe Arnal
ST Employee

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.

KMeld.1
Associate III

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 👍

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

Christophe Arnal
ST Employee

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.