diff options
Diffstat (limited to 'stm-flash.c')
-rw-r--r-- | stm-flash.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/stm-flash.c b/stm-flash.c new file mode 100644 index 0000000..991379b --- /dev/null +++ b/stm-flash.c @@ -0,0 +1,138 @@ +/* + * stm-flash.c + * ----------- + * Functions for writing/erasing the STM32 internal flash memory. + * The flash is memory mapped, so no code is needed here to read it. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - 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. + * + * - Neither the name of the NORDUnet 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. + */ + +#include "stm32f4xx_hal.h" +#include "stm-flash.h" +#include "stm-init.h" + + +/* Flash sector offsets from RM0090, Table 6. Flash module - 2 Mbyte dual bank organization */ +#define FLASH_NUM_SECTORS 24 +uint32_t flash_sector_offsets[FLASH_NUM_SECTORS + 1] = { + /* Bank 1 */ + 0x08000000, /* #0, 16 KBytes */ + 0x08004000, /* #1, 16 Kbytes */ + 0x08008000, /* #2, 16 Kbytes */ + 0x0800C000, /* #3, 16 Kbytes */ + 0x08010000, /* #4, 64 Kbytes */ + 0x08020000, /* #5, 128 Kbytes */ + 0x08040000, /* #6, 128 Kbytes */ + 0x08060000, /* #7, 128 Kbytes */ + 0x08080000, /* #8, 128 Kbytes */ + 0x080A0000, /* #9, 128 Kbytes */ + 0x080C0000, /* #10, 128 Kbytes */ + 0x080E0000, /* #11, 128 Kbytes */ + /* Bank 2 */ + 0x08100000, /* #12, 16 Kbytes */ + 0x08104000, /* #13, 16 Kbytes */ + 0x08108000, /* #14, 16 Kbytes */ + 0x0810C000, /* #15, 16 Kbytes */ + 0x08110000, /* #16, 64 Kbytes */ + 0x08120000, /* #17, 128 Kbytes */ + 0x08140000, /* #18, 128 Kbytes */ + 0x08160000, /* #19, 128 Kbytes */ + 0x08180000, /* #20, 128 Kbytes */ + 0x081A0000, /* #21, 128 Kbytes */ + 0x081C0000, /* #22, 128 Kbytes */ + 0x081E0000, /* #23, 128 Kbytes */ + 0x08200000 /* first address *after* flash */ +}; + +int stm_flash_sector_num(const uint32_t offset) +{ + int i = FLASH_NUM_SECTORS; + + while (i-- >= 0) { + if (offset >= flash_sector_offsets[i] && + offset < flash_sector_offsets[i + 1]) { + return i; + } + } + return -1; +} + +int stm_flash_erase_sectors(const uint32_t start_offset, const uint32_t end_offset) +{ + uint32_t start_sector = stm_flash_sector_num(start_offset); + uint32_t end_sector = stm_flash_sector_num(end_offset); + FLASH_EraseInitTypeDef FLASH_EraseInitStruct; + uint32_t SectorError = 0; + + if (start_sector > end_sector) return -1; + if (start_sector < 0 || end_sector > FLASH_NUM_SECTORS) return -2; + + FLASH_EraseInitStruct.Sector = start_sector; + FLASH_EraseInitStruct.NbSectors = (end_sector - start_sector) + 1; + FLASH_EraseInitStruct.TypeErase = TYPEERASE_SECTORS; + FLASH_EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; + + HAL_FLASH_Unlock(); + + if (HAL_FLASHEx_Erase(&FLASH_EraseInitStruct, &SectorError) != HAL_OK) { + return -3; + } + + HAL_FLASH_Lock(); + + if (SectorError == 0xFFFFFFFF) return 0; + + return -3; +} + +int stm_flash_write32(uint32_t offset, const uint32_t *buf, const uint32_t elements) +{ + uint32_t sector = stm_flash_sector_num(offset); + uint32_t i, j; + + if (offset == flash_sector_offsets[sector]) { + /* Request to write to beginning of a flash sector, erase it first. */ + if (stm_flash_erase_sectors(offset, offset) != 0) { + return -1; + } + } + + HAL_FLASH_Unlock(); + + for (i = 0; i < elements; i++) { + if ((j = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, offset, buf[i])) != HAL_OK) { + return -2; + } + offset += 4; + } + + HAL_FLASH_Lock(); + + return 1; +} |