Skip to content

Commit 0b5a91c

Browse files
committed
1 parent ec1e659 commit 0b5a91c

File tree

2 files changed

+116
-49
lines changed

2 files changed

+116
-49
lines changed

features/FEATURE_BLE/targets/TARGET_STM/TARGET_STM32WB/HCIDriver.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ static bool get_bd_address(uint8_t *bd_addr);
8686
static bool sysevt_wait(void);
8787
static bool sysevt_check(void);
8888

89+
extern int BLE_inited;
8990

9091
namespace ble {
9192
namespace vendor {
@@ -675,6 +676,9 @@ class TransportDriver : public cordio::CordioHCITransportDriver {
675676
* Starts the BLE Stack on CPU2
676677
*/
677678
SHCI_C2_BLE_Init(&ble_init_cmd_packet);
679+
680+
/* Used in flash_api.c */
681+
BLE_inited = 1;
678682
}
679683

680684
TL_CmdPacket_t *bleCmdBuf;

targets/TARGET_STM/TARGET_STM32WB/flash_api.c

Lines changed: 112 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
/* Family specific include for WB with HW semaphores */
2828
#include "hw.h"
2929
#include "hw_conf.h"
30+
#include "shci.h"
31+
32+
/* Used in HCIDriver.cpp/stm32wb_start_ble() */
33+
int BLE_inited = 0;
3034

3135
/**
3236
* @brief Gets the page of a given address
@@ -71,47 +75,82 @@ int32_t flash_erase_sector(flash_t *obj, uint32_t address)
7175
uint32_t PAGEError = 0;
7276
FLASH_EraseInitTypeDef EraseInitStruct;
7377
int32_t status = 0;
78+
uint32_t cpu1_sem_status = 1;
79+
uint32_t cpu2_sem_status = 1;
7480

7581
if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
7682
return -1;
7783
}
7884

79-
#if defined(CFG_HW_FLASH_SEMID)
80-
/* In case RNG is a shared ressource, get the HW semaphore first */
85+
/* Flash IP semaphore */
8186
while (LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID));
82-
#endif
8387

8488
/* Unlock the Flash to enable the flash control register access */
8589
if (HAL_FLASH_Unlock() != HAL_OK) {
8690
return -1;
8791
}
8892

89-
/* Clear OPTVERR bit set on virgin samples */
90-
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
93+
if (BLE_inited) {
94+
/*
95+
* Notify the CPU2 that some flash erase activity may be executed
96+
* On reception of this command, the CPU2 enables the BLE timing protection versus flash erase processing
97+
* The Erase flash activity will be executed only when the BLE RF is idle for at least 25ms
98+
* The CPU2 will prevent all flash activity (write or erase) in all cases when the BL RF Idle is shorter than 25ms.
99+
*/
100+
SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON);
101+
}
102+
103+
do {
104+
/* PESD bit mechanism used by M0+ to protect its timing */
105+
while (LL_FLASH_IsActiveFlag_OperationSuspended());
106+
107+
core_util_critical_section_enter();
108+
109+
/* Trying to access the flash can stall BLE */
110+
/* Use this semaphore to check M0+ activity */
111+
cpu1_sem_status = LL_HSEM_GetStatus(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID);
112+
if (cpu1_sem_status == 0) {
91113

92-
/* Get the page number associated to the address */
93-
PageNumber = GetPage(address);
114+
/* When flash processing is ongoing, the second CPU cannot access the flash anymore */
115+
cpu2_sem_status = LL_HSEM_1StepLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID);
116+
117+
if (cpu2_sem_status == 0) {
118+
/* Clear OPTVERR bit set on virgin samples */
119+
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
120+
121+
/* Get the page number associated to the address */
122+
PageNumber = GetPage(address);
123+
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
124+
EraseInitStruct.Page = PageNumber;
125+
EraseInitStruct.NbPages = 1;
126+
127+
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
128+
status = -1;
129+
}
130+
131+
LL_HSEM_ReleaseLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID, 0);
132+
}
133+
}
94134

95-
/* MBED HAL erases 1 page at a time */
96-
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
97-
EraseInitStruct.Page = PageNumber;
98-
EraseInitStruct.NbPages = 1;
135+
core_util_critical_section_exit();
136+
} while ((cpu2_sem_status) || (cpu1_sem_status));
99137

100-
/* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
101-
you have to make sure that these data are rewritten before they are accessed during code
102-
execution. If this cannot be done safely, it is recommended to flush the caches by setting the
103-
DCRST and ICRST bits in the FLASH_CR register. */
104-
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
105-
status = -1;
138+
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY));
139+
140+
if (BLE_inited) {
141+
/**
142+
* Notify the CPU2 there will be no request anymore to erase the flash
143+
* On reception of this command, the CPU2 disables the BLE timing protection versus flash erase processing
144+
*/
145+
SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF);
106146
}
107147

108148
/* Lock the Flash to disable the flash control register access (recommended
109149
to protect the FLASH memory against possible unwanted operation) */
110150
HAL_FLASH_Lock();
111151

112-
#if defined(CFG_HW_FLASH_SEMID)
152+
/* Flash IP semaphore */
113153
LL_HSEM_ReleaseLock(HSEM, CFG_HW_FLASH_SEMID, 0);
114-
#endif
115154

116155
return status;
117156
}
@@ -131,6 +170,8 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data,
131170
{
132171
uint32_t StartAddress = 0;
133172
int32_t status = 0;
173+
uint32_t cpu1_sem_status = 1;
174+
uint32_t cpu2_sem_status = 1;
134175

135176
if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
136177
return -1;
@@ -140,51 +181,73 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data,
140181
return -1;
141182
}
142183

143-
#if defined(CFG_HW_FLASH_SEMID)
144-
/* In case RNG is a shared ressource, get the HW semaphore first */
184+
/* Flash IP semaphore */
145185
while (LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID));
146-
#endif
147186

148187
/* Unlock the Flash to enable the flash control register access */
149188
if (HAL_FLASH_Unlock() != HAL_OK) {
150189
return -1;
151190
}
152191

153-
/* Program the user Flash area word by word */
154-
StartAddress = address;
155-
156-
/* HW needs an aligned address to program flash, which data parameters doesn't ensure */
157-
if ((uint32_t) data % 8 != 0) { // Data is not aligned, copy data in a temp buffer before programming it
158-
volatile uint64_t data64;
159-
while ((address < (StartAddress + size)) && (status == 0)) {
160-
for (uint8_t i = 0; i < 8; i++) {
161-
*(((uint8_t *) &data64) + i) = *(data + i);
162-
}
163-
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data64) == HAL_OK) {
164-
address = address + 8;
165-
data = data + 8;
166-
} else {
167-
status = -1;
192+
do {
193+
/* PESD bit mechanism used by M0+ to protect its timing */
194+
while (LL_FLASH_IsActiveFlag_OperationSuspended());
195+
196+
core_util_critical_section_enter();
197+
198+
/* Trying to access the flash can stall BLE */
199+
/* Use this semaphore to check M0+ activity */
200+
cpu1_sem_status = LL_HSEM_GetStatus(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID);
201+
if (cpu1_sem_status == 0) {
202+
203+
/* When flash processing is ongoing, the second CPU cannot access the flash anymore */
204+
cpu2_sem_status = LL_HSEM_1StepLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID);
205+
206+
if (cpu2_sem_status == 0) {
207+
208+
/* Program the user Flash area word by word */
209+
StartAddress = address;
210+
211+
/* HW needs an aligned address to program flash, which data parameters doesn't ensure */
212+
if ((uint32_t) data % 8 != 0) { // Data is not aligned, copy data in a temp buffer before programming it
213+
volatile uint64_t data64;
214+
while ((address < (StartAddress + size)) && (status == 0)) {
215+
for (uint8_t i = 0; i < 8; i++) {
216+
*(((uint8_t *) &data64) + i) = *(data + i);
217+
}
218+
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data64) == HAL_OK) {
219+
address = address + 8;
220+
data = data + 8;
221+
} else {
222+
status = -1;
223+
}
224+
}
225+
} else { // Data is aligned, so let's avoid any copy
226+
while ((address < (StartAddress + size)) && (status == 0)) {
227+
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *((uint64_t *) data)) == HAL_OK) {
228+
address = address + 8;
229+
data = data + 8;
230+
} else {
231+
status = -1;
232+
}
233+
}
234+
}
235+
236+
LL_HSEM_ReleaseLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID, 0);
168237
}
169238
}
170-
} else { // Data is aligned, so let's avoid any copy
171-
while ((address < (StartAddress + size)) && (status == 0)) {
172-
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *((uint64_t *) data)) == HAL_OK) {
173-
address = address + 8;
174-
data = data + 8;
175-
} else {
176-
status = -1;
177-
}
178-
}
179-
}
239+
240+
core_util_critical_section_exit();
241+
} while ((cpu2_sem_status) || (cpu1_sem_status));
242+
243+
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY));
180244

181245
/* Lock the Flash to disable the flash control register access (recommended
182246
to protect the FLASH memory against possible unwanted operation) */
183247
HAL_FLASH_Lock();
184248

185-
#if defined(CFG_HW_FLASH_SEMID)
249+
/* Flash IP semaphore */
186250
LL_HSEM_ReleaseLock(HSEM, CFG_HW_FLASH_SEMID, 0);
187-
#endif
188251

189252
return status;
190253
}

0 commit comments

Comments
 (0)