/* stm32f4.c * * Copyright (C) 2020 Danielinux * */ #include #include "system.h" /* STM32F4 FLASH Geometry */ #define FLASH_SECTOR_0 0x0000000 /* 16 Kb */ #define FLASH_SECTOR_1 0x0004000 /* 16 Kb */ #define FLASH_SECTOR_2 0x0008000 /* 16 Kb */ #define FLASH_SECTOR_3 0x000C000 /* 16 Kb */ #define FLASH_SECTOR_4 0x0010000 /* 64 Kb */ #define FLASH_SECTOR_5 0x0020000 /* 128 Kb */ #define FLASH_SECTOR_6 0x0040000 /* 128 Kb */ #define FLASH_SECTOR_7 0x0060000 /* 128 Kb */ #define FLASH_SECTOR_8 0x0080000 /* 128 Kb */ #define FLASH_SECTOR_9 0x00A0000 /* 128 Kb */ #define FLASH_SECTOR_10 0x00C0000 /* 128 Kb */ #define FLASH_SECTOR_11 0x00E0000 /* 128 Kb */ #define FLASH_TOP 0x0100000 #define FLASH_SECTORS 12 const uint32_t flash_sector[FLASH_SECTORS + 1] = { FLASH_SECTOR_0, FLASH_SECTOR_1, FLASH_SECTOR_2, FLASH_SECTOR_3, FLASH_SECTOR_4, FLASH_SECTOR_5, FLASH_SECTOR_6, FLASH_SECTOR_7, FLASH_SECTOR_8, FLASH_SECTOR_9, FLASH_SECTOR_10, FLASH_SECTOR_11, FLASH_TOP }; static void flash_wait_complete(void) { while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY) ; } static void flash_erase_sector(uint32_t sec) { uint32_t reg = FLASH_CR & (~(FLASH_CR_SNB_MASK << FLASH_CR_SNB_SHIFT)); FLASH_CR = reg | (sec & FLASH_CR_SNB_MASK) << FLASH_CR_SNB_SHIFT; FLASH_CR |= FLASH_CR_SER; FLASH_CR |= FLASH_CR_STRT; flash_wait_complete(); FLASH_CR &= ~FLASH_CR_SER; FLASH_CR &= ~(FLASH_CR_SNB_MASK << FLASH_CR_SNB_SHIFT); } static void clear_errors(void) { FLASH_SR |= ( FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR | FLASH_SR_WRPERR | FLASH_SR_OPERR | FLASH_SR_EOP ); } int flash_write(uint32_t address, const uint8_t *data, int len) { int i; uint32_t val; flash_wait_complete(); clear_errors(); /* Set 8-bit write */ FLASH_CR &= (~(0x03 << 8)); for (i = 0; i < len; i++) { FLASH_CR |= FLASH_CR_PG; *((uint8_t *)(address + i)) = data[i]; flash_wait_complete(); FLASH_CR &= ~FLASH_CR_PG; } return 0; } void flash_unlock(void) { FLASH_CR |= FLASH_CR_LOCK; FLASH_KEYR = FLASH_KEY1; FLASH_KEYR = FLASH_KEY2; } void flash_lock(void) { FLASH_CR |= FLASH_CR_LOCK; } int flash_erase(uint32_t address, int len) { int start = -1, end = -1; uint32_t end_address; int i; if (len == 0) return -1; end_address = address + len - 1; if (address < flash_sector[0] || end_address > FLASH_TOP) return -1; for (i = 0; i < FLASH_SECTORS; i++) { if ((address >= flash_sector[i]) && (address < flash_sector[i + 1])) { start = i; } if ((end_address >= flash_sector[i]) && (end_address < flash_sector[i + 1])) { end = i; } if (start > 0 && end > 0) break; } if (start < 0 || end < 0) return -1; for (i = start; i <= end; i++) flash_erase_sector(i); return 0; }