drivers: flash: Remove redundant code in STM32 drivers

Several STM32 chips have identical chip-specific code that has been
duplicated in different source files. Unify the F0x, F1x, and F3x to
use a single implementation.

Signed-off-by: Andreas Sandberg <andreas@sandberg.pp.se>
This commit is contained in:
Andreas Sandberg 2020-05-11 10:51:05 +01:00 committed by Anas Nashif
commit b9da052e51
5 changed files with 24 additions and 348 deletions

View file

@ -20,9 +20,7 @@ zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_RV32M1 soc_flash_rv32m1.c)
if(CONFIG_SOC_FLASH_STM32) if(CONFIG_SOC_FLASH_STM32)
zephyr_sources(flash_stm32.c) zephyr_sources(flash_stm32.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32F0X flash_stm32f0x.c) zephyr_sources_ifdef(CONFIG_SOC_FLASH_STM32_V1 flash_stm32_v1.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32F1X flash_stm32f1x.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32F3X flash_stm32f3x.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32F4X flash_stm32f4x.c) zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32F4X flash_stm32f4x.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32F7X flash_stm32f7x.c) zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32F7X flash_stm32f7x.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32L4X flash_stm32l4x.c) zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32L4X flash_stm32l4x.c)

View file

@ -10,18 +10,15 @@ config SOC_FLASH_STM32
depends on (SOC_SERIES_STM32F0X || SOC_SERIES_STM32F1X || SOC_SERIES_STM32F3X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X || SOC_SERIES_STM32L4X || SOC_SERIES_STM32WBX || SOC_SERIES_STM32G0X || SOC_SERIES_STM32G4X) depends on (SOC_SERIES_STM32F0X || SOC_SERIES_STM32F1X || SOC_SERIES_STM32F3X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X || SOC_SERIES_STM32L4X || SOC_SERIES_STM32WBX || SOC_SERIES_STM32G0X || SOC_SERIES_STM32G4X)
select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_DRIVER_ENABLED
default y default y
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F0X select SOC_FLASH_STM32_V1 if SOC_SERIES_STM32F0X
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F1X select SOC_FLASH_STM32_V1 if SOC_SERIES_STM32F1X
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F3X select SOC_FLASH_STM32_V1 if SOC_SERIES_STM32F3X
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32G0X select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32G0X
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F4X select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F4X
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F7X select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F7X
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32L4X select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32L4X
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32WBX select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32WBX
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32G4X select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32G4X
select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32F0X
select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32F1X
select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32F3X
select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32G0X select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32G0X
select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32F4X select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32F4X
select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32F7X select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32F7X
@ -31,3 +28,10 @@ config SOC_FLASH_STM32
help help
Enable STM32F0x, STM32F3x, STM32F4x, STM32F7x, STM32L4x, STM32WBx, Enable STM32F0x, STM32F3x, STM32F4x, STM32F7x, STM32L4x, STM32WBx,
STM32G0x or STM32G4x series flash driver. STM32G0x or STM32G4x series flash driver.
config SOC_FLASH_STM32_V1
bool
select FLASH_PAGE_LAYOUT
select FLASH_HAS_PAGE_LAYOUT
help
Enable the generic backend for the STM32 flash driver.

View file

@ -1,13 +1,12 @@
/* /*
* Copyright (c) 2017 BayLibre, SAS * Copyright (c) 2017 BayLibre, SAS
* Copyright (c) 2019 Linaro Limited
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#define LOG_DOMAIN flash_stm32f0
#define LOG_LEVEL CONFIG_FLASH_LOG_LEVEL
#include <logging/log.h> #include <logging/log.h>
LOG_MODULE_REGISTER(LOG_DOMAIN); LOG_MODULE_REGISTER(flash_stm32generic, CONFIG_FLASH_LOG_LEVEL);
#include <kernel.h> #include <kernel.h>
#include <device.h> #include <device.h>
@ -148,19 +147,24 @@ void flash_stm32_page_layout(struct device *dev,
const struct flash_pages_layout **layout, const struct flash_pages_layout **layout,
size_t *layout_size) size_t *layout_size)
{ {
static struct flash_pages_layout stm32f0_flash_layout = { static struct flash_pages_layout flash_layout = {
.pages_count = 0, .pages_count = 0,
.pages_size = 0, .pages_size = 0,
}; };
ARG_UNUSED(dev); ARG_UNUSED(dev);
if (stm32f0_flash_layout.pages_count == 0) { if (flash_layout.pages_count == 0) {
stm32f0_flash_layout.pages_count = (CONFIG_FLASH_SIZE * 1024) / #if defined(CONFIG_SOC_SERIES_STM32F3X)
FLASH_PAGE_SIZE; flash_layout.pages_count =
stm32f0_flash_layout.pages_size = FLASH_PAGE_SIZE; DT_REG_SIZE(DT_INST(0, soc_nv_flash)) / FLASH_PAGE_SIZE;
#else
flash_layout.pages_count = (CONFIG_FLASH_SIZE * 1024) /
FLASH_PAGE_SIZE;
#endif
flash_layout.pages_size = FLASH_PAGE_SIZE;
} }
*layout = &stm32f0_flash_layout; *layout = &flash_layout;
*layout_size = 1; *layout_size = 1;
} }

View file

@ -1,167 +0,0 @@
/*
* Copyright (c) 2017 BayLibre, SAS
* Copyright (c) 2019 Feng Cheng
*
* SPDX-License-Identifier: Apache-2.0
*/
#define LOG_DOMAIN flash_stm32f1
#define LOG_LEVEL CONFIG_FLASH_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(LOG_DOMAIN);
#include <kernel.h>
#include <device.h>
#include <string.h>
#include <drivers/flash.h>
#include <init.h>
#include <soc.h>
#include "flash_stm32.h"
/* offset and len must be aligned on 2 for write
* positive and not beyond end of flash
*/
bool flash_stm32_valid_range(struct device *dev, off_t offset, uint32_t len,
bool write)
{
return (!write || (offset % 2 == 0 && len % 2 == 0U)) &&
flash_stm32_range_exists(dev, offset, len);
}
static unsigned int get_page(off_t offset)
{
return offset / FLASH_PAGE_SIZE;
}
static int write_hword(struct device *dev, off_t offset, uint16_t val)
{
volatile uint16_t *flash = (uint16_t *)(offset + CONFIG_FLASH_BASE_ADDRESS);
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
uint32_t tmp;
int rc;
/* if the control register is locked, do not fail silently */
if (regs->CR & FLASH_CR_LOCK) {
return -EIO;
}
/* Check that no Flash main memory operation is ongoing */
rc = flash_stm32_wait_flash_idle(dev);
if (rc < 0) {
return rc;
}
/* Check if this half word is erased */
if (*flash != 0xFFFF) {
return -EIO;
}
/* Set the PG bit */
regs->CR |= FLASH_CR_PG;
/* Flush the register write */
tmp = regs->CR;
/* Perform the data write operation at the desired memory address */
*flash = val;
/* Wait until the BSY bit is cleared */
rc = flash_stm32_wait_flash_idle(dev);
/* Clear the PG bit */
regs->CR &= (~FLASH_CR_PG);
return rc;
}
static int erase_page(struct device *dev, unsigned int page)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
uint32_t page_address = CONFIG_FLASH_BASE_ADDRESS;
uint32_t tmp;
int rc;
/* if the control register is locked, do not fail silently */
if (regs->CR & FLASH_CR_LOCK) {
return -EIO;
}
/* Check that no Flash memory operation is ongoing */
rc = flash_stm32_wait_flash_idle(dev);
if (rc < 0) {
return rc;
}
/* Calculate the flash page address */
page_address += page * FLASH_PAGE_SIZE;
/* Set the PER bit and select the page you wish to erase */
regs->CR |= FLASH_CR_PER;
regs->AR = page_address;
/* Set the STRT bit */
regs->CR |= FLASH_CR_STRT;
/* flush the register write */
tmp = regs->CR;
/* Wait for the BSY bit */
rc = flash_stm32_wait_flash_idle(dev);
regs->CR &= ~FLASH_CR_PER;
return rc;
}
int flash_stm32_block_erase_loop(struct device *dev, unsigned int offset,
unsigned int len)
{
int i, rc = 0;
i = get_page(offset);
for (; i <= get_page(offset + len - 1) ; ++i) {
rc = erase_page(dev, i);
if (rc < 0) {
break;
}
}
return rc;
}
int flash_stm32_write_range(struct device *dev, unsigned int offset,
const void *data, unsigned int len)
{
int i, rc = 0;
for (i = 0; i < len; i += 2, offset += 2U) {
rc = write_hword(dev, offset, ((const uint16_t *) data)[i>>1]);
if (rc < 0) {
return rc;
}
}
return rc;
}
void flash_stm32_page_layout(struct device *dev,
const struct flash_pages_layout **layout,
size_t *layout_size)
{
static struct flash_pages_layout stm32f0_flash_layout = {
.pages_count = 0,
.pages_size = 0,
};
ARG_UNUSED(dev);
if (stm32f0_flash_layout.pages_count == 0) {
stm32f0_flash_layout.pages_count = (CONFIG_FLASH_SIZE * 1024) /
FLASH_PAGE_SIZE;
stm32f0_flash_layout.pages_size = FLASH_PAGE_SIZE;
}
*layout = &stm32f0_flash_layout;
*layout_size = 1;
}

View file

@ -1,163 +0,0 @@
/*
* Copyright (c) 2019 Linaro Limited
*
* SPDX-License-Identifier: Apache-2.0
*/
#define LOG_DOMAIN flash_stm32f3
#define LOG_LEVEL CONFIG_FLASH_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(LOG_DOMAIN);
#include <kernel.h>
#include <device.h>
#include <string.h>
#include <drivers/flash.h>
#include <init.h>
#include <soc.h>
#include "flash_stm32.h"
/* offset and len must be aligned on 2 for write
* , positive and not beyond end of flash */
bool flash_stm32_valid_range(struct device *dev, off_t offset, uint32_t len,
bool write)
{
return (!write || (offset % 2 == 0 && len % 2 == 0U)) &&
flash_stm32_range_exists(dev, offset, len);
}
static unsigned int get_page(off_t offset)
{
return offset / FLASH_PAGE_SIZE;
}
static int erase_page(struct device *dev, unsigned int page)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
uint32_t page_address = CONFIG_FLASH_BASE_ADDRESS;
int rc;
/* if the control register is locked, do not fail silently */
if (regs->CR & FLASH_CR_LOCK) {
return -EIO;
}
/* Check that no Flash memory operation is ongoing */
rc = flash_stm32_wait_flash_idle(dev);
if (rc < 0) {
return rc;
}
page_address += page * FLASH_PAGE_SIZE;
/* Set the PER bit and select the page you wish to erase */
regs->CR |= FLASH_CR_PER;
/* Set page address */
regs->AR = page_address;
/* Set the STRT bit */
regs->CR |= FLASH_CR_STRT;
/* Wait for the BSY bit */
rc = flash_stm32_wait_flash_idle(dev);
regs->CR &= ~FLASH_CR_PER;
return rc;
}
int flash_stm32_block_erase_loop(struct device *dev, unsigned int offset,
unsigned int len)
{
int i, rc = 0;
i = get_page(offset);
for (; i <= get_page(offset + len - 1) ; ++i) {
rc = erase_page(dev, i);
if (rc < 0) {
break;
}
}
return rc;
}
static int write_hword(struct device *dev, off_t offset, uint16_t val)
{
volatile uint16_t *flash = (uint16_t *)(offset + CONFIG_FLASH_BASE_ADDRESS);
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
uint32_t tmp;
int rc;
/* if the control register is locked, do not fail silently */
if (regs->CR & FLASH_CR_LOCK) {
return -EIO;
}
/* Check that no Flash main memory operation is ongoing */
rc = flash_stm32_wait_flash_idle(dev);
if (rc < 0) {
return rc;
}
/* Check if this half word is erased */
if (*flash != 0xFFFF) {
return -EIO;
}
/* Set the PG bit */
regs->CR |= FLASH_CR_PG;
/* Flush the register write */
tmp = regs->CR;
/* Perform the data write operation at the desired memory address */
*flash = val;
/* Wait until the BSY bit is cleared */
rc = flash_stm32_wait_flash_idle(dev);
/* Clear the PG bit */
regs->CR &= (~FLASH_CR_PG);
return rc;
}
int flash_stm32_write_range(struct device *dev, unsigned int offset,
const void *data, unsigned int len)
{
int i, rc = 0;
for (i = 0; i < len; i += 2, offset += 2U) {
rc = write_hword(dev, offset, ((const uint16_t *) data)[i>>1]);
if (rc < 0) {
return rc;
}
}
return rc;
}
void flash_stm32_page_layout(struct device *dev,
const struct flash_pages_layout **layout,
size_t *layout_size)
{
static struct flash_pages_layout stm32f3_flash_layout = {
.pages_count = 0,
.pages_size = 0,
};
ARG_UNUSED(dev);
if (stm32f3_flash_layout.pages_count == 0) {
stm32f3_flash_layout.pages_count =
DT_REG_SIZE(DT_INST(0, soc_nv_flash)) / FLASH_PAGE_SIZE;
stm32f3_flash_layout.pages_size = FLASH_PAGE_SIZE;
}
*layout = &stm32f3_flash_layout;
*layout_size = 1;
}