/**
******************************************************************************
* @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****/