42
42
// Used by CPU2 to prevent CPU1 from writing/erasing data in flash memory.
43
43
#define SEMID_FLASH_CPU2 (7)
44
44
45
+ #define SEM_LOCK_SUCCESSFUL (0)
46
+ #define SEM_LOCK_BUSY (1)
47
+
45
48
#endif
46
49
47
50
typedef struct {
@@ -217,35 +220,120 @@ int32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *siz
217
220
return -1 ;
218
221
}
219
222
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
+
220
263
int flash_erase (uint32_t flash_dest , uint32_t num_word32 ) {
264
+ HAL_StatusTypeDef status = 0 ;
265
+
221
266
// check there is something to write
222
267
if (num_word32 == 0 ) {
223
268
return 0 ;
224
269
}
225
270
226
- #if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
227
271
// Acquire lock on the flash peripheral.
228
272
while (LL_HSEM_1StepLock (HSEM , SEMID_FLASH_REGISTERS )) {
229
273
}
230
- #endif
231
274
232
275
// Unlock the flash for erase.
233
276
HAL_FLASH_Unlock ();
234
277
235
- #if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
236
278
// Tell the HCI controller stack we're starting an erase, so it
237
279
// avoids radio activity for a while.
238
280
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 ;
241
309
}
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 ;
244
331
}
245
- #endif
246
332
247
- // Clear pending flags (if any) and set up EraseInitStruct.
333
+ // Unlock the flash for erase.
334
+ HAL_FLASH_Unlock ();
248
335
336
+ // Clear pending flags (if any) and set up EraseInitStruct.
249
337
FLASH_EraseInitTypeDef EraseInitStruct ;
250
338
#if defined(STM32F0 )
251
339
__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) {
296
384
#endif
297
385
EraseInitStruct .Sector = flash_get_sector_info (flash_dest , NULL , NULL );
298
386
EraseInitStruct .NbSectors = flash_get_sector_info (flash_dest + 4 * num_word32 - 1 , NULL , NULL ) - EraseInitStruct .Sector + 1 ;
299
-
300
387
#endif
301
388
302
389
// Erase the sectors.
303
390
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 );
314
392
315
393
// Lock the flash after erase.
316
394
HAL_FLASH_Lock ();
317
395
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
-
323
396
return mp_hal_status_to_neg_errno (status );
324
397
}
325
398
399
+ #endif // ! MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
400
+
326
401
/*
327
402
// erase the sector using an interrupt
328
403
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) {
362
437
// Unlock the flash for write.
363
438
HAL_FLASH_Unlock ();
364
439
365
- #if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
366
- // Wait for PES.
367
- while (LL_FLASH_IsActiveFlag_OperationSuspended ()) {
368
- }
369
- #endif
370
-
371
440
HAL_StatusTypeDef status = HAL_OK ;
372
441
373
442
#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) {
377
446
uint64_t val = * (uint64_t * )src ;
378
447
379
448
#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 ();
383
451
#endif
384
452
385
453
status = HAL_FLASH_Program (FLASH_TYPEPROGRAM_DOUBLEWORD , flash_dest , val );
386
454
387
455
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
388
456
// 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 );
392
458
#endif
393
459
394
460
if (status != HAL_OK ) {
@@ -403,18 +469,15 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) {
403
469
val = (val & 0xffffffff00000000uL ) | (* src );
404
470
405
471
#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 ();
409
474
#endif
410
475
411
476
status = HAL_FLASH_Program (FLASH_TYPEPROGRAM_DOUBLEWORD , flash_dest , val );
412
477
413
478
#if MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
414
479
// 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 );
418
481
#endif
419
482
}
420
483
0 commit comments