56
56
// Used by CPU2 to prevent CPU1 from writing/erasing data in flash memory.
57
57
#define SEMID_FLASH_CPU2 (7)
58
58
59
+ #define SEM_LOCK_SUCCESSFUL (0)
60
+ #define SEM_LOCK_BUSY (1)
61
+
59
62
#endif
60
63
61
64
typedef struct {
@@ -242,35 +245,120 @@ int32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *siz
242
245
return -1 ;
243
246
}
244
247
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
+
245
288
int flash_erase (uint32_t flash_dest , uint32_t num_word32 ) {
289
+ HAL_StatusTypeDef status = 0 ;
290
+
246
291
// check there is something to write
247
292
if (num_word32 == 0 ) {
248
293
return 0 ;
249
294
}
250
295
251
- #if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
252
296
// Acquire lock on the flash peripheral.
253
297
while (LL_HSEM_1StepLock (HSEM , SEMID_FLASH_REGISTERS )) {
254
298
}
255
- #endif
256
299
257
300
// Unlock the flash for erase.
258
301
HAL_FLASH_Unlock ();
259
302
260
- #if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
261
303
// Tell the HCI controller stack we're starting an erase, so it
262
304
// avoids radio activity for a while.
263
305
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 ;
266
334
}
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 ;
269
356
}
270
- #endif
271
357
272
- // Clear pending flags (if any) and set up EraseInitStruct.
358
+ // Unlock the flash for erase.
359
+ HAL_FLASH_Unlock ();
273
360
361
+ // Clear pending flags (if any) and set up EraseInitStruct.
274
362
FLASH_EraseInitTypeDef EraseInitStruct ;
275
363
#if defined(STM32F0 )
276
364
__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) {
333
421
334
422
// Erase the sectors.
335
423
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 );
346
425
347
426
// Lock the flash after erase.
348
427
HAL_FLASH_Lock ();
349
428
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
-
355
429
return mp_hal_status_to_neg_errno (status );
356
430
}
357
431
432
+ #endif // ! MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
433
+
358
434
/*
359
435
// erase the sector using an interrupt
360
436
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) {
394
470
// Unlock the flash for write.
395
471
HAL_FLASH_Unlock ();
396
472
397
- #if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
398
- // Wait for PES.
399
- while (LL_FLASH_IsActiveFlag_OperationSuspended ()) {
400
- }
401
- #endif
402
-
403
473
HAL_StatusTypeDef status = HAL_OK ;
404
474
405
475
#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) {
409
479
uint64_t val = * (uint64_t * )src ;
410
480
411
481
#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 ();
415
484
#endif
416
485
417
486
status = HAL_FLASH_Program (FLASH_TYPEPROGRAM_DOUBLEWORD , flash_dest , val );
418
487
419
488
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
420
489
// 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 );
424
491
#endif
425
492
426
493
if (status != HAL_OK ) {
@@ -435,18 +502,15 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
435
502
val = (val & 0xffffffff00000000uL ) | (* src );
436
503
437
504
#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 ();
441
507
#endif
442
508
443
509
status = HAL_FLASH_Program (FLASH_TYPEPROGRAM_DOUBLEWORD , flash_dest , val );
444
510
445
511
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
446
512
// 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 );
450
514
#endif
451
515
}
452
516
0 commit comments