drivers: flash: stm32g0: preparation for dual bank handling

This commit makes no functional changes, it only refactors the
driver such that dual bank flash handling can be easily added.

Instead of using HAL macros directly in the code, new macros
with STM32G0 prefix are defined.
The erase_page function gets passed the offset instead of the page,
and the FLASH CR reg is written once with all erase parameters.
flash_stm32_wait_flash_idle is already called before each
write to CR, consequently it is also made sure CFGBSY flag
is not set.

Signed-off-by: Thomas Stranger <thomas.stranger@outlook.com>
This commit is contained in:
Thomas Stranger 2021-08-04 22:55:20 +02:00 committed by Christopher Friedt
commit 5bf11c250d

View file

@ -21,8 +21,12 @@ LOG_MODULE_REGISTER(LOG_DOMAIN);
#include "flash_stm32.h"
#define STM32G0X_PAGE_SHIFT 11
#define STM32G0_BANK_COUNT 1
#define STM32G0_FLASH_SIZE (FLASH_SIZE)
#define STM32G0_FLASH_PAGE_SIZE (FLASH_PAGE_SIZE)
#define STM32G0_PAGES_PER_BANK \
((STM32G0_FLASH_SIZE / STM32G0_FLASH_PAGE_SIZE) / STM32G0_BANK_COUNT)
/*
* offset and len must be aligned on 8 for write,
@ -36,14 +40,6 @@ bool flash_stm32_valid_range(const struct device *dev, off_t offset,
flash_stm32_range_exists(dev, offset, len);
}
/*
* STM32G0xx devices can have up to 64 2K pages
*/
static unsigned int get_page(off_t offset)
{
return offset >> STM32G0X_PAGE_SHIFT;
}
static inline void flush_cache(FLASH_TypeDef *regs)
{
if (regs->ACR & FLASH_ACR_ICEN) {
@ -101,11 +97,12 @@ static int write_dword(const struct device *dev, off_t offset, uint64_t val)
return rc;
}
static int erase_page(const struct device *dev, unsigned int page)
static int erase_page(const struct device *dev, unsigned int offset)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
uint32_t tmp;
int rc;
int page;
/* if the control register is locked, do not fail silently */
if (regs->CR & FLASH_CR_LOCK) {
@ -125,16 +122,17 @@ static int erase_page(const struct device *dev, unsigned int page)
*/
flush_cache(regs);
/* Set the PER bit and select the page you wish to erase */
regs->CR |= FLASH_CR_PER;
regs->CR &= ~FLASH_CR_PNB_Msk;
regs->CR |= ((page % 256) << 3);
/* Set the STRT bit */
regs->CR |= FLASH_CR_STRT;
/* flush the register write */
tmp = regs->CR;
page = offset / STM32G0_FLASH_PAGE_SIZE;
/* Set the PER bit and select the page you wish to erase */
tmp |= FLASH_CR_PER;
tmp &= ~FLASH_CR_PNB_Msk;
tmp |= ((page << FLASH_CR_PNB_Pos) & FLASH_CR_PNB_Msk);
/* Set the STRT bit and write the reg */
tmp |= FLASH_CR_STRT;
regs->CR = tmp;
/* Wait for the BSY bit */
rc = flash_stm32_wait_flash_idle(dev);
@ -148,11 +146,11 @@ int flash_stm32_block_erase_loop(const struct device *dev,
unsigned int offset,
unsigned int len)
{
int i, rc = 0;
unsigned int addr = offset;
int rc = 0;
i = get_page(offset);
for (; i <= get_page(offset + len - 1) ; ++i) {
rc = erase_page(dev, i);
for (; addr <= offset + len - 1 ; addr += STM32G0_FLASH_PAGE_SIZE) {
rc = erase_page(dev, addr);
if (rc < 0) {
break;
}
@ -188,8 +186,9 @@ void flash_stm32_page_layout(const struct device *dev,
ARG_UNUSED(dev);
if (stm32g0_flash_layout.pages_count == 0) {
stm32g0_flash_layout.pages_count = FLASH_SIZE / FLASH_PAGE_SIZE;
stm32g0_flash_layout.pages_size = FLASH_PAGE_SIZE;
stm32g0_flash_layout.pages_count =
STM32G0_FLASH_SIZE / STM32G0_FLASH_PAGE_SIZE;
stm32g0_flash_layout.pages_size = STM32G0_FLASH_PAGE_SIZE;
}
*layout = &stm32g0_flash_layout;