2727/* Family specific include for WB with HW semaphores */
2828#include "hw.h"
2929#include "hw_conf.h"
30+ #include "shci.h"
31+
32+ /* Used in HCIDriver.cpp/stm32wb_start_ble() */
33+ int BLE_inited = 0 ;
3034
3135/**
3236 * @brief Gets the page of a given address
@@ -71,47 +75,82 @@ int32_t flash_erase_sector(flash_t *obj, uint32_t address)
7175 uint32_t PAGEError = 0 ;
7276 FLASH_EraseInitTypeDef EraseInitStruct ;
7377 int32_t status = 0 ;
78+ uint32_t cpu1_sem_status = 1 ;
79+ uint32_t cpu2_sem_status = 1 ;
7480
7581 if ((address >= (FLASH_BASE + FLASH_SIZE )) || (address < FLASH_BASE )) {
7682 return -1 ;
7783 }
7884
79- #if defined(CFG_HW_FLASH_SEMID )
80- /* In case RNG is a shared ressource, get the HW semaphore first */
85+ /* Flash IP semaphore */
8186 while (LL_HSEM_1StepLock (HSEM , CFG_HW_FLASH_SEMID ));
82- #endif
8387
8488 /* Unlock the Flash to enable the flash control register access */
8589 if (HAL_FLASH_Unlock () != HAL_OK ) {
8690 return -1 ;
8791 }
8892
89- /* Clear OPTVERR bit set on virgin samples */
90- __HAL_FLASH_CLEAR_FLAG (FLASH_FLAG_OPTVERR );
93+ if (BLE_inited ) {
94+ /*
95+ * Notify the CPU2 that some flash erase activity may be executed
96+ * On reception of this command, the CPU2 enables the BLE timing protection versus flash erase processing
97+ * The Erase flash activity will be executed only when the BLE RF is idle for at least 25ms
98+ * The CPU2 will prevent all flash activity (write or erase) in all cases when the BL RF Idle is shorter than 25ms.
99+ */
100+ SHCI_C2_FLASH_EraseActivity (ERASE_ACTIVITY_ON );
101+ }
102+
103+ do {
104+ /* PESD bit mechanism used by M0+ to protect its timing */
105+ while (LL_FLASH_IsActiveFlag_OperationSuspended ());
106+
107+ core_util_critical_section_enter ();
108+
109+ /* Trying to access the flash can stall BLE */
110+ /* Use this semaphore to check M0+ activity */
111+ cpu1_sem_status = LL_HSEM_GetStatus (HSEM , CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID );
112+ if (cpu1_sem_status == 0 ) {
91113
92- /* Get the page number associated to the address */
93- PageNumber = GetPage (address );
114+ /* When flash processing is ongoing, the second CPU cannot access the flash anymore */
115+ cpu2_sem_status = LL_HSEM_1StepLock (HSEM , CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID );
116+
117+ if (cpu2_sem_status == 0 ) {
118+ /* Clear OPTVERR bit set on virgin samples */
119+ __HAL_FLASH_CLEAR_FLAG (FLASH_FLAG_OPTVERR );
120+
121+ /* Get the page number associated to the address */
122+ PageNumber = GetPage (address );
123+ EraseInitStruct .TypeErase = FLASH_TYPEERASE_PAGES ;
124+ EraseInitStruct .Page = PageNumber ;
125+ EraseInitStruct .NbPages = 1 ;
126+
127+ if (HAL_FLASHEx_Erase (& EraseInitStruct , & PAGEError ) != HAL_OK ) {
128+ status = -1 ;
129+ }
130+
131+ LL_HSEM_ReleaseLock (HSEM , CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID , 0 );
132+ }
133+ }
94134
95- /* MBED HAL erases 1 page at a time */
96- EraseInitStruct .TypeErase = FLASH_TYPEERASE_PAGES ;
97- EraseInitStruct .Page = PageNumber ;
98- EraseInitStruct .NbPages = 1 ;
135+ core_util_critical_section_exit ();
136+ } while ((cpu2_sem_status ) || (cpu1_sem_status ));
99137
100- /* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
101- you have to make sure that these data are rewritten before they are accessed during code
102- execution. If this cannot be done safely, it is recommended to flush the caches by setting the
103- DCRST and ICRST bits in the FLASH_CR register. */
104- if (HAL_FLASHEx_Erase (& EraseInitStruct , & PAGEError ) != HAL_OK ) {
105- status = -1 ;
138+ while (__HAL_FLASH_GET_FLAG (FLASH_FLAG_CFGBSY ));
139+
140+ if (BLE_inited ) {
141+ /**
142+ * Notify the CPU2 there will be no request anymore to erase the flash
143+ * On reception of this command, the CPU2 disables the BLE timing protection versus flash erase processing
144+ */
145+ SHCI_C2_FLASH_EraseActivity (ERASE_ACTIVITY_OFF );
106146 }
107147
108148 /* Lock the Flash to disable the flash control register access (recommended
109149 to protect the FLASH memory against possible unwanted operation) */
110150 HAL_FLASH_Lock ();
111151
112- #if defined( CFG_HW_FLASH_SEMID )
152+ /* Flash IP semaphore */
113153 LL_HSEM_ReleaseLock (HSEM , CFG_HW_FLASH_SEMID , 0 );
114- #endif
115154
116155 return status ;
117156}
@@ -131,6 +170,8 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data,
131170{
132171 uint32_t StartAddress = 0 ;
133172 int32_t status = 0 ;
173+ uint32_t cpu1_sem_status = 1 ;
174+ uint32_t cpu2_sem_status = 1 ;
134175
135176 if ((address >= (FLASH_BASE + FLASH_SIZE )) || (address < FLASH_BASE )) {
136177 return -1 ;
@@ -140,51 +181,73 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data,
140181 return -1 ;
141182 }
142183
143- #if defined(CFG_HW_FLASH_SEMID )
144- /* In case RNG is a shared ressource, get the HW semaphore first */
184+ /* Flash IP semaphore */
145185 while (LL_HSEM_1StepLock (HSEM , CFG_HW_FLASH_SEMID ));
146- #endif
147186
148187 /* Unlock the Flash to enable the flash control register access */
149188 if (HAL_FLASH_Unlock () != HAL_OK ) {
150189 return -1 ;
151190 }
152191
153- /* Program the user Flash area word by word */
154- StartAddress = address ;
155-
156- /* HW needs an aligned address to program flash, which data parameters doesn't ensure */
157- if ((uint32_t ) data % 8 != 0 ) { // Data is not aligned, copy data in a temp buffer before programming it
158- volatile uint64_t data64 ;
159- while ((address < (StartAddress + size )) && (status == 0 )) {
160- for (uint8_t i = 0 ; i < 8 ; i ++ ) {
161- * (((uint8_t * ) & data64 ) + i ) = * (data + i );
162- }
163- if (HAL_FLASH_Program (FLASH_TYPEPROGRAM_DOUBLEWORD , address , data64 ) == HAL_OK ) {
164- address = address + 8 ;
165- data = data + 8 ;
166- } else {
167- status = -1 ;
192+ do {
193+ /* PESD bit mechanism used by M0+ to protect its timing */
194+ while (LL_FLASH_IsActiveFlag_OperationSuspended ());
195+
196+ core_util_critical_section_enter ();
197+
198+ /* Trying to access the flash can stall BLE */
199+ /* Use this semaphore to check M0+ activity */
200+ cpu1_sem_status = LL_HSEM_GetStatus (HSEM , CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID );
201+ if (cpu1_sem_status == 0 ) {
202+
203+ /* When flash processing is ongoing, the second CPU cannot access the flash anymore */
204+ cpu2_sem_status = LL_HSEM_1StepLock (HSEM , CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID );
205+
206+ if (cpu2_sem_status == 0 ) {
207+
208+ /* Program the user Flash area word by word */
209+ StartAddress = address ;
210+
211+ /* HW needs an aligned address to program flash, which data parameters doesn't ensure */
212+ if ((uint32_t ) data % 8 != 0 ) { // Data is not aligned, copy data in a temp buffer before programming it
213+ volatile uint64_t data64 ;
214+ while ((address < (StartAddress + size )) && (status == 0 )) {
215+ for (uint8_t i = 0 ; i < 8 ; i ++ ) {
216+ * (((uint8_t * ) & data64 ) + i ) = * (data + i );
217+ }
218+ if (HAL_FLASH_Program (FLASH_TYPEPROGRAM_DOUBLEWORD , address , data64 ) == HAL_OK ) {
219+ address = address + 8 ;
220+ data = data + 8 ;
221+ } else {
222+ status = -1 ;
223+ }
224+ }
225+ } else { // Data is aligned, so let's avoid any copy
226+ while ((address < (StartAddress + size )) && (status == 0 )) {
227+ if (HAL_FLASH_Program (FLASH_TYPEPROGRAM_DOUBLEWORD , address , * ((uint64_t * ) data )) == HAL_OK ) {
228+ address = address + 8 ;
229+ data = data + 8 ;
230+ } else {
231+ status = -1 ;
232+ }
233+ }
234+ }
235+
236+ LL_HSEM_ReleaseLock (HSEM , CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID , 0 );
168237 }
169238 }
170- } else { // Data is aligned, so let's avoid any copy
171- while ((address < (StartAddress + size )) && (status == 0 )) {
172- if (HAL_FLASH_Program (FLASH_TYPEPROGRAM_DOUBLEWORD , address , * ((uint64_t * ) data )) == HAL_OK ) {
173- address = address + 8 ;
174- data = data + 8 ;
175- } else {
176- status = -1 ;
177- }
178- }
179- }
239+
240+ core_util_critical_section_exit ();
241+ } while ((cpu2_sem_status ) || (cpu1_sem_status ));
242+
243+ while (__HAL_FLASH_GET_FLAG (FLASH_FLAG_CFGBSY ));
180244
181245 /* Lock the Flash to disable the flash control register access (recommended
182246 to protect the FLASH memory against possible unwanted operation) */
183247 HAL_FLASH_Lock ();
184248
185- #if defined( CFG_HW_FLASH_SEMID )
249+ /* Flash IP semaphore */
186250 LL_HSEM_ReleaseLock (HSEM , CFG_HW_FLASH_SEMID , 0 );
187- #endif
188251
189252 return status ;
190253}
0 commit comments