@@ -20,7 +20,20 @@ LOG_MODULE_REGISTER(LOG_DOMAIN);
20
20
21
21
#include "flash_stm32.h"
22
22
23
+ #if defined(FLASH_OPTR_DUAL_BANK )
24
+ /* The stm32wba6x MCUs have 2MB dual-bank */
25
+ #define STM32_SERIES_MAX_FLASH 2048
26
+ #define STM32_FLASH_HAS_2_BANKS (flash_device ) \
27
+ ((FLASH_STM32_REGS(flash_device)->OPTR & FLASH_STM32_DBANK) \
28
+ == FLASH_STM32_DBANK)
29
+ #else
23
30
#define STM32_SERIES_MAX_FLASH 1024
31
+ #define STM32_FLASH_HAS_2_BANKS (flash_device ) (false)
32
+ #endif /* FLASH_OPTR_DUAL_BANK */
33
+
34
+ #define PAGES_PER_BANK ((FLASH_SIZE / FLASH_PAGE_SIZE) / 2)
35
+
36
+ #define BANK2_OFFSET (KB(STM32_SERIES_MAX_FLASH) / 2)
24
37
25
38
#define ICACHE_DISABLE_TIMEOUT_VALUE 1U /* 1ms */
26
39
#define ICACHE_INVALIDATE_TIMEOUT_VALUE 1U /* 1ms */
@@ -105,6 +118,34 @@ static int icache_wait_for_invalidate_complete(void)
105
118
return status ;
106
119
}
107
120
121
+ /*
122
+ * offset and len must be aligned on write-block-size for write,
123
+ * positive and not beyond end of flash
124
+ */
125
+ bool flash_stm32_valid_range (const struct device * dev , off_t offset ,
126
+ uint32_t len , bool write )
127
+ {
128
+ if (STM32_FLASH_HAS_2_BANKS (dev ) &&
129
+ (CONFIG_FLASH_SIZE < STM32_SERIES_MAX_FLASH )) {
130
+ /*
131
+ * In case of bank1/2 discontinuity, the range should not
132
+ * start before bank2 and end beyond bank1 at the same time.
133
+ * Locations beyond bank2 are caught by
134
+ * flash_stm32_range_exists.
135
+ */
136
+ if ((offset < BANK2_OFFSET ) &&
137
+ (offset + len > FLASH_SIZE / 2 )) {
138
+ return false;
139
+ }
140
+ }
141
+
142
+ if (write && !flash_stm32_valid_write (offset , len )) {
143
+ return false;
144
+ }
145
+
146
+ return flash_stm32_range_exists (dev , offset , len );
147
+ }
148
+
108
149
static int write_qword (const struct device * dev , off_t offset , const uint32_t * buff )
109
150
{
110
151
FLASH_TypeDef * regs = FLASH_STM32_REGS (dev );
@@ -172,9 +213,40 @@ static int erase_page(const struct device *dev, unsigned int offset)
172
213
return rc ;
173
214
}
174
215
216
+ #if defined(FLASH_OPTR_DUAL_BANK )
217
+ bool bank_swap ;
218
+ /* Check whether bank1/2 are swapped */
219
+ bank_swap =
220
+ ((regs -> OPTR & FLASH_OPTR_SWAP_BANK ) == FLASH_OPTR_SWAP_BANK );
221
+
222
+ if ((offset < (FLASH_SIZE / 2 )) && !bank_swap ) {
223
+ /* The pages to be erased is in bank 1 */
224
+ regs -> NSCR &= ~FLASH_STM32_NSBKER_MSK ;
225
+ page = offset / FLASH_PAGE_SIZE ;
226
+ LOG_DBG ("Erase page %d on bank 1" , page );
227
+ } else if ((offset >= BANK2_OFFSET ) && bank_swap ) {
228
+ /* The pages to be erased is in bank 1 */
229
+ regs -> NSCR &= ~FLASH_STM32_NSBKER_MSK ;
230
+ page = (offset - BANK2_OFFSET ) / FLASH_PAGE_SIZE ;
231
+ LOG_DBG ("Erase page %d on bank 1" , page );
232
+ } else if ((offset < (FLASH_SIZE / 2 )) && bank_swap ) {
233
+ /* The pages to be erased is in bank 2 */
234
+ regs -> NSCR |= FLASH_STM32_NSBKER ;
235
+ page = offset / FLASH_PAGE_SIZE ;
236
+ LOG_DBG ("Erase page %d on bank 2" , page );
237
+ } else if ((offset >= BANK2_OFFSET ) && !bank_swap ) {
238
+ /* The pages to be erased is in bank 2 */
239
+ regs -> NSCR |= FLASH_STM32_NSBKER ;
240
+ page = (offset - BANK2_OFFSET ) / FLASH_PAGE_SIZE ;
241
+ LOG_DBG ("Erase page %d on bank 2" , page );
242
+ } else {
243
+ LOG_ERR ("Offset %d does not exist" , offset );
244
+ return - EINVAL ;
245
+ }
246
+ #else
175
247
page = offset / FLASH_PAGE_SIZE ;
176
248
LOG_DBG ("Erase page %d\n" , page );
177
-
249
+ #endif
178
250
/* Set the NSPER bit and select the page you wish to erase */
179
251
regs -> NSCR |= FLASH_STM32_NSPER ;
180
252
regs -> NSCR &= ~FLASH_STM32_NSPNB_MSK ;
@@ -282,6 +354,55 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset,
282
354
return rc ;
283
355
}
284
356
357
+ #if defined(FLASH_OPTR_DUAL_BANK )
358
+ /* The STM32WBA6x has a dual-bank flash */
359
+ void flash_stm32_page_layout (const struct device * dev ,
360
+ const struct flash_pages_layout * * layout ,
361
+ size_t * layout_size )
362
+ {
363
+ static struct flash_pages_layout stm32_flash_layout [3 ];
364
+ static size_t stm32_flash_layout_size ;
365
+
366
+ * layout = stm32_flash_layout ;
367
+
368
+ if (stm32_flash_layout [0 ].pages_count != 0 ) {
369
+ /* Short circuit calculation logic if already performed (size is known) */
370
+ * layout_size = stm32_flash_layout_size ;
371
+ return ;
372
+ }
373
+
374
+ if (STM32_FLASH_HAS_2_BANKS (dev ) &&
375
+ (CONFIG_FLASH_SIZE < STM32_SERIES_MAX_FLASH )) {
376
+ /* For device, which has space between banks 1 and 2 */
377
+
378
+ /* Bank1 */
379
+ stm32_flash_layout [0 ].pages_count = PAGES_PER_BANK ;
380
+ stm32_flash_layout [0 ].pages_size = FLASH_PAGE_SIZE ;
381
+
382
+ /* Dummy page corresponding to space between banks 1 and 2 */
383
+ stm32_flash_layout [1 ].pages_count = 1 ;
384
+ stm32_flash_layout [1 ].pages_size = BANK2_OFFSET
385
+ - (PAGES_PER_BANK * FLASH_PAGE_SIZE );
386
+
387
+ /* Bank2 */
388
+ stm32_flash_layout [2 ].pages_count = PAGES_PER_BANK ;
389
+ stm32_flash_layout [2 ].pages_size = FLASH_PAGE_SIZE ;
390
+
391
+ stm32_flash_layout_size = ARRAY_SIZE (stm32_flash_layout );
392
+ } else {
393
+ /*
394
+ * For device, which has no space between banks 1 and 2
395
+ * Considering one layout of full flash size, even with 2 banks
396
+ */
397
+ stm32_flash_layout [0 ].pages_count = FLASH_SIZE / FLASH_PAGE_SIZE ;
398
+ stm32_flash_layout [0 ].pages_size = FLASH_PAGE_SIZE ;
399
+
400
+ stm32_flash_layout_size = 1 ;
401
+ }
402
+
403
+ * layout_size = stm32_flash_layout_size ;
404
+ }
405
+ #else
285
406
void flash_stm32_page_layout (const struct device * dev ,
286
407
const struct flash_pages_layout * * layout ,
287
408
size_t * layout_size )
@@ -301,3 +422,4 @@ void flash_stm32_page_layout(const struct device *dev,
301
422
* layout = & stm32wba_flash_layout ;
302
423
* layout_size = 1 ;
303
424
}
425
+ #endif /* FLASH_OPTR_DUAL_BANK */
0 commit comments