drivers/flash: STM32: Adding flash driver for nucleo_f207zg

This commit adds the flash driver for nucleo_f207zg platform.
This has been tested with flash test application.

Signed-off-by: Krishna Mohan Dani <krishnamohan.d@hcl.com>
This commit is contained in:
Krishna Mohan Dani 2021-05-21 21:40:57 +05:30 committed by Carles Cufí
parent fcc38a9080
commit 27435cf6e5
4 changed files with 209 additions and 4 deletions

View file

@ -37,6 +37,7 @@ if(CONFIG_SOC_FLASH_STM32)
zephyr_sources(flash_stm32.c)
zephyr_sources_ifdef(CONFIG_SOC_FLASH_STM32_V1 flash_stm32_v1.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32F2X flash_stm32f2x.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_STM32L4X flash_stm32l4x.c)

View file

@ -7,7 +7,7 @@
config SOC_FLASH_STM32
bool "STM32 flash driver"
depends on SOC_FAMILY_STM32
depends on (SOC_SERIES_STM32F0X || SOC_SERIES_STM32F1X || SOC_SERIES_STM32F3X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X || SOC_SERIES_STM32L0X || SOC_SERIES_STM32L1X || SOC_SERIES_STM32L4X || SOC_SERIES_STM32WBX || SOC_SERIES_STM32G0X || SOC_SERIES_STM32G4X || SOC_SERIES_STM32H7X)
depends on (SOC_SERIES_STM32F0X || SOC_SERIES_STM32F1X || SOC_SERIES_STM32F2X || SOC_SERIES_STM32F3X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X || SOC_SERIES_STM32L0X || SOC_SERIES_STM32L1X || SOC_SERIES_STM32L4X || SOC_SERIES_STM32WBX || SOC_SERIES_STM32G0X || SOC_SERIES_STM32G4X || SOC_SERIES_STM32H7X)
select FLASH_HAS_DRIVER_ENABLED
default y
select SOC_FLASH_STM32_V1 if SOC_SERIES_STM32F0X
@ -16,6 +16,7 @@ config SOC_FLASH_STM32
select SOC_FLASH_STM32_V1 if SOC_SERIES_STM32L0X
select SOC_FLASH_STM32_V1 if SOC_SERIES_STM32L1X
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32G0X
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F2X
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F4X
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F7X
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32L4X
@ -23,6 +24,7 @@ config SOC_FLASH_STM32
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32G4X
select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32H7X
select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32G0X
select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32F2X
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_STM32L4X
@ -31,9 +33,9 @@ config SOC_FLASH_STM32
select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32H7X
select MPU_ALLOW_FLASH_WRITE if ARM_MPU
help
Enable STM32F0x, STM32F1x, STM32F3x, STM32F4x, STM32F7x, STM32L0x,
STM32L1x, STM32L4x, STM32WBx, STM32G0x, STM32G4x or STM3H7x series
flash driver.
Enable STM32F0x, STM32F1x, STM32F2x, STM32F3x, STM32F4x, STM32F7x,
STM32L0x, STM32L1x, STM32L4x, STM32WBx, STM32G0x, STM32G4x or STM3H7x
series flash driver.
config SOC_FLASH_STM32_V1
bool

View file

@ -30,6 +30,9 @@ LOG_MODULE_REGISTER(flash_stm32, CONFIG_FLASH_LOG_LEVEL);
/* STM32F3: maximum erase time of 40ms for a 2K sector */
#elif defined(CONFIG_SOC_SERIES_STM32F1X)
#define STM32_FLASH_MAX_ERASE_TIME 40
/* STM32F2: maximum erase time of 4s for a 128K sector */
#elif defined(CONFIG_SOC_SERIES_STM32F2X)
#define STM32_FLASH_MAX_ERASE_TIME 4000
/* STM32F3: maximum erase time of 40ms for a 2K sector */
#elif defined(CONFIG_SOC_SERIES_STM32F3X)
#define STM32_FLASH_MAX_ERASE_TIME 40

View file

@ -0,0 +1,199 @@
/*
* Copyright (c) 2021 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <kernel.h>
#include <device.h>
#include <string.h>
#include <drivers/flash.h>
#include <init.h>
#include <soc.h>
#include "flash_stm32.h"
bool flash_stm32_valid_range(const struct device *dev, off_t offset,
uint32_t len,
bool write)
{
ARG_UNUSED(write);
return flash_stm32_range_exists(dev, offset, len);
}
static inline void flush_cache(FLASH_TypeDef *regs)
{
/* If Data cache is enabled, disable Data cache, reset Data cache
* and then re-enable Data cache.
*/
if (regs->ACR & FLASH_ACR_DCEN) {
regs->ACR &= ~FLASH_ACR_DCEN;
/* Datasheet: DCRST: Data cache reset
* This bit can be written only when the Data cache is disabled
*/
regs->ACR |= FLASH_ACR_DCRST;
regs->ACR &= ~FLASH_ACR_DCRST;
regs->ACR |= FLASH_ACR_DCEN;
}
/* If Instruction cache is enabled, disable Instruction cache, reset
* Instruction cache and then re-enable Instruction cache.
*/
if (regs->ACR & FLASH_ACR_ICEN) {
regs->ACR &= ~FLASH_ACR_ICEN;
/* Datasheet: ICRST: Instruction cache reset
* This bit can be written only when the Instruction cache
* is disabled
*/
regs->ACR |= FLASH_ACR_ICRST;
regs->ACR &= ~FLASH_ACR_ICRST;
regs->ACR |= FLASH_ACR_ICEN;
}
}
static int write_byte(const struct device *dev, off_t offset, uint8_t val)
{
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;
}
regs->CR &= ~FLASH_CR_PSIZE;
regs->CR |= FLASH_PSIZE_BYTE;
regs->CR |= FLASH_CR_PG;
/* flush the register write */
tmp = regs->CR;
*((uint8_t *) offset + CONFIG_FLASH_BASE_ADDRESS) = 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_sector(const struct device *dev, uint32_t sector)
{
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 memory operation is ongoing */
rc = flash_stm32_wait_flash_idle(dev);
if (rc < 0) {
return rc;
}
regs->CR &= ~FLASH_CR_SNB;
regs->CR |= FLASH_CR_SER | (sector << 3);
regs->CR |= FLASH_CR_STRT;
/* flush the register write */
tmp = regs->CR;
/* Wait for the BSY bit */
rc = flash_stm32_wait_flash_idle(dev);
flush_cache(regs);
regs->CR &= ~(FLASH_CR_SER | FLASH_CR_SNB);
return rc;
}
int flash_stm32_block_erase_loop(const struct device *dev,
unsigned int offset,
unsigned int len)
{
struct flash_pages_info info;
uint32_t start_sector, end_sector;
uint32_t i;
int rc = 0;
rc = flash_get_page_info_by_offs(dev, offset, &info);
if (rc) {
return rc;
}
start_sector = info.index;
rc = flash_get_page_info_by_offs(dev, offset + len - 1, &info);
if (rc) {
return rc;
}
end_sector = info.index;
for (i = start_sector; i <= end_sector; i++) {
rc = erase_sector(dev, i);
if (rc < 0) {
break;
}
}
return rc;
}
int flash_stm32_write_range(const struct device *dev, unsigned int offset,
const void *data, unsigned int len)
{
int i, rc = 0;
for (i = 0; i < len; i++, offset++) {
rc = write_byte(dev, offset, ((const uint8_t *) data)[i]);
if (rc < 0) {
return rc;
}
}
return rc;
}
/*
* The flash memory in stm32f2 series has bank 1 only with 12 sectors,
* they are split as 4 sectors of 16 Kbytes, 1 sector of 64 Kbytes,
* and 7 sectors of 128 Kbytes.
*/
#ifndef FLASH_SECTOR_TOTAL
#error "Unknown flash layout"
#else /* defined(FLASH_SECTOR_TOTAL) */
#if FLASH_SECTOR_TOTAL == 12
static const struct flash_pages_layout stm32f2_flash_layout[] = {
/*
* PM0059, table 10: STM32F207xx
*/
{.pages_count = 4, .pages_size = KB(16)},
{.pages_count = 1, .pages_size = KB(64)},
{.pages_count = 7, .pages_size = KB(128)},
};
#else
#error "Unknown flash layout"
#endif /* FLASH_SECTOR_TOTAL == 12 */
#endif/* !defined(FLASH_SECTOR_TOTAL) */
void flash_stm32_page_layout(const struct device *dev,
const struct flash_pages_layout **layout,
size_t *layout_size)
{
ARG_UNUSED(dev);
*layout = stm32f2_flash_layout;
*layout_size = ARRAY_SIZE(stm32f2_flash_layout);
}