@@ -20,7 +20,20 @@ LOG_MODULE_REGISTER(LOG_DOMAIN);
2020
2121#include "flash_stm32.h"
2222
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
2330#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)
2437
2538#define ICACHE_DISABLE_TIMEOUT_VALUE 1U /* 1ms */
2639#define ICACHE_INVALIDATE_TIMEOUT_VALUE 1U /* 1ms */
@@ -105,6 +118,34 @@ static int icache_wait_for_invalidate_complete(void)
105118 return status ;
106119}
107120
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+
108149static int write_qword (const struct device * dev , off_t offset , const uint32_t * buff )
109150{
110151 FLASH_TypeDef * regs = FLASH_STM32_REGS (dev );
@@ -172,9 +213,40 @@ static int erase_page(const struct device *dev, unsigned int offset)
172213 return rc ;
173214 }
174215
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
175247 page = offset / FLASH_PAGE_SIZE ;
176248 LOG_DBG ("Erase page %d\n" , page );
177-
249+ #endif
178250 /* Set the NSPER bit and select the page you wish to erase */
179251 regs -> NSCR |= FLASH_STM32_NSPER ;
180252 regs -> NSCR &= ~FLASH_STM32_NSPNB_MSK ;
@@ -282,6 +354,55 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset,
282354 return rc ;
283355}
284356
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
285406void flash_stm32_page_layout (const struct device * dev ,
286407 const struct flash_pages_layout * * layout ,
287408 size_t * layout_size )
@@ -301,3 +422,4 @@ void flash_stm32_page_layout(const struct device *dev,
301422 * layout = & stm32wba_flash_layout ;
302423 * layout_size = 1 ;
303424}
425+ #endif /* FLASH_OPTR_DUAL_BANK */
0 commit comments