/** ****************************************************************************** * @file FLASH.c * @author * @brief program the STM32F4xx FLASH. ****************************************************************************** * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "flash.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /*Variable used for Erase procedure*/ uint8_t flashBuf[FLASH_BUFFER_SIZE] = {0}; /* Private function prototypes -----------------------------------------------*/ static uint32_t GetSector(uint32_t Address); static uint32_t GetSectorSize(uint32_t Sector); /* Private functions ---------------------------------------------------------*/ /** * @brief program * @param None * @retval None */ #if 0 int ProgramFlashPage(uint32_t startAddress, uint32_t endAddress, uint32_t data) { uint32_t FirstSector = 0, NbOfSectors = 0, Address = 0; uint32_t SectorError = 0; __IO uint32_t data32 = 0 , MemoryProgramStatus = 0; FLASH_EraseInitTypeDef EraseInitStruct; int retval=0; /* Unlock the Flash to enable the flash control register access *************/ HAL_FLASH_Unlock(); /* Get the 1st sector to erase */ FirstSector = GetSector(startAddress); /* Get the number of sector to erase from 1st sector*/ NbOfSectors = GetSector(endAddress) - FirstSector + 1; /* Fill EraseInit structure*/ EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; EraseInitStruct.Sector = FirstSector; EraseInitStruct.NbSectors = NbOfSectors; if(HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) { /* Error occurred while sector erase. User can add here some code to deal with this error. SectorError will contain the faulty sector and then to know the code error on this sector, user can call function 'HAL_FLASH_GetError()' */ retval = -1; } else { /* 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(); /* Program the user Flash area word by word ***********/ Address = startAddress; while (Address < endAddress) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, data) == HAL_OK) { Address = Address + 4; } else { /* Error occurred while writing data in Flash memory. User can add here some code to deal with this error */ retval = -2; } } } /* Lock the Flash to disable the flash control register access (recommended to protect the FLASH memory against possible unwanted operation) *********/ HAL_FLASH_Lock(); if(retval==0) { /* Check if the programmed data is OK MemoryProgramStatus = 0: data programmed correctly MemoryProgramStatus != 0: number of words not programmed correctly ******/ Address = startAddress; MemoryProgramStatus = 0; while (Address < endAddress) { data32 = *(__IO uint32_t*)Address; if (data32 != data) { MemoryProgramStatus++; } Address = Address + 4; } } /* Check if there is an issue to program data */ if (MemoryProgramStatus == 0) { } else { retval = -3; } return retval; } #else int ProgramFlashPage(uint32_t startAddress, const uint8_t* data, uint32_t len) { uint32_t FirstSector = 0, NbOfSectors = 0, Address = 0, endAddress = 0; uint32_t SectorError = 0; __IO uint32_t data32 = 0 , MemoryProgramStatus = 0; uint32_t* pData = 0; FLASH_EraseInitTypeDef EraseInitStruct; int retval=0; HAL_StatusTypeDef status; Address = startAddress & (uint32_t)(~(FLASH_USER_PAGE_SIZE - 1)); endAddress = (startAddress + len + sizeof(uint64_t) -1) & (uint32_t)(~(sizeof(uint64_t)-1)); if( endAddress >= Address + FLASH_USER_PAGE_SIZE || FLASH_BUFFER_SIZE < len)// { return -1; } memcpy((void*)flashBuf, (void const*)Address, FLASH_BUFFER_SIZE); memcpy((void*)(flashBuf + (startAddress - Address)), (void const*)data, len); /* Unlock the Flash to enable the flash control register access *************/ ClearFlashWriteProtect(); HAL_FLASH_Unlock(); /* Get the 1st sector to erase */ FirstSector = GetSector(startAddress); /* Get the number of sector to erase from 1st sector*/ //NbOfSectors = GetSector(endAddress) - FirstSector + 1; NbOfSectors = 1; /* Fill EraseInit structure*/ EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; EraseInitStruct.Sector = FirstSector; EraseInitStruct.NbSectors = NbOfSectors; status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError); if(status != HAL_OK) { /* Error occurred while sector erase. User can add here some code to deal with this error. SectorError will contain the faulty sector and then to know the code error on this sector, user can call function 'HAL_FLASH_GetError()' */ retval = -1; } else { /* 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(); /* Program the user Flash area word by word ***********/ Address = FLASH_USER_START_ADDR; endAddress = Address + FLASH_BUFFER_SIZE; pData = (uint32_t*)flashBuf; while (Address < endAddress) { status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, *pData); if (status == HAL_OK) { Address = Address + 4; pData++; } else { /* Error occurred while writing data in Flash memory. User can add here some code to deal with this error */ retval = -2; break; } } } /* Lock the Flash to disable the flash control register access (recommended to protect the FLASH memory against possible unwanted operation) *********/ SetFlashWriteProtect(); if(retval==0) { /* Check if the programmed data is OK MemoryProgramStatus = 0: data programmed correctly MemoryProgramStatus != 0: number of words not programmed correctly ******/ Address = FLASH_USER_START_ADDR; pData = (uint32_t*)flashBuf; MemoryProgramStatus = 0; while (Address < endAddress) { data32 = *(__IO uint32_t*)Address; if (data32 != *pData) { MemoryProgramStatus++; } Address = Address + 4; pData++; } /* Check if there is an issue to program data */ if (MemoryProgramStatus == 0) { retval = 0; } else { retval = -3; } } return retval; } #endif int EraseFlashProgram(uint32_t startAddress, uint32_t length) { uint32_t FirstSector = 0, NbOfSectors = 0; uint32_t SectorError = 0,endAddress=0; FLASH_EraseInitTypeDef EraseInitStruct; int retval=0; HAL_StatusTypeDef status; /* Unlock the Flash to enable the flash control register access *************/ HAL_FLASH_Unlock(); /* Get the 1st sector to erase */ FirstSector = GetSector(startAddress); /* Get the number of sector to erase from 1st sector*/ endAddress = startAddress + length; NbOfSectors = GetSector(endAddress) - FirstSector + 1; /* Fill EraseInit structure*/ EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; EraseInitStruct.Sector = FirstSector; EraseInitStruct.NbSectors = NbOfSectors; status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError); if(HAL_OK != status) { /* Error occurred while sector erase. User can add here some code to deal with this error. SectorError will contain the faulty sector and then to know the code error on this sector, user can call function 'HAL_FLASH_GetError()' */ retval = -1; } else { retval = 1; } return retval; } int WriteData2FlashProgram(uint32_t startAddress, const uint8_t* data, uint32_t length) { int retval = 1; uint32_t endAddress = startAddress + length, curAddress = startAddress; uint32_t* pData = (uint32_t*)data; /* 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(); /* Program the user Flash area word by word ***********/ while (curAddress < endAddress) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, curAddress, *pData) == HAL_OK) { curAddress += sizeof(uint32_t); pData++; } else { /* Error occurred while writing data in Flash memory. User can add here some code to deal with this error */ retval = -2; } } return retval;; } int FinishFlashProgram(uint32_t startAddress, uint32_t length) { int retval = 1; /* Lock the Flash to disable the flash control register access (recommended to protect the FLASH memory against possible unwanted operation) *********/ HAL_FLASH_Lock(); return retval; } /** * @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; 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; } else /* (Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_11) */ { sector = FLASH_SECTOR_11; } 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((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) { sectorsize = 64 * 1024; } else { sectorsize = 128 * 1024; } return sectorsize; } void SetFlashReadProtect(void) { FLASH_OBProgramInitTypeDef OBInit={0}; HAL_FLASHEx_OBGetConfig(&OBInit); if(OB_RDP_LEVEL_0 == OBInit.RDPLevel) { OBInit.OptionType = OPTIONBYTE_RDP; OBInit.RDPLevel = OB_RDP_LEVEL_1; /* Allow Access to option bytes sector */ HAL_FLASH_OB_Unlock(); /* Allow Access to Flash control registers and user Flash */ HAL_FLASH_Unlock(); HAL_FLASHEx_OBProgram(&OBInit); /* Prevent Access to option bytes sector */ HAL_FLASH_OB_Lock(); /* Disable the Flash option control register access (recommended to protect the option Bytes against possible unwanted operations) */ HAL_FLASH_Lock(); } } void SetFlashWriteProtect(void) { FLASH_OBProgramInitTypeDef OBInit={0}; HAL_FLASHEx_OBGetConfig(&OBInit); if(OB_WRPSTATE_DISABLE == OBInit.WRPState || OB_WRP_SECTOR_All != OBInit.WRPSector) { OBInit.OptionType = OPTIONBYTE_WRP; OBInit.WRPState = OB_WRPSTATE_ENABLE; OBInit.WRPSector = OB_WRP_SECTOR_All; OBInit.Banks = FLASH_BANK_1; /* Allow Access to option bytes sector */ HAL_FLASH_OB_Unlock(); /* Allow Access to Flash control registers and user Flash */ HAL_FLASH_Unlock(); HAL_StatusTypeDef status = HAL_FLASHEx_OBProgram(&OBInit); /* Prevent Access to option bytes sector */ HAL_FLASH_OB_Lock(); /* Disable the Flash option control register access (recommended to protect the option Bytes against possible unwanted operations) */ HAL_FLASH_Lock(); if(HAL_OK != status) { return; } } } void ClearFlashWriteProtect(void) { FLASH_OBProgramInitTypeDef OBInit={0}; HAL_FLASHEx_OBGetConfig(&OBInit); //if(OB_WRPSTATE_ENABLE == OBInit.WRPState) { OBInit.OptionType = OPTIONBYTE_WRP; OBInit.WRPState = OB_WRPSTATE_DISABLE; OBInit.WRPSector = OB_WRP_SECTOR_All; OBInit.Banks = FLASH_BANK_1; /* Allow Access to option bytes sector */ HAL_FLASH_OB_Unlock(); /* Allow Access to Flash control registers and user Flash */ HAL_FLASH_Unlock(); HAL_StatusTypeDef status = HAL_FLASHEx_OBProgram(&OBInit); /* Prevent Access to option bytes sector */ HAL_FLASH_OB_Lock(); /* Disable the Flash option control register access (recommended to protect the option Bytes against possible unwanted operations) */ HAL_FLASH_Lock(); if(HAL_OK != status) { return; } } } void SetBORLevel(void) { FLASH_OBProgramInitTypeDef OBInit={0}; HAL_FLASHEx_OBGetConfig(&OBInit); if(OB_BOR_LEVEL3 != OBInit.BORLevel) { OBInit.OptionType = OPTIONBYTE_BOR; OBInit.BORLevel = OB_BOR_LEVEL3; /* Allow Access to option bytes sector */ HAL_FLASH_OB_Unlock(); /* Allow Access to Flash control registers and user Flash */ HAL_FLASH_Unlock(); HAL_FLASHEx_OBProgram(&OBInit); /* Prevent Access to option bytes sector */ HAL_FLASH_OB_Lock(); /* Disable the Flash option control register access (recommended to protect the option Bytes against possible unwanted operations) */ HAL_FLASH_Lock(); } } /*********************************END OF FILE**********************************/