Skip to content

Commit 2594f3f

Browse files
committed
stm32wb55/flash: Update semaphore use for flash cpu synchronisation.
Signed-off-by: Andrew Leech <[email protected]>
1 parent 426e57f commit 2594f3f

File tree

1 file changed

+106
-42
lines changed

1 file changed

+106
-42
lines changed

ports/stm32/flash.c

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

59+
#define SEM_LOCK_SUCCESSFUL (0)
60+
#define SEM_LOCK_BUSY (1)
61+
5962
#endif
6063

6164
typedef struct {
@@ -242,35 +245,120 @@ int32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *siz
242245
return -1;
243246
}
244247

248+
249+
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
250+
static mp_uint_t flash_sync_lock_aquire(void) {
251+
// Wait for flash interlocks
252+
mp_uint_t atomic_state;
253+
254+
for (;;) {
255+
// Wait for PES (if it's enabled, no-op if not).
256+
while (LL_FLASH_IsActiveFlag_OperationSuspended()) {
257+
}
258+
259+
atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
260+
261+
// Check the flash hasn't already been locked elsewhere by CPU1
262+
if (LL_HSEM_GetStatus(HSEM, SEMID_FLASH_CPU1) == SEM_LOCK_SUCCESSFUL) {
263+
264+
// Ensure CPU2 isn't already using the flash
265+
if (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_CPU2) == SEM_LOCK_SUCCESSFUL) {
266+
// Got the lock, continue flash operation
267+
break;
268+
}
269+
// CPU2 Locked, release our semaphore / critical section to try again.
270+
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_CPU2, 0);
271+
}
272+
MICROPY_END_ATOMIC_SECTION(atomic_state);
273+
274+
MICROPY_EVENT_POLL_HOOK
275+
}
276+
return atomic_state;
277+
}
278+
279+
static void flash_sync_lock_release(mp_uint_t atomic_state) {
280+
// Release flash lock.
281+
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY)) {
282+
}
283+
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_CPU2, 0);
284+
285+
MICROPY_END_ATOMIC_SECTION(atomic_state);
286+
}
287+
245288
int flash_erase(uint32_t flash_dest, uint32_t num_word32) {
289+
HAL_StatusTypeDef status = 0;
290+
246291
// check there is something to write
247292
if (num_word32 == 0) {
248293
return 0;
249294
}
250295

251-
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
252296
// Acquire lock on the flash peripheral.
253297
while (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_REGISTERS)) {
254298
}
255-
#endif
256299

257300
// Unlock the flash for erase.
258301
HAL_FLASH_Unlock();
259302

260-
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
261303
// Tell the HCI controller stack we're starting an erase, so it
262304
// avoids radio activity for a while.
263305
rfcore_start_flash_erase();
264-
// Wait for PES.
265-
while (LL_FLASH_IsActiveFlag_OperationSuspended()) {
306+
307+
// On STM32WB only one page shall be erased per semaphore lock
308+
size_t total_pages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE;
309+
for (size_t i = 0; i < total_pages && status == 0; i++) {
310+
num_word32 = 1024; // 1 page
311+
312+
// Wait for flash semaphore locks
313+
mp_uint_t sync_lock = flash_sync_lock_aquire();
314+
315+
// Clear pending flags (if any) and set up EraseInitStruct.
316+
FLASH_EraseInitTypeDef EraseInitStruct;
317+
#if defined(STM32WB)
318+
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
319+
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
320+
EraseInitStruct.Page = get_page(flash_dest);
321+
EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE;
322+
#else
323+
#error "MICROPY_HW_STM32WB_FLASH_SYNCRONISATION only supported on STM32WB"
324+
#endif
325+
326+
// Erase the sectors.
327+
uint32_t SectorError = 0;
328+
status |= HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
329+
330+
// Release flash lock.
331+
flash_sync_lock_release(sync_lock);
332+
333+
flash_dest += FLASH_PAGE_SIZE;
266334
}
267-
// Wait for flash lock.
268-
while (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_CPU2)) {
335+
336+
// Tell HCI controller that erase is over.
337+
rfcore_end_flash_erase();
338+
339+
// Lock the flash after erase.
340+
HAL_FLASH_Lock();
341+
342+
// Release lock on the flash peripheral.
343+
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_REGISTERS, 0);
344+
345+
return mp_hal_status_to_neg_errno(status);
346+
}
347+
348+
#else // ! MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
349+
350+
int flash_erase(uint32_t flash_dest, uint32_t num_word32) {
351+
HAL_StatusTypeDef status = 0;
352+
353+
// check there is something to write
354+
if (num_word32 == 0) {
355+
return 0;
269356
}
270-
#endif
271357

272-
// Clear pending flags (if any) and set up EraseInitStruct.
358+
// Unlock the flash for erase.
359+
HAL_FLASH_Unlock();
273360

361+
// Clear pending flags (if any) and set up EraseInitStruct.
274362
FLASH_EraseInitTypeDef EraseInitStruct;
275363
#if defined(STM32F0)
276364
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR);
@@ -333,28 +421,16 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) {
333421

334422
// Erase the sectors.
335423
uint32_t SectorError = 0;
336-
HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
337-
338-
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
339-
// Release flash lock.
340-
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY)) {
341-
}
342-
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_CPU2, 0);
343-
// Tell HCI controller that erase is over.
344-
rfcore_end_flash_erase();
345-
#endif
424+
status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
346425

347426
// Lock the flash after erase.
348427
HAL_FLASH_Lock();
349428

350-
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
351-
// Release lock on the flash peripheral.
352-
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_REGISTERS, 0);
353-
#endif
354-
355429
return mp_hal_status_to_neg_errno(status);
356430
}
357431

432+
#endif // ! MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
433+
358434
/*
359435
// erase the sector using an interrupt
360436
void flash_erase_it(uint32_t flash_dest, uint32_t num_word32) {
@@ -394,12 +470,6 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
394470
// Unlock the flash for write.
395471
HAL_FLASH_Unlock();
396472

397-
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
398-
// Wait for PES.
399-
while (LL_FLASH_IsActiveFlag_OperationSuspended()) {
400-
}
401-
#endif
402-
403473
HAL_StatusTypeDef status = HAL_OK;
404474

405475
#if defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
@@ -409,18 +479,15 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
409479
uint64_t val = *(uint64_t *)src;
410480

411481
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
412-
// Wait for flash lock.
413-
while (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_CPU2)) {
414-
}
482+
// Wait for flash interlocks
483+
mp_uint_t sync_lock = flash_sync_lock_aquire();
415484
#endif
416485

417486
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val);
418487

419488
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
420489
// Release flash lock.
421-
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_CPU2, 0);
422-
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY)) {
423-
}
490+
flash_sync_lock_release(sync_lock);
424491
#endif
425492

426493
if (status != HAL_OK) {
@@ -435,18 +502,15 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
435502
val = (val & 0xffffffff00000000uL) | (*src);
436503

437504
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
438-
// Wait for flash lock.
439-
while (LL_HSEM_1StepLock(HSEM, SEMID_FLASH_CPU2)) {
440-
}
505+
// Wait for flash interlocks
506+
mp_uint_t sync_lock = flash_sync_lock_aquire();
441507
#endif
442508

443509
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_dest, val);
444510

445511
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
446512
// Release flash lock.
447-
LL_HSEM_ReleaseLock(HSEM, SEMID_FLASH_CPU2, 0);
448-
while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY)) {
449-
}
513+
flash_sync_lock_release(sync_lock);
450514
#endif
451515
}
452516

0 commit comments

Comments
 (0)