Skip to content

Commit a60d774

Browse files
FRASTMkartben
authored andcommitted
drivers: flash: stm32wba6x add flash driver support
-The stm32wba6x has Dual Bank memory. Change the flash driver to support this OPTion given by presence of the DUAL_BANK bit (21) in the FLASH_OPTR register. -Flash erase with 2 banks: Add the control of the BKER bit of the FLASH_NSCR1 to select BANK1 or 2 of the internal flash depending on the page number >127 for BANK2 Signed-off-by: Francois Ramu <[email protected]>
1 parent 940993c commit a60d774

File tree

2 files changed

+128
-1
lines changed

2 files changed

+128
-1
lines changed

drivers/flash/flash_stm32.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,12 @@ struct flash_stm32_priv {
131131
#define FLASH_STM32_NSPNB_POS FLASH_NSCR1_PNB_Pos
132132
#define FLASH_STM32_NSPNB FLASH_NSCR1_PNB
133133
#define FLASH_STM32_NSSTRT FLASH_NSCR1_STRT
134+
/* STM32WBA6x has DUAL bank flash */
135+
#if defined(FLASH_OPTR_DUAL_BANK)
136+
#define FLASH_STM32_DBANK FLASH_OPTR_DUAL_BANK
137+
#endif /* FLASH_OPTR_DUAL_BANK */
134138
#endif /* CONFIG_SOC_SERIES_STM32U5X */
139+
135140
#if defined(FLASH_OPTR_DBANK)
136141
#define FLASH_STM32_DBANK FLASH_OPTR_DBANK
137142
#endif /* FLASH_OPTR_DBANK */

drivers/flash/flash_stm32wbax.c

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
108149
static 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
285406
void 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

Comments
 (0)