27
27
/* Family specific include for WB with HW semaphores */
28
28
#include "hw.h"
29
29
#include "hw_conf.h"
30
+ #include "shci.h"
31
+
32
+ /* Used in HCIDriver.cpp/stm32wb_start_ble() */
33
+ int BLE_inited = 0 ;
30
34
31
35
/**
32
36
* @brief Gets the page of a given address
@@ -71,47 +75,82 @@ int32_t flash_erase_sector(flash_t *obj, uint32_t address)
71
75
uint32_t PAGEError = 0 ;
72
76
FLASH_EraseInitTypeDef EraseInitStruct ;
73
77
int32_t status = 0 ;
78
+ uint32_t cpu1_sem_status = 1 ;
79
+ uint32_t cpu2_sem_status = 1 ;
74
80
75
81
if ((address >= (FLASH_BASE + FLASH_SIZE )) || (address < FLASH_BASE )) {
76
82
return -1 ;
77
83
}
78
84
79
- #if defined(CFG_HW_FLASH_SEMID )
80
- /* In case RNG is a shared ressource, get the HW semaphore first */
85
+ /* Flash IP semaphore */
81
86
while (LL_HSEM_1StepLock (HSEM , CFG_HW_FLASH_SEMID ));
82
- #endif
83
87
84
88
/* Unlock the Flash to enable the flash control register access */
85
89
if (HAL_FLASH_Unlock () != HAL_OK ) {
86
90
return -1 ;
87
91
}
88
92
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 ) {
91
113
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
+ }
94
134
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 ));
99
137
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 );
106
146
}
107
147
108
148
/* Lock the Flash to disable the flash control register access (recommended
109
149
to protect the FLASH memory against possible unwanted operation) */
110
150
HAL_FLASH_Lock ();
111
151
112
- #if defined( CFG_HW_FLASH_SEMID )
152
+ /* Flash IP semaphore */
113
153
LL_HSEM_ReleaseLock (HSEM , CFG_HW_FLASH_SEMID , 0 );
114
- #endif
115
154
116
155
return status ;
117
156
}
@@ -131,6 +170,8 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data,
131
170
{
132
171
uint32_t StartAddress = 0 ;
133
172
int32_t status = 0 ;
173
+ uint32_t cpu1_sem_status = 1 ;
174
+ uint32_t cpu2_sem_status = 1 ;
134
175
135
176
if ((address >= (FLASH_BASE + FLASH_SIZE )) || (address < FLASH_BASE )) {
136
177
return -1 ;
@@ -140,51 +181,73 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data,
140
181
return -1 ;
141
182
}
142
183
143
- #if defined(CFG_HW_FLASH_SEMID )
144
- /* In case RNG is a shared ressource, get the HW semaphore first */
184
+ /* Flash IP semaphore */
145
185
while (LL_HSEM_1StepLock (HSEM , CFG_HW_FLASH_SEMID ));
146
- #endif
147
186
148
187
/* Unlock the Flash to enable the flash control register access */
149
188
if (HAL_FLASH_Unlock () != HAL_OK ) {
150
189
return -1 ;
151
190
}
152
191
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 );
168
237
}
169
238
}
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 ));
180
244
181
245
/* Lock the Flash to disable the flash control register access (recommended
182
246
to protect the FLASH memory against possible unwanted operation) */
183
247
HAL_FLASH_Lock ();
184
248
185
- #if defined( CFG_HW_FLASH_SEMID )
249
+ /* Flash IP semaphore */
186
250
LL_HSEM_ReleaseLock (HSEM , CFG_HW_FLASH_SEMID , 0 );
187
- #endif
188
251
189
252
return status ;
190
253
}
0 commit comments