diff --git a/drivers/flash/CMakeLists.txt b/drivers/flash/CMakeLists.txt index 7ae48398acc..db42c60984a 100644 --- a/drivers/flash/CMakeLists.txt +++ b/drivers/flash/CMakeLists.txt @@ -20,8 +20,10 @@ zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_STM32 endif() if(CONFIG_SOC_SERIES_STM32F3X) -zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_STM32 flash_stm32f3x.c) -zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_STM32 flash_stm32f3x_priv.c) +zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_STM32 + flash_stm32.c + flash_stm32f3x.c + ) endif() if(CONFIG_SOC_SERIES_STM32F4X) diff --git a/drivers/flash/Kconfig.stm32 b/drivers/flash/Kconfig.stm32 index de9fe30b6a8..6113707a3d2 100644 --- a/drivers/flash/Kconfig.stm32 +++ b/drivers/flash/Kconfig.stm32 @@ -14,10 +14,12 @@ menuconfig SOC_FLASH_STM32 select FLASH_HAS_DRIVER_ENABLED default y select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F0X + select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F3X select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F4X select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32F7X select FLASH_PAGE_LAYOUT if SOC_SERIES_STM32L4X select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32F0X + select FLASH_HAS_PAGE_LAYOUT if SOC_SERIES_STM32F3X 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 diff --git a/drivers/flash/flash_stm32.c b/drivers/flash/flash_stm32.c index 02250ae5336..f4e8f4e7ed9 100644 --- a/drivers/flash/flash_stm32.c +++ b/drivers/flash/flash_stm32.c @@ -17,6 +17,9 @@ /* STM32F0: maximum erase time of 40ms for a 2K sector */ #if defined(CONFIG_SOC_SERIES_STM32F0X) #define STM32_FLASH_TIMEOUT (K_MSEC(40)) +/* STM32F3: maximum erase time of 40ms for a 2K sector */ +#elif defined(CONFIG_SOC_SERIES_STM32F3X) +#define STM32_FLASH_TIMEOUT (K_MSEC(40)) /* STM32F4: maximum erase time of 4s for a 128K sector */ #elif defined(CONFIG_SOC_SERIES_STM32F4X) #define STM32_FLASH_TIMEOUT (K_MSEC(4000)) @@ -95,7 +98,7 @@ int flash_stm32_wait_flash_idle(struct device *dev) static void flash_stm32_flush_caches(struct device *dev, off_t offset, size_t len) { -#if defined(CONFIG_SOC_SERIES_STM32F0X) +#if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32F3X) ARG_UNUSED(dev); ARG_UNUSED(offset); ARG_UNUSED(len); @@ -188,6 +191,8 @@ static int flash_stm32_write_protection(struct device *dev, bool enable) struct stm32f7x_flash *regs = FLASH_STM32_REGS(dev); #elif defined(CONFIG_SOC_SERIES_STM32F0X) struct stm32f0x_flash *regs = FLASH_STM32_REGS(dev); +#elif defined(CONFIG_SOC_SERIES_STM32F3X) + struct stm32f3x_flash *regs = FLASH_STM32_REGS(dev); #elif defined(CONFIG_SOC_SERIES_STM32L4X) struct stm32l4x_flash *regs = FLASH_STM32_REGS(dev); #endif @@ -205,6 +210,11 @@ static int flash_stm32_write_protection(struct device *dev, bool enable) } else { if (regs->cr & FLASH_CR_LOCK) { regs->keyr = FLASH_KEY1; +#ifdef CONFIG_SOC_SERIES_STM32F3X + /* On STM32F3 series some time is requested */ + /* before writing again on key register */ + flash_stm32_wait_flash_idle(dev); +#endif /* CONFIG_SOC_SERIES_STM32F3X */ regs->keyr = FLASH_KEY2; } } @@ -219,6 +229,10 @@ static struct flash_stm32_priv flash_data = { .regs = (struct stm32f0x_flash *) DT_FLASH_DEV_BASE_ADDRESS, .pclken = { .bus = STM32_CLOCK_BUS_AHB1, .enr = LL_AHB1_GRP1_PERIPH_FLASH }, +#elif defined(CONFIG_SOC_SERIES_STM32F3X) + .regs = (struct stm32f3x_flash *) DT_FLASH_DEV_BASE_ADDRESS, + .pclken = { .bus = STM32_CLOCK_BUS_AHB1, + .enr = LL_AHB1_GRP1_PERIPH_FLASH }, #elif defined(CONFIG_SOC_SERIES_STM32F4X) .regs = (struct stm32f4x_flash *) DT_FLASH_DEV_BASE_ADDRESS, #elif defined(CONFIG_SOC_SERIES_STM32F7X) @@ -251,14 +265,15 @@ static int stm32_flash_init(struct device *dev) { struct flash_stm32_priv *p = FLASH_STM32_PRIV(dev); #if defined(CONFIG_SOC_SERIES_STM32L4X) || \ - defined(CONFIG_SOC_SERIES_STM32F0X) + defined(CONFIG_SOC_SERIES_STM32F0X) || \ + defined(CONFIG_SOC_SERIES_STM32F3X) struct device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME); /* * On STM32F0, Flash interface clock source is always HSI, * so statically enable HSI here. */ -#if defined(CONFIG_SOC_SERIES_STM32F0X) +#if defined(CONFIG_SOC_SERIES_STM32F0X) || defined(CONFIG_SOC_SERIES_STM32F3X) LL_RCC_HSI_Enable(); while (!LL_RCC_HSI_IsReady()) { diff --git a/drivers/flash/flash_stm32.h b/drivers/flash/flash_stm32.h index 7ad41f72701..5ad5f7c9643 100644 --- a/drivers/flash/flash_stm32.h +++ b/drivers/flash/flash_stm32.h @@ -11,7 +11,8 @@ #include #if defined(CONFIG_SOC_SERIES_STM32L4X) || \ - defined(CONFIG_SOC_SERIES_STM32F0X) + defined(CONFIG_SOC_SERIES_STM32F0X) || \ + defined(CONFIG_SOC_SERIES_STM32F3X) #include #include #endif @@ -21,6 +22,10 @@ struct flash_stm32_priv { struct stm32f0x_flash *regs; /* clock subsystem driving this peripheral */ struct stm32_pclken pclken; +#elif defined(CONFIG_SOC_SERIES_STM32F3X) + struct stm32f3x_flash *regs; + /* clock subsystem driving this peripheral */ + struct stm32_pclken pclken; #elif defined(CONFIG_SOC_SERIES_STM32F4X) struct stm32f4x_flash *regs; #elif defined(CONFIG_SOC_SERIES_STM32F7X) diff --git a/drivers/flash/flash_stm32f3x.c b/drivers/flash/flash_stm32f3x.c index 54cb556b0d0..636aac1609e 100644 --- a/drivers/flash/flash_stm32f3x.c +++ b/drivers/flash/flash_stm32f3x.c @@ -1,151 +1,168 @@ /* - * Copyright (c) 2016 RnDity Sp. z o.o. + * Copyright (c) 2019 Linaro Limited * * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include +#define LOG_DOMAIN flash_stm32f3 +#define LOG_LEVEL CONFIG_FLASH_LOG_LEVEL +#include +LOG_MODULE_REGISTER(LOG_DOMAIN); -#include "flash_stm32f3x.h" +#include +#include +#include +#include +#include +#include -static int flash_stm32_erase(struct device *dev, off_t offset, size_t size) +#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, u32_t len, + bool write) { - u32_t first_page_addr = 0U; - u32_t last_page_addr = 0U; - u16_t no_of_pages = size / CONFIG_FLASH_PAGE_SIZE; - u16_t page_index = 0U; - - /* Check offset and size alignment. */ - if (((offset % CONFIG_FLASH_PAGE_SIZE) != 0) || - ((size % CONFIG_FLASH_PAGE_SIZE) != 0) || - (no_of_pages == 0)) { - return -EINVAL; - } - - /* Find address of the first page to be erased. */ - page_index = offset / CONFIG_FLASH_PAGE_SIZE; - - first_page_addr = CONFIG_FLASH_BASE_ADDRESS + - page_index * CONFIG_FLASH_PAGE_SIZE; - - __ASSERT_NO_MSG(IS_FLASH_PROGRAM_ADDRESS(first_page_addr)); - - /* Find address of the last page to be erased. */ - page_index = ((offset + size) / CONFIG_FLASH_PAGE_SIZE) - 1; - - last_page_addr = CONFIG_FLASH_BASE_ADDRESS + - page_index * CONFIG_FLASH_PAGE_SIZE; - - __ASSERT_NO_MSG(IS_FLASH_PROGRAM_ADDRESS(last_page_addr)); - - while (no_of_pages) { - if (flash_stm32_erase_page(dev, first_page_addr) - != FLASH_COMPLETE) { - return -EINVAL; - } - no_of_pages--; - first_page_addr += CONFIG_FLASH_PAGE_SIZE; - } - - return 0; + return (!write || (offset % 2 == 0 && len % 2 == 0)) && + flash_stm32_range_exists(dev, offset, len); } -static int flash_stm32_read(struct device *dev, off_t offset, - void *data, size_t len) +static unsigned int get_page(off_t offset) { - u32_t address = CONFIG_FLASH_BASE_ADDRESS + offset; - - __ASSERT_NO_MSG(IS_FLASH_PROGRAM_ADDRESS(address)); - - flash_stm32_read_data(data, address, len); - - return 0; + return offset / FLASH_PAGE_SIZE; } -static int flash_stm32_write(struct device *dev, off_t offset, - const void *data, size_t len) +static int erase_page(struct device *dev, unsigned int page) { - u16_t halfword = 0U; + struct stm32f3x_flash *regs = FLASH_STM32_REGS(dev); + u32_t page_address = CONFIG_FLASH_BASE_ADDRESS; + int rc; - u32_t address = - CONFIG_FLASH_BASE_ADDRESS + offset; - - u8_t remainder = 0U; - - if ((len % 2) != 0) { - remainder = 1U; + /* if the control register is locked, do not fail silently */ + if (regs->cr & FLASH_CR_LOCK) { + return -EIO; } - len = len / 2; - - while (len--) { - halfword = *((u8_t *)data++); - halfword |= *((u8_t *)data++) << 8; - if (flash_stm32_program_halfword(dev, address, halfword) - != FLASH_COMPLETE) { - return -EINVAL; - } - address += 2; + /* Check that no Flash memory operation is ongoing */ + rc = flash_stm32_wait_flash_idle(dev); + if (rc < 0) { + return rc; } - if (remainder) { - halfword = (*((u16_t *)data)) & 0x00FF; - if (flash_stm32_program_halfword(dev, address, halfword) - != FLASH_COMPLETE) { - return -EINVAL; + 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; + /* Give some time to write operation to complete */ + rc = flash_stm32_wait_flash_idle(dev); + if (rc < 0) { + return rc; + } + /* 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 0; + return rc; } -static int flash_stm32_protection_set(struct device *dev, bool enable) + +static int write_hword(struct device *dev, off_t offset, u16_t val) { - if (enable) { - flash_stm32_lock(dev); - } else { - flash_stm32_unlock(dev); + volatile u16_t *flash = (u16_t *)(offset + CONFIG_FLASH_BASE_ADDRESS); + struct stm32f3x_flash *regs = FLASH_STM32_REGS(dev); + u32_t tmp; + int rc; + + /* if the control register is locked, do not fail silently */ + if (regs->cr & FLASH_CR_LOCK) { + return -EIO; } - return 0; + /* 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 flash_stm32_init(struct device *dev) + +int flash_stm32_write_range(struct device *dev, unsigned int offset, + const void *data, unsigned int len) { - const struct flash_stm32_dev_config *cfg = FLASH_CFG(dev); + int i, rc = 0; - struct device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME); + for (i = 0; i < len; i += 2, offset += 2) { + rc = write_hword(dev, offset, ((const u16_t *) data)[i>>1]); + if (rc < 0) { + return rc; + } + } - if (clock_control_on(clk, (clock_control_subsys_t *) &cfg->pclken) != 0) - return -ENODEV; - - return 0; + return rc; } -static const struct flash_driver_api flash_stm32_api = { - .read = flash_stm32_read, - .write = flash_stm32_write, - .erase = flash_stm32_erase, - .write_protection = flash_stm32_protection_set, - .write_block_size = 2, -}; +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, + }; -static const struct flash_stm32_dev_config flash_device_config = { - .base = (u32_t *)DT_FLASH_DEV_BASE_ADDRESS, - .pclken = { .bus = STM32_CLOCK_BUS_APB1, - .enr = LL_AHB1_GRP1_PERIPH_FLASH}, -}; + ARG_UNUSED(dev); -static struct flash_stm32_dev_data flash_device_data = { + if (stm32f3_flash_layout.pages_count == 0) { + stm32f3_flash_layout.pages_count = DT_FLASH_SIZE \ + * 1024 / FLASH_PAGE_SIZE; + stm32f3_flash_layout.pages_size = FLASH_PAGE_SIZE; + } -}; - -DEVICE_AND_API_INIT(flash_stm32, DT_FLASH_DEV_NAME, - flash_stm32_init, - &flash_device_data, - &flash_device_config, - POST_KERNEL, - CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - &flash_stm32_api); + *layout = &stm32f3_flash_layout; + *layout_size = 1; +} diff --git a/drivers/flash/flash_stm32f3x.h b/drivers/flash/flash_stm32f3x.h deleted file mode 100644 index e5a17884f3f..00000000000 --- a/drivers/flash/flash_stm32f3x.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2016 RnDity Sp. z o.o. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_DRIVERS_FLASH_FLASH_STM32F3X_H_ -#define ZEPHYR_DRIVERS_FLASH_FLASH_STM32F3X_H_ - -#include -#include -#include -#include - -struct flash_stm32_dev_config { - u32_t *base; - struct stm32_pclken pclken; -}; - -struct flash_stm32_dev_data { - /* For future use. */ -}; - -#define FLASH_CFG(dev) \ - ((const struct flash_stm32_dev_config * const)(dev)->config->config_info) -#define FLASH_DATA(dev) \ - ((struct flash_stm32_dev_data * const)(dev)->driver_data) -#define FLASH_STRUCT(base) \ - (volatile struct stm32_flash *)(base) - -/* Flash programming timeout definition. */ -#define FLASH_ER_PRG_TIMEOUT ((u32_t)0x000B0000) - -enum flash_status { - FLASH_BUSY = 1, - FLASH_ERROR_WRITE_PROTECTION, - FLASH_ERROR_PROGRAM, - FLASH_COMPLETE, - FLASH_TIMEOUT -}; - -void flash_stm32_lock(struct device *flash); - -void flash_stm32_unlock(struct device *flash); - -u8_t flash_stm32_program_halfword(struct device *flash, - u32_t address, - u16_t data); - -u8_t flash_stm32_program_word(struct device *flash, - u32_t address, - u32_t data); - -void flash_stm32_read_data(void *data, u32_t address, size_t len); - -u8_t flash_stm32_wait_for_last_operation(struct device *flash, - u32_t timeout); - -u8_t flash_stm32_get_status(struct device *flash); - -u8_t flash_stm32_erase_page(struct device *flash, - u32_t page_address); - -u8_t flash_stm32_erase_all_pages(struct device *flash); - -#endif /* ZEPHYR_DRIVERS_FLASH_FLASH_STM32F3X_H_ */ diff --git a/drivers/flash/flash_stm32f3x_priv.c b/drivers/flash/flash_stm32f3x_priv.c deleted file mode 100644 index ee2a33a4fb6..00000000000 --- a/drivers/flash/flash_stm32f3x_priv.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2016 RnDity Sp. z o.o. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include - -#include "flash_stm32f3x.h" - -void flash_stm32_unlock(struct device *flash) -{ - const struct flash_stm32_dev_config *config = FLASH_CFG(flash); - - volatile struct stm32_flash *reg = FLASH_STRUCT(config->base); - - if ((reg->cr & FLASH_CR_LOCK) != 0) { - /* Authorize the FLASH Registers access */ - reg->keyr = FLASH_KEY1; - reg->keyr = FLASH_KEY2; - } -} - -void flash_stm32_lock(struct device *flash) -{ - const struct flash_stm32_dev_config *config = FLASH_CFG(flash); - - volatile struct stm32_flash *reg = FLASH_STRUCT(config->base); - - reg->cr |= FLASH_CR_LOCK; -} - -u8_t flash_stm32_program_halfword(struct device *flash, - u32_t address, - u16_t data) -{ - u8_t status = FLASH_COMPLETE; - - const struct flash_stm32_dev_config *config = FLASH_CFG(flash); - - volatile struct stm32_flash *reg = FLASH_STRUCT(config->base); - - __ASSERT_NO_MSG(IS_FLASH_PROGRAM_ADDRESS(address)); - - status = flash_stm32_wait_for_last_operation(flash, - FLASH_ER_PRG_TIMEOUT); - - if (status == FLASH_COMPLETE) { - reg->cr |= FLASH_CR_PG; - - *(volatile u16_t *)address = data; - - status = flash_stm32_wait_for_last_operation(flash, - FLASH_ER_PRG_TIMEOUT); - - reg->cr &= ~FLASH_CR_PG; - } - - return status; -} - -u8_t flash_stm32_program_word(struct device *flash, - u32_t address, - u32_t data) -{ - u8_t status = FLASH_COMPLETE; - - const struct flash_stm32_dev_config *config = FLASH_CFG(flash); - - volatile struct stm32_flash *reg = FLASH_STRUCT(config->base); - - __ASSERT_NO_MSG(IS_FLASH_PROGRAM_ADDRESS(address)); - - status = flash_stm32_wait_for_last_operation(flash, - FLASH_ER_PRG_TIMEOUT); - - if (status == FLASH_COMPLETE) { - reg->cr |= FLASH_CR_PG; - - *(volatile u16_t *)address = (u16_t)data; - - status = flash_stm32_wait_for_last_operation(flash, - FLASH_ER_PRG_TIMEOUT); - - if (status == FLASH_COMPLETE) { - address += 2; - - *(volatile u16_t *)address = data >> 16; - - status = flash_stm32_wait_for_last_operation(flash, - FLASH_ER_PRG_TIMEOUT); - } - - reg->cr &= ~FLASH_CR_PG; - } - - return status; -} - -u8_t flash_stm32_wait_for_last_operation(struct device *flash, - u32_t timeout) -{ - u8_t status = FLASH_COMPLETE; - - /* Check for the FLASH Status */ - status = flash_stm32_get_status(flash); - - /* Wait for a FLASH operation to complete or a TIMEOUT to occur. */ - while ((status == FLASH_BUSY) && (timeout != 0x00)) { - status = flash_stm32_get_status(flash); - timeout--; - } - - if (timeout == 0x00) { - status = FLASH_TIMEOUT; - } - - return status; -} - -u8_t flash_stm32_get_status(struct device *flash) -{ - u8_t status = FLASH_COMPLETE; - - const struct flash_stm32_dev_config *config = FLASH_CFG(flash); - - volatile struct stm32_flash *reg = FLASH_STRUCT(config->base); - - do { - if ((reg->sr & FLASH_SR_BSY) == FLASH_SR_BSY) { - status = FLASH_BUSY; - break; - } - - if ((reg->sr & FLASH_SR_WRPERR) != (u32_t)0x00) { - status = FLASH_ERROR_WRITE_PROTECTION; - break; - } - - if ((reg->sr & FLASH_SR_PGERR) != (u32_t)0x00) { - status = FLASH_ERROR_PROGRAM; - break; - } - } while (0); - - return status; -} - -u8_t flash_stm32_erase_page(struct device *flash, - u32_t page_address) -{ - u8_t status = FLASH_COMPLETE; - - const struct flash_stm32_dev_config *config = FLASH_CFG(flash); - - volatile struct stm32_flash *reg = FLASH_STRUCT(config->base); - - __ASSERT_NO_MSG(IS_FLASH_PROGRAM_ADDRESS(page_address)); - - status = flash_stm32_wait_for_last_operation(flash, - FLASH_ER_PRG_TIMEOUT); - - if (status == FLASH_COMPLETE) { - reg->cr |= FLASH_CR_PER; - reg->ar = page_address; - reg->cr |= FLASH_CR_STRT; - - status = flash_stm32_wait_for_last_operation(flash, - FLASH_ER_PRG_TIMEOUT); - - reg->cr &= ~FLASH_CR_PER; - } - - return status; -} - -u8_t flash_stm32_erase_all_pages(struct device *flash) -{ - u8_t status = FLASH_COMPLETE; - - const struct flash_stm32_dev_config *config = FLASH_CFG(flash); - - volatile struct stm32_flash *reg = FLASH_STRUCT(config->base); - - status = flash_stm32_wait_for_last_operation(flash, - FLASH_ER_PRG_TIMEOUT); - - if (status == FLASH_COMPLETE) { - reg->cr |= FLASH_CR_MER; - reg->cr |= FLASH_CR_STRT; - - status = flash_stm32_wait_for_last_operation(flash, - FLASH_ER_PRG_TIMEOUT); - - reg->cr &= ~FLASH_CR_MER; - } - - return status; -} - -void flash_stm32_read_data(void *data, u32_t address, size_t len) -{ - u8_t *addr = INT_TO_POINTER(address); - - memcpy(data, addr, len); -} diff --git a/soc/arm/st_stm32/stm32f3/flash_registers.h b/soc/arm/st_stm32/stm32f3/flash_registers.h index 53d5dfb2970..6bdbf334e5d 100644 --- a/soc/arm/st_stm32/stm32f3/flash_registers.h +++ b/soc/arm/st_stm32/stm32f3/flash_registers.h @@ -40,7 +40,7 @@ union ef_acr { }; /* 3.3.3 Embedded flash registers */ -struct stm32_flash { +struct stm32f3x_flash { union ef_acr acr; u32_t keyr; u32_t optkeyr;