8000 stm32wb55/flash: Update semaphore use for flash cpu synchronisation. · micropython/micropython@2594f3f · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2594f3f

Browse files
committed
stm32wb55/flash: Update semaphore use for flash cpu synchronisation.
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
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
426
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 < 10000 span class=pl-c1>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

493
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)
0