cancel
Showing results for 
Search instead for 
Did you mean: 

STMWB55: Flash write access during BLE connection

APort
Associate III

Hello,

We are trying to write(erase) the flash during BLE connection.

If we follow the STM32Cube_FW_WB_V1.4.0/Projects/P-NUCLEO-WB55.Nucleo/Examples/FLASH/FLASH_EraseProgram

Example the BLE connection terminates immediately (timeout error code).

Apparently you have to let the CPU2 know that you are about to access the flash. The only example I found for this is:

STM32Cube_FW_WB_V1.4.0/Middlewares/ST/STM32_WPAN/ble/mesh/PAL/STM32WB/pal_nvm.c

It works when BLE is not connected.

When there is an active connection the code is stuck in dead-loop on first:

while(LL_FLASH_IsActiveFlag_OperationSuspended());

(pal_nvm.c line 226).

Once BLE device is disconnected, it passes this while.

Now... I am trying to erase a single sector, and this happens even before address is given or anything; no prior errors.

The Erase is called from main loop handler.

CPU2 firmware used is 1.4.0 (latest).

Any ideas?

Thanks in advance.

28 REPLIES 28
Remi QUINTIN
ST Employee

The real time constraints regarding the RF management are very tight on CPU2. Erasing a single sector (an estimated 22ms duration) can be long for the CPU2 if it required an immediate access to the flash for writing or reading data. So the CPU2 must have the priority otherwise the connection can be lost. This is why CPU1 must inform CPU2 that it intends to perform some access to the Flash memory. CPU2 will grant CPU1 access to the flash when it does not need it anymore.

But if the CPU2 is in a phase requiring regular and time critical accesses to the flash memory, any access required by the CPU1 is hold until the CPU2 has completed all the work it has to do.

So imagine that the RF part is active with a advertising and connecting interval duration lower that about 22ms, CPU2 will always need an access to the flash memory to perform some tasks and the CPU1 will never be granted any access hence being stuck in the while(LL_FLASH_IsActiveFlag_OperationSuspended()); loop

As soon as the BLE is disconnected, CPU1 will have full access to the Flash memory.

If CPU1 wants to perform an even longer access, then it all depends of the regular need from CPU2 (RF active window).

So please check the interval duration used for the connection, extend it and check if CPU gain access to the flash memory more often.

Hello Remi,

Thank you for the reply.

You were right about the connection interval. We were able to write flash on values 60ms or above.

The thing is that it limits the throughput on our use-case significantly (we tested 12ms interval with no apparent issues before the flash access).

Is there something can be done here?

CPU2 has to access(write) the flash every cycle? I mean, its BLE stack, with no pairing, no privacy - apparently no persistent data at all that has to be written to the flash by CPU2, especially not every tick.

Thanks in advance.

Remi QUINTIN
ST Employee

​>The thing is that it limits the throughput on our use-case significantly (we tested 12ms interval with no apparent issues before the flash access).

Do you mean you do not face any issue with a connection interval of 12ms??

The usual way to inform the other CPU that a flash access is required is to set the PESD bit. There is one such bit for each CPU.

For BLE operation, it is required to make sure that the CPU2 is stalled during BLE timing critical activity. So it may happen that one CPU (here CPU1) is blocked for a longer time than required if the other CPU is stalled.

May be using a semaphore to protect access to the flash memory could improve.

CPU2 has only one port (port2) to access the flash memory (fetch/read/write) while CPU1 has 2 ports: port0 for the a fetch access, port1 for any read or write access.

Generally CPU1 can still execute some code if the flash access through port1 is blocked. But this is true as long as it does not require to read or write some literals.

> Do you mean you do not face any issue with a connection interval of 12ms??

Yes. It was actually 15ms interval (12 in 1.25ms units) but its same ballpark.

The test consisted of receiving packets (BLE peripheral, 244MTU vs Android phone) on M4 and doing very basic "skip-crc" check.

I totally understand that flash access has to be in sync;

It just strange to me (looks like a bug somewhere) that CPU2 has to either read or write the flash every tick (beside the code, but it takes less than 15ms as per prev test, plus it has icache?).

Furthermore, its not like CPU2 is busy with RF critical as SHCI_C2_FLASH_EraseActivity() returned with success code and its an IPC line before.

If its not a bug/wrong usage (aka. by chip design) - that's some seriously bad news for us ...

> May be using a semaphore to protect access to the flash memory could improve.

Using while(LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID)); as per example.

Hello APort,

I have the same problem with access to the flash.

Can you suggest where to change connection interval?

Thanks in advance.

APort
Associate III

You can do it either from the central side (depending on the platform) or by aci_l2cap_connection_parameter_update_req() after connection from peripheral.

From the central side do you mean from device itself? I work on STM32WB with BLE_Mesh application.

Hello Remi,

I have the same problems with FLASH access as APort but I work with BLE_MeshLightingDemo application.

I do not know how to change connection interval in mesh application type.

APort
Associate III

Just an update on this one as new 1.5.0 version tried to address this issue.

Using the SEM7 mechanism apparently does not work.

Tried with following:

// on init

SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON);

SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7);

// on every page erase

while(LL_HSEM_2StepLock(HSEM, 7, 66)) { };

FLASH_PageErase(i);

LL_HSEM_ReleaseLock(HSEM, 7, 66);

Everything is happy (no errors), but the BLE disconnects pretty much on first write. The connection interval is 100ms (150ms do not work either).

Using the SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_PES) with 100ms interval does work most of the time tho ...

Anyway, if someone can look at this one again, we'll really appreciate it as it is a major issue for us.