8000 stm32wb55/flash: Use Sem7 for flash cpu synchronisation. · micropython/micropython@d396081 · GitHub
[go: up one dir, main page]

Skip to content

Commit d396081

Browse files
committed
stm32wb55/flash: Use Sem7 for flash cpu synchronisation.
1 parent 2ea21ab commit d396081

File tree

2 files changed

+111
-45
lines changed

2 files changed

+111
-45
lines changed

ports/stm32/flash.c

Lines changed: 106 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
// Used by CPU2 to prevent CPU1 from writing/erasing data in flash memory.
4343
#define SEMID_FLASH_CPU2 (7)
4444

45+
#define SEM_LOCK_SUCCESSFUL (0)
46+
#define SEM_LOCK_BUSY (1)
47+
4548
#endif
4649

4750
typedef struct {
@@ -217,35 +220,120 @@ int32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *siz
217220
return -1;
218221
}
219222

223+
224+
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
225+
static mp_uint_t flash_sync_lock_aquire(void) {
226+
// Wait for flash interlocks
227+
mp_uint_t atomic_state;
228+
229+
for (;;) {
230+
// Wait for PES (if it's enabled, no-op if not).
231+
while (LL_FLASH_IsActiveFlag_OperationSuspended()) {
232+
}
233+
234+
atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
235+
236+
// Check the flash hasn't already been locked elsewhere by CPU1
237+
if (LL_HSEM_GetStatus(HSEM, SEMID_FLASH_CPU1) == SEM_LOCK_SUCCESSFUL) {
238+
239+
// Ensure CPU2 isn't already using the flash
240+
if (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_CPU2) == SEM_LOCK_SUCCESSFUL) {
241+
// Got the lock, continue flash operation
242+
break;
243+
}
244+
// CPU2 Locked, release our semaphore / critical section to try again.
245+
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_CPU2, 0);
246+
}
247+
MICROPY_END_ATOMIC_SECTION(atomic_state);
248+
249+
MICROPY_EVENT_POLL_HOOK
250+
}
251+
return atomic_state;
252+
}
253+
254+
static void flash_sync_lock_release(mp_uint_t atomic_state) {
255+
// Release flash lock.
256+
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY)) {
257+
}
258+
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_CPU2, 0);
259+
260+
MICROPY_END_ATOMIC_SECTION(atomic_state);
261+
}
262+
220263
int flash_erase(uint32_t flash_dest, uint32_t num_word32) {
264+
HAL_StatusTypeDef status = 0;
265+
221266
// check there is something to write
222267
if (num_word32 == 0) {
223268
return 0;
224269
}
225270

226-
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
227271
// Acquire lock on the flash peripheral.
228272
while (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_REGISTERS)) {
229273
}
230-
#endif
231274

232275
// Unlock the flash for erase.
233276
HAL_FLASH_Unlock();
234277

235-
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
236278
// Tell the HCI controller stack we're starting an erase, so it
237279
// avoids radio activity for a while.
238280
rfcore_start_flash_erase();
239-
// Wait for PES.
240-
while (LL_FLASH_IsActiveFlag_OperationSuspended()) {
281+
282+
// On STM32WB only one page shall be erased per semaphore lock
283+
size_t total_pages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE;
284+
for (size_t i = 0; i < total_pages && status == 0; i++) {
285+
num_word32 = 1024; // 1 page
286+
287+
// Wait for flash semaphore locks
288+
mp_uint_t sync_lock = flash_sync_lock_aquire();
289+
290+
// Clear pending flags (if any) and set up EraseInitStruct.
291+
FLASH_EraseInitTypeDef EraseInitStruct;
292+
#if defined(STM32WB)
293+
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
294+
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
295+
EraseInitStruct.Page = get_page(flash_dest);
296+
EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE;
297+
#else
298+
#error "MICROPY_HW_STM32WB_FLASH_SYNCRONISATION only supported on STM32WB"
299+
#endif
300+
301+
// Erase the sectors.
302+
uint32_t SectorError = 0;
303+
status |= HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
304+
305+
// Release flash lock.
306+
flash_sync_lock_release(sync_lock);
307+
308+
flash_dest += FLASH_PAGE_SIZE;
241309
}
242-
// Wait for flash lock.
243-
while (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_CPU2)) {
310+
311+
// Tell HCI controller that erase is over.
312+
rfcore_end_flash_erase();
313+
314+
// Lock the flash after erase.
315+
HAL_FLASH_Lock();
316+
317+
// Release lock on the flash peripheral.
318+
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_REGISTERS, 0);
319+
320+
return mp_hal_status_to_neg_errno(status);
321+
}
322+
323+
#else // ! MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
324+
325+
int flash_erase(uint32_t flash_dest, uint32_t num_word32) {
326+
HAL_StatusTypeDef status = 0;
327+
328+
// check there is something to write
329+
if (num_word32 == 0) {
330+
return 0;
244331
}
245-
#endif
246332

247-
// Clear pending flags (if any) and set up EraseInitStruct.
333+
// Unlock the flash for erase.
334+
HAL_FLASH_Unlock();
248335

336+
// Clear pending flags (if any) and set up EraseInitStruct.
249337
FLASH_EraseInitTypeDef EraseInitStruct;
250338
#if defined(STM32F0)
251339
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR);
@@ -296,33 +384,20 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) {
296384
#endif
297385
EraseInitStruct.Sector = flash_get_sector_info(flash_dest, NULL, NULL);
298386
EraseInitStruct.NbSectors = flash_get_sector_info(flash_dest + 4 * num_word32 - 1, NULL, NULL) - EraseInitStruct.Sector + 1;
299-
300387
#endif
301388

302389
// Erase the sectors.
303390
uint32_t SectorError = 0;
304-
HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
305-
306-
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
307-
// Release flash lock.
308-
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY)) {
309-
}
310-
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_CPU2, 0);
311-
// Tell HCI controller that erase is over.
312-
rfcore_end_flash_erase();
313-
#endif
391+
status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
314392

315393
// Lock the flash after erase.
316394
HAL_FLASH_Lock();
317395

318-
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
319-
// Release lock on the flash peripheral.
320-
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_REGISTERS, 0);
321-
#endif
322-
323396
return mp_hal_status_to_neg_errno(status);
324397
}
325398

399+
#endif // ! MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
400+
326401
/*
327402
// erase the sector using an interrupt
328403
void flash_erase_it(uint32_t flash_dest, uint32_t num_word32) {
@@ -362,12 +437,6 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
362437
// Unlock the flash for write.
363438
HAL_FLASH_Unlock();
364439

365-
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
366-
// Wait for PES.
367-
while (LL_FLASH_IsActiveFlag_OperationSuspended()) {
368-
}
369-
#endif
370-
371440
HAL_StatusTypeDef status = HAL_OK;
372441

373442
#if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
@@ -377,18 +446,15 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
377446
uint64_t val = *(uint64_t *)src;
378447

379448
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
380-
// Wait for flash lock.
381-
while (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_CPU2)) {
382-
}
449+
// Wait for flash interlocks
450+
mp_uint_t sync_lock = flash_sync_lock_aquire();
383451
#endif
384452

385453
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val);
386454

387455
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
388456
// Release flash lock.
389-
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_CPU2, 0);
390-
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY)) {
391-
}
457+
flash_sync_lock_release(sync_lock);
392458
#endif
393459

394460
if (status != HAL_OK) {
@@ -403,18 +469,15 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
403469
val = (val & 0xffffffff00000000uL) | (*src);
404470

405471
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
406-
// Wait for flash lock.
407-
while (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_CPU2)) {
408-
}
472+
// Wait for flash interlocks
473+
mp_uint_t sync_lock = flash_sync_lock_aquire();
409474
#endif
410475

411476
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val);
412477

413478
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
414479
// Release flash lock.
415-
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_CPU2, 0);
416-
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY)) {
417-
}
480+
flash_sync_lock_release(sync_lock);
418481
#endif
419482
}
420483

ports/stm32/rfcore.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@
7676
#define OCF_C2_FLASH_ERASE_ACTIVITY (0x69)
7777
#define OCF_C2_SET_FLASH_ACTIVITY_CONTROL (0x73)
7878

79+
#define FLASH_ACTIVITY_CONTROL_PES (0)
80+
#define FLASH_ACTIVITY_CONTROL_SEM7 (1)
81+
7982
#define HCI_OPCODE(ogf, ocf) ((ogf) << 10 | (ocf))
8083

8184
#define HCI_KIND_BT_CMD (0x01) // <kind=1>...?
@@ -592,8 +595,8 @@ void rfcore_ble_init(void) {
592595
tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_BLE_INIT), (const uint8_t *)&ble_init_params, sizeof(ble_init_params), 0);
593596
tl_ble_hci_cmd_resp(HCI_OPCODE(0x03, 0x0003), NULL, 0);
594597

595-
// Enable PES rather than SEM7 to moderate flash access between the cores.
596-
uint8_t buf = 0; // FLASH_ACTIVITY_CONTROL_PES
598+
// Enable SEM7 rather than PES to moderate flash access between the cores.
599+
uint8_t buf = FLASH_ACTIVITY_CONTROL_SEM7;
597600
tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_C2_SET_FLASH_ACTIVITY_CONTROL), &buf, 1, 0);
598601
}
599602

0 commit comments

Comments
 (0)
0