From c86f1efd9cd07b19d8b1913a7a79121e05cf4345 Mon Sep 17 00:00:00 2001 From: bcostm Date: Fri, 15 Dec 2017 14:45:11 +0100 Subject: [PATCH 1/2] STM32F2: Add Flash API support --- .../TARGET_NUCLEO_F207ZG/device/flash_data.h | 54 ++++ targets/TARGET_STM/TARGET_STM32F2/flash_api.c | 268 ++++++++++++++++++ targets/TARGET_STM/TARGET_STM32F2/objects.h | 7 + targets/targets.json | 2 +- 4 files changed, 330 insertions(+), 1 deletion(-) create mode 100644 targets/TARGET_STM/TARGET_STM32F2/TARGET_NUCLEO_F207ZG/device/flash_data.h create mode 100644 targets/TARGET_STM/TARGET_STM32F2/flash_api.c diff --git a/targets/TARGET_STM/TARGET_STM32F2/TARGET_NUCLEO_F207ZG/device/flash_data.h b/targets/TARGET_STM/TARGET_STM32F2/TARGET_NUCLEO_F207ZG/device/flash_data.h new file mode 100644 index 0000000000..f39e40d693 --- /dev/null +++ b/targets/TARGET_STM/TARGET_STM32F2/TARGET_NUCLEO_F207ZG/device/flash_data.h @@ -0,0 +1,54 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2017, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************* + */ +#ifndef MBED_FLASH_DATA_H +#define MBED_FLASH_DATA_H + +#include + +#if DEVICE_FLASH + +#define FLASH_SIZE ((uint32_t)0x100000) + +/* Base address of the Flash sectors */ +#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */ +#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */ +#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */ +#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */ + +#endif +#endif diff --git a/targets/TARGET_STM/TARGET_STM32F2/flash_api.c b/targets/TARGET_STM/TARGET_STM32F2/flash_api.c new file mode 100644 index 0000000000..e4953e7d38 --- /dev/null +++ b/targets/TARGET_STM/TARGET_STM32F2/flash_api.c @@ -0,0 +1,268 @@ +/* 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. + */ + + #if DEVICE_FLASH + +#include "flash_api.h" +#include "flash_data.h" +#include "platform/mbed_critical.h" + +static uint32_t GetSector(uint32_t Address); +static uint32_t GetSectorSize(uint32_t Sector); + +/** Initialize the flash peripheral and the flash_t object + * + * @param obj The flash object + * @return 0 for success, -1 for error + */ +int32_t flash_init(flash_t *obj) +{ + return 0; +} + +/** Uninitialize the flash peripheral and the flash_t object + * + * @param obj The flash object + * @return 0 for success, -1 for error + */ +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; + } +} + +/** Erase one sector starting at defined address + * + * The address should be at sector boundary. This function does not do any check for address alignments + * @param obj The flash object + * @param address The sector starting address + * @return 0 for success, -1 for error + */ +int32_t flash_erase_sector(flash_t *obj, uint32_t address) +{ + static FLASH_EraseInitTypeDef EraseInitStruct; + uint32_t FirstSector; + uint32_t SectorError = 0; + int32_t status = 0; + + if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) { + return -1; + } + + if (flash_unlock() != HAL_OK) { + return -1; + } + + /* Get the 1st sector to erase */ + FirstSector = GetSector(address); + + /* Fill EraseInit structure*/ + EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; + EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; + EraseInitStruct.Sector = FirstSector; + EraseInitStruct.NbSectors = 1; + + if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) { + status = -1; + } + + flash_lock(); + + return status; +} + +/** Program one page starting at defined address + * + * The page should be at page boundary, should not cross multiple sectors. + * This function does not do any check for address alignments or if size + * is aligned to a page size. + * @param obj The flash object + * @param address The sector starting address + * @param data The data buffer to be programmed + * @param size The number of bytes to program + * @return 0 for success, -1 for error + */ +int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size) +{ + int32_t status = 0; + + if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) { + return -1; + } + + if (flash_unlock() != HAL_OK) { + return -1; + } + + /* 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. */ + __HAL_FLASH_DATA_CACHE_DISABLE(); + __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); + + __HAL_FLASH_DATA_CACHE_RESET(); + __HAL_FLASH_INSTRUCTION_CACHE_RESET(); + + __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); + __HAL_FLASH_DATA_CACHE_ENABLE(); + + while ((size > 0) && (status == 0)) { + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, address, (uint64_t)*data) != HAL_OK) { + status = -1; + } else { + size--; + address++; + data++; + } + } + + flash_lock(); + + return status; +} + +/** Get sector size + * + * @param obj The flash object + * @param address The sector starting address + * @return The size of a sector (in our case considering 1 sector = 1 page) + */ +uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address) +{ + if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) { + return MBED_FLASH_INVALID_SIZE; + } else { + return (GetSectorSize(GetSector(address))); + } +} + +/** Get page size + * + * @param obj The flash object + * @param address The page starting address + * @return The size of a page (in our case the minimum programmable size) + */ +uint32_t flash_get_page_size(const flash_t *obj) +{ + // Flash of STM32F2 devices can be programed 1 byte at a time + return 1; +} + +/** Get start address for the flash region + * + * @param obj The flash object + * @return The start address for the flash region + */ +uint32_t flash_get_start_address(const flash_t *obj) +{ + return FLASH_BASE; +} + +/** Get the flash region size + * + * @param obj The flash object + * @return The flash region size + */ +uint32_t flash_get_size(const flash_t *obj) +{ + return FLASH_SIZE; +} + +/** + * @brief Gets the sector of a given address + * @param None + * @retval The sector of a given address + */ +static uint32_t GetSector(uint32_t address) +{ + uint32_t sector = 0; + uint32_t tmp = address - ADDR_FLASH_SECTOR_0; + /* This function supports 1Mb and 2Mb flash sizes */ +#if defined(ADDR_FLASH_SECTOR_16) + if (address & 0x100000) { // handle 2nd bank + /* Sector will be at least 12 */ + sector = FLASH_SECTOR_12; + tmp -= 0x100000; + address -= 0x100000; + } +#endif + if (address < ADDR_FLASH_SECTOR_4) { // 16k sectorsize + sector += tmp >>14; + } +#if defined(ADDR_FLASH_SECTOR_5) + else if (address < ADDR_FLASH_SECTOR_5) { //64k sector size + sector += FLASH_SECTOR_4; + } else { + sector += 4 + (tmp >>17); + } +#else + // In case ADDR_FLASH_SECTOR_5 is not defined, sector 4 is the last one. + else { //64k sector size + sector += FLASH_SECTOR_4; + } +#endif + return sector; +} + +/** + * @brief Gets sector Size + * @param None + * @retval The size of a given sector + */ +static uint32_t GetSectorSize(uint32_t Sector) +{ + uint32_t sectorsize = 0x00; +#if defined(FLASH_SECTOR_16) + if((Sector == FLASH_SECTOR_0) || (Sector == FLASH_SECTOR_1) || (Sector == FLASH_SECTOR_2) ||\ + (Sector == FLASH_SECTOR_3) || (Sector == FLASH_SECTOR_12) || (Sector == FLASH_SECTOR_13) ||\ + (Sector == FLASH_SECTOR_14) || (Sector == FLASH_SECTOR_15)) { + sectorsize = 16 * 1024; + } else if((Sector == FLASH_SECTOR_4) || (Sector == FLASH_SECTOR_16)) { +#else +if((Sector == FLASH_SECTOR_0) || (Sector == FLASH_SECTOR_1) || (Sector == FLASH_SECTOR_2) ||\ + (Sector == FLASH_SECTOR_3)) { + sectorsize = 16 * 1024; + } else if(Sector == FLASH_SECTOR_4) { +#endif + sectorsize = 64 * 1024; + } else { + sectorsize = 128 * 1024; + } + return sectorsize; +} + +#endif diff --git a/targets/TARGET_STM/TARGET_STM32F2/objects.h b/targets/TARGET_STM/TARGET_STM32F2/objects.h index a961a63a44..7359e18a6c 100644 --- a/targets/TARGET_STM/TARGET_STM32F2/objects.h +++ b/targets/TARGET_STM/TARGET_STM32F2/objects.h @@ -145,6 +145,13 @@ struct can_s { }; #endif +#if DEVICE_FLASH +struct flash_s { + /* nothing to be stored for now */ + uint32_t dummy; +}; +#endif + #define GPIO_IP_WITHOUT_BRR #include "gpio_object.h" diff --git a/targets/targets.json b/targets/targets.json index dfd17df2b5..0db80c4cd2 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -904,7 +904,7 @@ }, "detect_code": ["0835"], "macros_add": ["USBHOST_OTHER"], - "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_ASYNCH", "SERIAL_FC"], + "device_has_add": ["ANALOGOUT", "CAN", "SERIAL_ASYNCH", "SERIAL_FC", "FLASH"], "features": ["LWIP"], "release_versions": ["2", "5"], "device_name": "STM32F207ZG" From 0d3e189545ef1b3520d74bd315e804dd4aa5fd99 Mon Sep 17 00:00:00 2001 From: bcostm Date: Mon, 18 Dec 2017 15:38:35 +0100 Subject: [PATCH 2/2] STM32F2: Remove flash functions doc --- targets/TARGET_STM/TARGET_STM32F2/flash_api.c | 76 ++++--------------- 1 file changed, 13 insertions(+), 63 deletions(-) diff --git a/targets/TARGET_STM/TARGET_STM32F2/flash_api.c b/targets/TARGET_STM/TARGET_STM32F2/flash_api.c index e4953e7d38..321647cf09 100644 --- a/targets/TARGET_STM/TARGET_STM32F2/flash_api.c +++ b/targets/TARGET_STM/TARGET_STM32F2/flash_api.c @@ -23,26 +23,6 @@ static uint32_t GetSector(uint32_t Address); static uint32_t GetSectorSize(uint32_t Sector); -/** Initialize the flash peripheral and the flash_t object - * - * @param obj The flash object - * @return 0 for success, -1 for error - */ -int32_t flash_init(flash_t *obj) -{ - return 0; -} - -/** Uninitialize the flash peripheral and the flash_t object - * - * @param obj The flash object - * @return 0 for success, -1 for error - */ -int32_t flash_free(flash_t *obj) -{ - return 0; -} - static int32_t flash_unlock(void) { /* Allow Access to Flash control registers and user Falsh */ @@ -64,13 +44,16 @@ static int32_t flash_lock(void) } } -/** Erase one sector starting at defined address - * - * The address should be at sector boundary. This function does not do any check for address alignments - * @param obj The flash object - * @param address The sector starting address - * @return 0 for success, -1 for error - */ +int32_t flash_init(flash_t *obj) +{ + return 0; +} + +int32_t flash_free(flash_t *obj) +{ + return 0; +} + int32_t flash_erase_sector(flash_t *obj, uint32_t address) { static FLASH_EraseInitTypeDef EraseInitStruct; @@ -104,17 +87,6 @@ int32_t flash_erase_sector(flash_t *obj, uint32_t address) return status; } -/** Program one page starting at defined address - * - * The page should be at page boundary, should not cross multiple sectors. - * This function does not do any check for address alignments or if size - * is aligned to a page size. - * @param obj The flash object - * @param address The sector starting address - * @param data The data buffer to be programmed - * @param size The number of bytes to program - * @return 0 for success, -1 for error - */ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size) { int32_t status = 0; @@ -155,13 +127,7 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, return status; } -/** Get sector size - * - * @param obj The flash object - * @param address The sector starting address - * @return The size of a sector (in our case considering 1 sector = 1 page) - */ -uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address) +uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address) { if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) { return MBED_FLASH_INVALID_SIZE; @@ -170,34 +136,18 @@ uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address) } } -/** Get page size - * - * @param obj The flash object - * @param address The page starting address - * @return The size of a page (in our case the minimum programmable size) - */ uint32_t flash_get_page_size(const flash_t *obj) { // Flash of STM32F2 devices can be programed 1 byte at a time return 1; } -/** Get start address for the flash region - * - * @param obj The flash object - * @return The start address for the flash region - */ -uint32_t flash_get_start_address(const flash_t *obj) +uint32_t flash_get_start_address(const flash_t *obj) { return FLASH_BASE; } -/** Get the flash region size - * - * @param obj The flash object - * @return The flash region size - */ -uint32_t flash_get_size(const flash_t *obj) +uint32_t flash_get_size(const flash_t *obj) { return FLASH_SIZE; }