/** ****************************************************************************** * @file IAP/IAP_Main/Src/flash_if.c * @author MCD Application Team * @brief This file provides all the memory related operation functions. ****************************************************************************** * @attention * *

© Copyright (c) 2017 STMicroelectronics International N.V. * 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. Redistribution 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 other * contributors to this software may be used to endorse or promote products * derived from this software without specific written permission. * 4. This software, including modifications and/or derivative works of this * software, must execute solely and exclusively on microcontroller or * microprocessor devices manufactured by or for STMicroelectronics. * 5. Redistribution and use of this software other than as permitted under * this license is void and will automatically terminate your rights under * this license. * * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT * SHALL STMICROELECTRONICS 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. * ****************************************************************************** */ /** @addtogroup STM32F4xx_IAP_Main * @{ */ /* Includes ------------------------------------------------------------------*/ #include "flash_if.h" #include "usart.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ static uint32_t GetSector(uint32_t Address); /* Private functions ---------------------------------------------------------*/ /** * @brief Unlocks Flash for write access * @param None * @retval None */ void FLASH_If_Init(void) { HAL_FLASH_Unlock(); /* Clear pending flags (if any) */ __HAL_FLASH_CLEAR_FLAG(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 */ uint32_t FLASH_If_Erase(uint32_t StartSector, uint32_t NumberOfSector) { uint32_t UserStartSector; uint32_t SectorError; FLASH_EraseInitTypeDef pEraseInit; /* Unlock the Flash to enable the flash control register access *************/ FLASH_If_Init(); /* Get the sector where start the user flash area */ UserStartSector = GetSector(StartSector); pEraseInit.TypeErase = TYPEERASE_SECTORS; pEraseInit.Sector = UserStartSector; pEraseInit.NbSectors = NumberOfSector; pEraseInit.VoltageRange = VOLTAGE_RANGE_3; if (HAL_FLASHEx_Erase(&pEraseInit, &SectorError) != HAL_OK) { /* 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 DataLength: length of data buffer (unit is 32-bit word) * @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 */ uint32_t FLASH_If_Write(uint32_t FlashAddress, uint32_t* Data ,uint32_t DataLength) { uint32_t i = 0; for (i = 0; (i < DataLength) && (FlashAddress <= (USER_FLASH_END_ADDRESS-0)); i++) { /* Device voltage range supposed to be [2.7V to 3.6V], the operation will be done by word */ if (HAL_FLASH_Program(TYPEPROGRAM_WORD, FlashAddress, *(uint32_t*)(Data+i)) == HAL_OK) { /* Check the written value */ if (*(uint32_t*)FlashAddress != *(uint32_t*)(Data+i)) { /* Flash content doesn't match SRAM content */ return(FLASHIF_WRITINGCTRL_ERROR); } /* Increment FLASH destination address */ FlashAddress += 4; } else { /* Error occurred while writing data in Flash memory */ return (FLASHIF_WRITING_ERROR); } } return (FLASHIF_OK); } /** * @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 */ uint16_t FLASH_If_GetWriteProtectionStatus(void) { uint32_t ProtectedSECTOR = 0xFFF; FLASH_OBProgramInitTypeDef OptionsBytesStruct; /* Unlock the Flash to enable the flash control register access *************/ HAL_FLASH_Unlock(); /* Check if there are write protected sectors inside the user flash area ****/ HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct); /* Lock the Flash to disable the flash control register access (recommended to protect the FLASH memory against possible unwanted operation) *********/ HAL_FLASH_Lock(); /* Get pages already write protected ****************************************/ ProtectedSECTOR = ~(OptionsBytesStruct.WRPSector) & FLASH_SECTOR_TO_BE_PROTECTED; /* Check if desired pages are already write protected ***********************/ if(ProtectedSECTOR != 0) { /* Some sectors inside the user flash area are write protected */ return FLASHIF_PROTECTION_WRPENABLED; } else { /* No write protected sectors inside the user flash area */ return FLASHIF_PROTECTION_NONE; } } /** * @brief Gets the sector of a given address * @param Address: Flash address * @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 Configure the write protection status of user flash area. * @param modifier DISABLE or ENABLE the protection * @retval HAL_StatusTypeDef HAL_OK if change is applied. */ HAL_StatusTypeDef FLASH_If_WriteProtectionConfig(uint32_t modifier) { uint32_t ProtectedSECTOR = 0xFFF; FLASH_OBProgramInitTypeDef config_new, config_old; HAL_StatusTypeDef result = HAL_OK; /* Get pages write protection status ****************************************/ HAL_FLASHEx_OBGetConfig(&config_old); /* The parameter says whether we turn the protection on or off */ config_new.WRPState = modifier; /* We want to modify only the Write protection */ config_new.OptionType = OPTIONBYTE_WRP; /* No read protection, keep BOR and reset settings */ config_new.RDPLevel = OB_RDP_LEVEL_0; config_new.USERConfig = config_old.USERConfig; /* Get pages already write protected ****************************************/ ProtectedSECTOR = config_old.WRPSector | FLASH_SECTOR_TO_BE_PROTECTED; /* Unlock the Flash to enable the flash control register access *************/ HAL_FLASH_Unlock(); /* Unlock the Options Bytes *************************************************/ HAL_FLASH_OB_Unlock(); config_new.WRPSector = ProtectedSECTOR; result = HAL_FLASHEx_OBProgram(&config_new); return result; } //================================================ // Phihong IAP custom routine //================================================ uint8_t PH_CalNewCodeChecksum(void) { uint32_t CheckSum=0; __IO uint32_t flashdestination = NEW_CODE_ADDRESS; for(uint32_t i=0;i<0x60000;i++) { CheckSum += (*(uint16_t *)(flashdestination+i)); } #ifdef DEBUG DEBUG_INFO("\r\nChecksum = 0x%X", CheckSum); #endif if(CheckSum == *(uint16_t *)0x080fffff) { return(1); } else { return(0); } } uint8_t PH_isMoveOK(void) { uint8_t isSuccess = 1; //__IO uint32_t flashdestination = APPLICATION_ADDRESS; //__IO uint32_t newdestination = NEW_CODE_ADDRESS; uint32_t flashdestination = APPLICATION_ADDRESS; uint32_t newdestination = NEW_CODE_ADDRESS; for(uint32_t i=0;i<0x60000;i++) { HAL_IWDG_Refresh(&hiwdg); if((*((uint8_t *)newdestination++)) != (*((uint8_t *)flashdestination++))) { isSuccess = 0; } } #ifdef DEBUG if(isSuccess) DEBUG_INFO("Move code compare OK...\r\n"); else DEBUG_INFO("Move code compare fail...\r\n"); #endif return isSuccess; } void PH_ClearUpgradeReq(void) { FLASH_If_Erase(UPGRADE_REQ_ADDRESS, 1); #ifdef DEBUG DEBUG_INFO("Clean firmware upgrade request flag...\r\n"); #endif } uint8_t PH_isUpgradeReq(void) { uint8_t isSuccess = 0; __IO uint32_t flashdestination = UPGRADE_REQ_ADDRESS; if(*((uint32_t *)flashdestination) == 0x0aa55aa55) { #ifdef DEBUG DEBUG_INFO("Firmware upgrade request detect...\r\n"); #endif isSuccess = 1; } else if(*((uint32_t *)flashdestination) != 0x0ffffffff) { PH_ClearUpgradeReq(); } else { #ifdef DEBUG DEBUG_INFO("Firmware upgrade request does not detect...\r\n"); #endif } return isSuccess; } void PH_MoveCode2Ap(void) { uint32_t packet_length = 0x10000; uint8_t flag_flash_write_err = 0; //__IO uint32_t flashdestination = APPLICATION_ADDRESS; //__IO uint32_t newdestination = NEW_CODE_ADDRESS; uint32_t flashdestination = APPLICATION_ADDRESS; uint32_t newdestination = NEW_CODE_ADDRESS; FLASH_If_Erase(ADDR_FLASH_SECTOR_6, 3); #ifdef DEBUG DEBUG_INFO("AP flash(0x8040000 erase finish\r\n"); DEBUG_INFO("Move flash data form 0x80A0000( length 0x60000) to 0x8040000"); #endif for(uint32_t i=0;i<6;i++) { if ((FLASH_If_Write(flashdestination, (uint32_t*) newdestination, packet_length/4)) == FLASHIF_OK) { flashdestination += packet_length; newdestination += packet_length; #ifdef DEBUG DEBUG_INFO("."); if(i==5) DEBUG_INFO("\r\n"); #endif } else { #ifdef DEBUG DEBUG_INFO("Fail\r\n"); #endif flag_flash_write_err = 1; } } //CalNewCodeChecksum(); if(!PH_isMoveOK()) { flag_flash_write_err = 1; } if(!flag_flash_write_err) { PH_ClearUpgradeReq(); #ifdef DEBUG DEBUG_INFO("Upgrade finish, MCU reboot...\r\n"); #endif NVIC_SystemReset(); } } /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/