Skip to main content
APort
Associate III
February 16, 2020
Question

STMWB55: Flash write access during BLE connection

  • February 16, 2020
  • 13 replies
  • 8041 views

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.

This topic has been closed for replies.

13 replies

Remi QUINTIN
ST Technical Moderator
February 17, 2020

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.

APort
APortAuthor
Associate III
February 17, 2020

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.

lukasz2
Associate III
February 17, 2020

Hello APort,

I have the same problem with access to the flash.

Can you suggest where to change connection interval?

Thanks in advance.

Remi QUINTIN
ST Technical Moderator
February 17, 2020

​>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.

APort
APortAuthor
Associate III
February 17, 2020

> 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.

APort
APortAuthor
Associate III
March 16, 2020

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.

Remi QUINTIN
ST Technical Moderator
March 16, 2020

Sem2 gives the ownership of the Flash memory and Sem7 is only used at the time the write access is done to ensure M0+ is not using the Flash memory at the same time.

SEM7 is Used by CPU2 (M0+) to prevent CPU1 (M4) from writing/erasing data in Flash memory

Sem7 is used to protect the CPU2 timing versus write/erase Flash memory operation requested by CPU1. The CPU1 must get Sem7 before writing or erasing. Sem7 must be taken and released for each single write or erase operation, but not for more than 0.5 ms in addition to the write/erase timing. To comply with this requirement, the code has to be executed in the critical section. The algorithm is described in the picture below.

Remi QUINTIN
ST Technical Moderator
March 16, 2020

..

APort
APortAuthor
Associate III
March 16, 2020

Thanks Remi,

The "Release Sem3" is a typo in the diagram? Should it be Sem7?

If so when should I use the Sem2? should it surround this entire flow?

Any chance there's an example code for proper flash erase?

Thanks in advance

Remi QUINTIN
ST Technical Moderator
March 16, 2020

Indeed it is a typo . You should read SEM7.

Yes the get and release of SEM2 is surrounding this sequence using HAL_Lock() et HAL_unlock() function calls.

This figure only describes the potential issue of the timing protection for the M0+ to be able to manage the RF IP.

The Sem7 is a way for the CM0+ to allow the CM4 core to effectively write to the flash.

APort
APortAuthor
Associate III
March 16, 2020

1) I did try to lock everything with Sem2 - unfortunately, it did not help (not measurably at least).

while(LL_HSEM_2StepLock(HSEM, CFG_HW_FLASH_SEMID, 88)) { };

// my prev write code

LL_HSEM_ReleaseLock(HSEM, CFG_HW_FLASH_SEMID, 88);

2) "HAL_Lock() et HAL_unlock()" - did you mean HAL_FLASH_Unlock() and HAL_FLASH_Lock()? as the former are not defined.

Remi QUINTIN
ST Technical Moderator
March 17, 2020

1) Please have a look at the picture showing a more complete sequence for the flash memory access

2) Yes the functions are HAL_FLASH_Unlock() and HAL_FLASH_Lock

APort
APortAuthor
Associate III
March 18, 2020

Thanks for the diagram, very useful.

I found the issue we've been having - we missed the lock every 64bit write. It somewhat works now.

The lowest connection interval we manged to work with using sem7 is 70ms.

Is this is the expected value for this design?

lukasz2
Associate III
March 19, 2020

Hello APort,

Can you share your improved FLASH access functions?

Thanks in advance

Remi QUINTIN
ST Technical Moderator
March 20, 2020

A complete example will be provided in the next CubeWB FW package V1.6.0 planned to be delivered by 20w14.

Scott Löhr
Senior III
June 8, 2020

@APort​ and/or @lukasz2​ - have either of you found a best solution for erasing a flash page without breaking the BLE connection?

I have success with a function that I created to align with the BLE interval to ensure the most time possible for the page erase - call the align function immediately before making the page erase. I posted this function in my own question about the proper order and usage of the semaphores to coordinate with CPU2, I hope it helps and let me know if you found the exact steps to follow wrt the semaphores:

https://community.st.com/s/question/0D53W00000914bCSAQ/stm32wb-hsem-flash-semaphore-usage

Remi QUINTIN
ST Technical Moderator
June 8, 2020

Regarding the example provided in the CubeWB FW package regarding writing some data into the flash memory without losing the connection, please have a look at the project under Projects\P-NUCLEO-WB55.Nucleo\Applications\BLE\BLE_RfWithFlash directory.

March 23, 2021

Hi guys.

I try to change "slave latency" to (!=0) as example = 3. And problem with while(LL_FLASH_IsActiveFlag_OperationSuspended()); is disappeared.

But not on all phones.

For example, MIUI refuses to work.

But I don’t understand why the choice of phones affects the work with flash on chip :).

ST Employee
April 6, 2021

Hello,

The only action that could be blocked is the flash erase procedure. There is always some time to fit a "write flash" operation.

You need the radio to be idle for at least 25ms to fit an "erase flash operation" so I believe that depending on the remote phone used, the radio interval may be different and some time, it does not provide a 25ms idle time required to fit an "erase flash operation"

Regards.

April 8, 2021

Hi.

I fixed the problem by setting the connection intreval to 50-60 msec because cpu2 needs 25ms to erase 1 page, and mine is erased 2 pages.