You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
8.3 KiB
241 lines
8.3 KiB
#include "stm32f4xx.h"
|
|
#include "flash_if.h"
|
|
|
|
/**
|
|
* @brief Gets the sector of a given address
|
|
* @param Address: Flash address
|
|
* @retval The sector of a given address
|
|
*/
|
|
static uint32_t get_sector(uint32_t Address)
|
|
{
|
|
uint32_t sector = 0;
|
|
|
|
if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0)) {
|
|
sector = FLASH_Sector_0;
|
|
} else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1)) {
|
|
sector = FLASH_Sector_1;
|
|
} else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2)) {
|
|
sector = FLASH_Sector_2;
|
|
} else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3)) {
|
|
sector = FLASH_Sector_3;
|
|
} else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4)) {
|
|
sector = FLASH_Sector_4;
|
|
} else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5)) {
|
|
sector = FLASH_Sector_5;
|
|
} else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6)) {
|
|
sector = FLASH_Sector_6;
|
|
} else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7)) {
|
|
sector = FLASH_Sector_7;
|
|
} else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8)) {
|
|
sector = FLASH_Sector_8;
|
|
} else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9)) {
|
|
sector = FLASH_Sector_9;
|
|
} else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10)) {
|
|
sector = FLASH_Sector_10;
|
|
#if !defined(STM32F429_439xx)
|
|
} else {/*(Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_11))*/
|
|
sector = FLASH_Sector_11;
|
|
}
|
|
#else
|
|
} else if((Address < ADDR_FLASH_SECTOR_12) && (Address >= ADDR_FLASH_SECTOR_11)) {
|
|
sector = FLASH_Sector_11;
|
|
} else if((Address < ADDR_FLASH_SECTOR_13) && (Address >= ADDR_FLASH_SECTOR_12)) {
|
|
sector = FLASH_Sector_12;
|
|
} else if((Address < ADDR_FLASH_SECTOR_14) && (Address >= ADDR_FLASH_SECTOR_13)) {
|
|
sector = FLASH_Sector_13;
|
|
} else if((Address < ADDR_FLASH_SECTOR_15) && (Address >= ADDR_FLASH_SECTOR_14)) {
|
|
sector = FLASH_Sector_14;
|
|
} else if((Address < ADDR_FLASH_SECTOR_16) && (Address >= ADDR_FLASH_SECTOR_15)) {
|
|
sector = FLASH_Sector_15;
|
|
} else if((Address < ADDR_FLASH_SECTOR_17) && (Address >= ADDR_FLASH_SECTOR_16)) {
|
|
sector = FLASH_Sector_16;
|
|
} else if((Address < ADDR_FLASH_SECTOR_18) && (Address >= ADDR_FLASH_SECTOR_17)) {
|
|
sector = FLASH_Sector_17;
|
|
} else if((Address < ADDR_FLASH_SECTOR_19) && (Address >= ADDR_FLASH_SECTOR_18)) {
|
|
sector = FLASH_Sector_18;
|
|
} else if((Address < ADDR_FLASH_SECTOR_20) && (Address >= ADDR_FLASH_SECTOR_19)) {
|
|
sector = FLASH_Sector_19;
|
|
} else if((Address < ADDR_FLASH_SECTOR_21) && (Address >= ADDR_FLASH_SECTOR_20)) {
|
|
sector = FLASH_Sector_20;
|
|
} else if((Address < ADDR_FLASH_SECTOR_22) && (Address >= ADDR_FLASH_SECTOR_21)) {
|
|
sector = FLASH_Sector_21;
|
|
} else if((Address < ADDR_FLASH_SECTOR_23) && (Address >= ADDR_FLASH_SECTOR_22)) {
|
|
sector = FLASH_Sector_22;
|
|
} else {
|
|
sector = FLASH_Sector_23;
|
|
}
|
|
#endif
|
|
return sector;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Unlocks Flash for write access
|
|
* @param None
|
|
* @retval None
|
|
*/
|
|
void flash_if_init(void)
|
|
{
|
|
FLASH_Unlock();
|
|
|
|
/* Clear pending flags (if any) */
|
|
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
|
|
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
|
|
}
|
|
|
|
/**
|
|
* @brief This function does an erase of all user flash area
|
|
* @param StartSector: start of user flash area
|
|
* @retval 0: user flash area successfully erased
|
|
* 1: error occurred
|
|
*/
|
|
int flash_if_erase(uint32_t start_address, uint32_t length)
|
|
{
|
|
uint32_t start, end, i = 0;
|
|
|
|
start = get_sector(start_address);
|
|
if (length > 0) {
|
|
end = get_sector(start_address + length);
|
|
} else {
|
|
#if !defined(STM32F429_439xx)
|
|
end = FLASH_Sector_11;
|
|
#else
|
|
end = FLASH_Sector_23;
|
|
#endif
|
|
}
|
|
|
|
for (i = start; i <= end; i += 8) {
|
|
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
|
|
be done by word */
|
|
if (FLASH_EraseSector(i, VoltageRange_3) != FLASH_COMPLETE) {
|
|
/* Error occurred while page erase */
|
|
return (1);
|
|
}
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
/**
|
|
* @brief This function writes a data buffer in flash (data are 32-bit aligned).
|
|
* @note After writing data buffer, the flash content is checked.
|
|
* @param FlashAddress: start address for writing data buffer
|
|
* @param data: pointer on data buffer
|
|
* @param length: length of data buffer (unit is byte)
|
|
* @retval 0: Data successfully written to Flash memory
|
|
* 1: Error occurred while writing data in Flash memory
|
|
* 2: Written Data in flash memory is different from expected one
|
|
*/
|
|
int flash_if_write(uint32_t flash_address, const void *data ,uint32_t tot)
|
|
{
|
|
const uint8_t *ptr = data;
|
|
const uint32_t *ptr32;
|
|
uint32_t i, length, align;
|
|
|
|
align = flash_address % 4;
|
|
if (align > 0) {
|
|
while ((tot > 0) && (align > 0) && (flash_address <= (USER_FLASH_END_ADDRESS))) {
|
|
if (FLASH_ProgramByte(flash_address, *ptr) != FLASH_COMPLETE) {
|
|
return 1;
|
|
}
|
|
if (*(volatile uint8_t *)flash_address != *ptr) {
|
|
return 2;
|
|
}
|
|
++flash_address;
|
|
++ptr;
|
|
--align;
|
|
--tot;
|
|
}
|
|
}
|
|
|
|
ptr32 = (const uint32_t *)ptr;
|
|
length = tot / 4;
|
|
for (i = 0; (i < length) && (flash_address <= (USER_FLASH_END_ADDRESS-4)); i++) {
|
|
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
|
|
be done by word */
|
|
if (FLASH_ProgramWord(flash_address, ptr32[i]) == FLASH_COMPLETE) {
|
|
/* Check the written value */
|
|
if (*(volatile uint32_t*)flash_address != ptr32[i]) {
|
|
/* Flash content doesn't match SRAM content */
|
|
return (2);
|
|
}
|
|
/* Increment FLASH destination address */
|
|
flash_address += 4;
|
|
ptr += 4;
|
|
} else {
|
|
/* Error occurred while writing data in Flash memory */
|
|
return (1);
|
|
}
|
|
}
|
|
|
|
align = tot % 4;
|
|
while ((align > 0) && (flash_address <= USER_FLASH_END_ADDRESS)) {
|
|
if (FLASH_ProgramByte(flash_address, *ptr) == FLASH_COMPLETE) {
|
|
if (*(volatile uint8_t *)flash_address != *ptr) {
|
|
return (2);
|
|
}
|
|
} else {
|
|
return (1);
|
|
}
|
|
++ptr;
|
|
++flash_address;
|
|
--align;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the write protection status of user flash area.
|
|
* @param None
|
|
* @retval 0: No write protected sectors inside the user flash area
|
|
* 1: Some sectors inside the user flash area are write protected
|
|
*/
|
|
int flash_if_get_write_protection_status(uint32_t address)
|
|
{
|
|
uint32_t UserStartSector;
|
|
|
|
/* Get the sector where start the user flash area */
|
|
UserStartSector = get_sector(address);
|
|
|
|
/* Check if there are write protected sectors inside the user flash area */
|
|
if ((FLASH_OB_GetWRP() >> (UserStartSector/8)) == (0xFFF >> (UserStartSector/8))) {
|
|
/* No write protected sectors inside the user flash area */
|
|
return 1;
|
|
} else { /* Some sectors inside the user flash area are write protected */
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Disables the write protection of user flash area.
|
|
* @param None
|
|
* @retval 1: Write Protection successfully disabled
|
|
* 2: Error: Flash write unprotection failed
|
|
*/
|
|
int flash_if_disable_write_protection(uint32_t address)
|
|
{
|
|
__IO uint32_t UserStartSector, UserWrpSectors = OB_WRP_Sector_1;
|
|
|
|
/* Get the sector where start the user flash area */
|
|
UserStartSector = get_sector(address);
|
|
|
|
/* Mark all sectors inside the user flash area as non protected */
|
|
UserWrpSectors = 0xFFF-((1 << (UserStartSector/8))-1);
|
|
|
|
/* Unlock the Option Bytes */
|
|
FLASH_OB_Unlock();
|
|
|
|
/* Disable the write protection for all sectors inside the user flash area */
|
|
FLASH_OB_WRPConfig(UserWrpSectors, DISABLE);
|
|
|
|
/* Start the Option Bytes programming process. */
|
|
if (FLASH_OB_Launch() != FLASH_COMPLETE) {
|
|
/* Error: Flash write unprotection failed */
|
|
return (2);
|
|
}
|
|
|
|
/* Write Protection successfully disabled */
|
|
return (1);
|
|
}
|
|
|
|
|