From 0d09f6d788bb4efd37a447b5276a4bf93871421b Mon Sep 17 00:00:00 2001 From: bcostm Date: Tue, 12 Dec 2017 16:52:32 +0100 Subject: [PATCH] STM32F3: add Flash api --- .../TARGET_STM32F3/common_objects.h | 7 + targets/TARGET_STM/TARGET_STM32F3/flash_api.c | 173 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 targets/TARGET_STM/TARGET_STM32F3/flash_api.c diff --git a/targets/TARGET_STM/TARGET_STM32F3/common_objects.h b/targets/TARGET_STM/TARGET_STM32F3/common_objects.h index ba731890ce..590b60d94c 100644 --- a/targets/TARGET_STM/TARGET_STM32F3/common_objects.h +++ b/targets/TARGET_STM/TARGET_STM32F3/common_objects.h @@ -132,6 +132,13 @@ struct can_s { }; #endif +#if DEVICE_FLASH +struct flash_s { + /* nothing to be stored for now */ + uint32_t dummy; +}; +#endif + #include "gpio_object.h" #ifdef __cplusplus diff --git a/targets/TARGET_STM/TARGET_STM32F3/flash_api.c b/targets/TARGET_STM/TARGET_STM32F3/flash_api.c new file mode 100644 index 0000000000..459294d045 --- /dev/null +++ b/targets/TARGET_STM/TARGET_STM32F3/flash_api.c @@ -0,0 +1,173 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "flash_api.h" +#include "mbed_critical.h" + +#if DEVICE_FLASH +#include "mbed_assert.h" +#include "cmsis.h" + +#define NUM_PAGES_IN_SECTOR (1U) +#define FLASH_SIZE (uint32_t)(*((uint16_t *)FLASHSIZE_BASE) * 1024U) + +int32_t flash_init(flash_t *obj) +{ + return 0; +} + +int32_t flash_free(flash_t *obj) +{ + return 0; +} + +static int32_t flash_unlock(void) +{ + /* Allow Access to Flash control registers and user Falsh */ + if (HAL_FLASH_Unlock()) { + return -1; + } else { + return 0; + } +} + +static int32_t flash_lock(void) +{ + /* Disable the Flash option control register access (recommended to protect + the option Bytes against possible unwanted operations) */ + if (HAL_FLASH_Lock()) { + return -1; + } else { + return 0; + } +} + +int32_t flash_erase_sector(flash_t *obj, uint32_t address) +{ + uint32_t PAGEError = 0; + FLASH_EraseInitTypeDef EraseInitStruct; + int32_t status = 0; + + if (!(IS_FLASH_PROGRAM_ADDRESS(address))) { + return -1; + } + + if (flash_unlock() != HAL_OK) { + return -1; + } + + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR); + /* MBED HAL erases 1 sector at a time */ + /* Fill EraseInit structure*/ + EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; + EraseInitStruct.PageAddress = address; + EraseInitStruct.NbPages = NUM_PAGES_IN_SECTOR; + + /* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache, + you have to make sure that these data are rewritten before they are accessed during code + execution. If this cannot be done safely, it is recommended to flush the caches by setting the + DCRST and ICRST bits in the FLASH_CR register. */ + + if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) { + status = -1; + } + + flash_lock(); + + return status; + +} + +int32_t flash_program_page(flash_t *obj, uint32_t address, + const uint8_t *data, uint32_t size) +{ + uint32_t StartAddress = 0; + int32_t status = 0; + + if (!(IS_FLASH_PROGRAM_ADDRESS(address))) { + return -1; + } + + if ((size % 4) != 0) { + /* F3 flash devices can only be programmed 32bits/4 bytes at a time */ + return -1; + } + + if (flash_unlock() != HAL_OK) { + return -1; + } + + /* Program the user Flash area word by word */ + StartAddress = address; + + /* HW needs an aligned address to program flash, which data + * parameters doesn't ensure */ + if ((uint32_t) data % 4 != 0) { + volatile uint32_t data32; + while (address < (StartAddress + size) && (status == 0)) { + for (uint8_t i =0; i < 4; i++) { + *(((uint8_t *) &data32) + i) = *(data + i); + } + + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data32) == HAL_OK) { + address = address + 4; + data = data + 4; + } else { + status = -1; + } + } + } else { /* case where data is aligned, so let's avoid any copy */ + while ((address < (StartAddress + size)) && (status == 0)) { + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, *((uint32_t*) data)) == HAL_OK) { + address = address + 4; + data = data + 4; + } else { + status = -1; + } + } + } + + flash_lock(); + + return status; +} + +uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address) +{ + if (!(IS_FLASH_PROGRAM_ADDRESS(address))) { + return MBED_FLASH_INVALID_SIZE; + } else { + return (NUM_PAGES_IN_SECTOR * FLASH_PAGE_SIZE); + } +} + +uint32_t flash_get_page_size(const flash_t *obj) +{ + /* Page size is the minimum programmable size, which is 4 bytes */ + return 4; +} + +uint32_t flash_get_start_address(const flash_t *obj) +{ + return FLASH_BASE; +} + +uint32_t flash_get_size(const flash_t *obj) +{ + return FLASH_SIZE; +} + +#endif