/**
|
******************************************************************************
|
* @file xl_flash.c
|
* @author xu.wang
|
* @version 4.5.2
|
* @date Fri Mar 26 17:29:12 2021
|
* @brief This file provide function about FLASH firmware program
|
******************************************************************************
|
* @attention
|
*
|
* 2019 by Chipways Communications,Inc. All Rights Reserved.
|
* This software is supplied under the terms of a license
|
* agreement or non-disclosure agreement with Chipways.
|
* Passing on and copying of this document,and communication
|
* of its contents is not permitted without prior written
|
* authorization.
|
*
|
* <h2><center>© COPYRIGHT 2019 Chipways</center></h2>
|
******************************************************************************
|
*/
|
#if defined(__cplusplus)
|
extern "C"
|
{
|
#endif /* __cplusplus */
|
|
/* Includes ---------------------------------------------------------------*/
|
#include "xl_flash.h"
|
/** @addtogroup XL6600_StdPeriph_Driver
|
* @{
|
*/
|
|
/** @defgroup FLASH FLASH Module
|
* @brief FLASH Driver Modules Library
|
* @{
|
*/
|
|
/* Private typedef -----------------------------------------------------------*/
|
/* Private define ------------------------------------------------------------*/
|
/* Private macro -------------------------------------------------------------*/
|
/* Private variables ---------------------------------------------------------*/
|
/* Private function prototypes -----------------------------------------------*/
|
/* Private functions ---------------------------------------------------------*/
|
|
/** @defgroup FMC_Private_Functions
|
* @{
|
*/
|
|
/**
|
* @brief FLASH³õʼ»¯.
|
* @param BusClock:µ±Ç°FlashʱÖÓ
|
* @retval ·µ»ØFLASH״̬.
|
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
|
* @arg FLASH_ERR_INIT_CCIF£º¼ÓÔØÃüÁîδÍê³É
|
* @arg FLASH_ERR_INIT_CLK1M£ºCLK1M´íÎó
|
*/
|
uint16_t FLASH_Init(uint8_t BusClockMhz)
|
{
|
uint16_t errorstatus;
|
uint32_t clk1M = (uint32_t)BusClockMhz - 1u;
|
uint32_t fcpco;
|
|
errorstatus = FLASH_ERR_SUCCESS;
|
|
if ((FMC->FSTAT & FMC_FSTAT_CCIF_MASK) != FMC_FSTAT_CCIF_MASK)
|
{
|
errorstatus |= (uint16_t)FLASH_ERR_INIT_CCIF;
|
}
|
else
|
{
|
fcpco = FMC->FCPC0;
|
if (BusClockMhz > 48u)
|
{
|
/* high speed ,>48Mhz */
|
fcpco |= FMC_FCPC0_HSMD_MASK;
|
}
|
else
|
{
|
/* low speed ,<=48Mhz */
|
fcpco &= ~FMC_FCPC0_HSMD_MASK;
|
}
|
/* clk1m is not locked */
|
if ((fcpco & FMC_FCPC0_CLK1MLCK_MASK) != FMC_FCPC0_CLK1MLCK_MASK)
|
{
|
/* first clear the clk1M bit */
|
fcpco &= ~FMC_FCPC0_CLK1M_MASK;
|
|
fcpco |= (clk1M << FMC_FCPC0_CLK1M_SHIFT);
|
|
FMC->FCPC0 = fcpco;
|
}
|
else
|
{
|
/* clk1m is locked */
|
if ((fcpco & FMC_FCPC0_CLK1M_MASK) != (clk1M << FMC_FCPC0_CLK1M_SHIFT))
|
{
|
/* clk1m locked is wrong */
|
errorstatus |= (uint16_t)FLASH_ERR_INIT_CLKIM;
|
}
|
}
|
}
|
return errorstatus;
|
}
|
|
/**
|
* @brief flash±£»¤ÅäÖÃ
|
* @param FLASH_ProtectType:±£»¤²ÎÊýÅäÖýṹÌå
|
* @retval None
|
*/
|
void FLASH_ProtecConfig(const FLASH_ProtectTypeDef *FLASH_ProtectType)
|
{
|
uint32_t temp;
|
|
temp = FMC->FOSP;
|
/* first clear the protection bits */
|
temp &= ~(uint32_t)FLASH_PROTECT_MASK;
|
/* set the protection bits */
|
temp |= ((uint32_t)FLASH_ProtectType->FLASH_POPEN << FMC_FOSP_FPOPEN_SHIFT) | ((uint32_t)FLASH_ProtectType->FLASH_FPHDIS << FMC_FOSP_FPHDIS_SHIFT) |
|
((uint32_t)FLASH_ProtectType->FLASH_FPHS << FMC_FOSP_FPHS_SHIFT) | ((uint32_t)FLASH_ProtectType->FLASH_FPLDIS << FMC_FOSP_FPLDIS_SHIFT) |
|
((uint32_t)FLASH_ProtectType->FLASH_FPLS << FMC_FOSP_FPLS_SHIFT);
|
FMC->FOSP = temp;
|
}
|
|
/**
|
* @brief flashÃüÁîÍê³ÉÖжÏʹÄÜ.
|
* @param NewState£ºÑ¡ÔñÊÇ·ñʹÄÜ
|
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
|
* @arg ENABLE £ºÊ¹ÄÜ
|
* @arg DISABLE £ºÊ§ÄÜ
|
* @retval None
|
*/
|
void FLASH_CCIEnableCmd(FunctionalState NewState)
|
{
|
if (NewState != DISABLE)
|
{
|
/* Enable the FLASH Command Complete interrupt */
|
FMC->FCNFG |= FMC_FCNFG_CCIE_MASK;
|
}
|
else
|
{
|
/* Disable the FLASH Command Complete interrupt */
|
FMC->FCNFG &= ~FMC_FCNFG_CCIE_MASK;
|
}
|
}
|
|
/**
|
* @brief flash¹Ø±ÕECC¹¦ÄÜ
|
* @param ecc_area£ºÑ¡ÔñµÄÇøÓò£¬´ÓFlashµÄ×î´óµØÖ·ÍùÉϼÆÊý
|
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
|
* @arg FLASH_ECC_DISABLE_AREA_0KB £º0KbµÄÇø¼ä
|
* @arg FLASH_ECC_DISABLE_AREA_1KB £º1KbµÄÇø¼ä
|
* @arg FLASH_ECC_DISABLE_AREA_2KB £º2KbµÄÇø¼ä
|
* @arg FLASH_ECC_DISABLE_AREA_4KB £º4KbµÄÇø¼ä
|
* @arg FLASH_ECC_DISABLE_AREA_8KB £º8KbµÄÇø¼ä
|
* @arg FLASH_ECC_DISABLE_AREA_16KB £º16KbµÄÇø¼ä
|
* @arg FLASH_ECC_DISABLE_AREA_32KB £º32KbµÄÇø¼ä
|
* @arg FLASH_ECC_DISABLE_AREA_64KB £º64KbµÄÇø¼ä
|
* @retval None
|
*/
|
void FLASH_DisableECCArea(uint8_t ecc_area)
|
{
|
FMC->FCNFG |= (uint32_t)ecc_area;
|
}
|
|
/**
|
* @brief flash »º´æÊÇÄÜ
|
* @param NewState£ºÑ¡ÔñÊÇ·ñʹÄÜ
|
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
|
* @arg ENABLE £ºÊ¹ÄÜ
|
* @arg DISABLE £ºÊ§ÄÜ
|
* @retval None
|
*/
|
void FLASH_CacheCmd(FunctionalState NewState)
|
{
|
if (NewState != DISABLE)
|
{
|
/* Enable the cache */
|
FMC->FCPC0 |= FMC_FCPC0_CEN_MASK;
|
}
|
else
|
{
|
/* Disable the cache */
|
FMC->FCPC0 &= ~FMC_FCPC0_CEN_MASK;
|
}
|
}
|
/**
|
* @brief flashÔÚstopģʽϽøÈëÐÝÃßģʽ
|
* @param NewState£ºÑ¡ÔñÊÇ·ñʹÄÜ״̬.
|
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
|
* @arg ENABLE £ºÊ¹ÄÜ
|
* @arg DISABLE £ºÊ§ÄÜ
|
* @retval None
|
*/
|
void FLASH_SleepInStopCmd(FunctionalState NewState)
|
{
|
if (NewState != DISABLE)
|
{
|
/* alow to enter sleep mode in stop mode */
|
FMC->FCPC0 |= FMC_FCPC0_DPSTB_MASK;
|
}
|
else
|
{
|
/* Can not enter sleep mode in stop mode */
|
FMC->FCPC0 &= ~FMC_FCPC0_DPSTB_MASK;
|
}
|
}
|
|
/**
|
* @brief CLK1MËø¶¨¿ØÖÆÊ¹ÄÜ
|
* @param NewState£ºÑ¡ÔñÊÇ·ñʹÄÜ״̬.
|
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
|
* @arg ENABLE £ºÊ¹ÄÜ
|
* @arg DISABLE £ºÊ§ÄÜ
|
* @retval None
|
*/
|
void FLASH_LockClk1MCmd(FunctionalState NewState)
|
{
|
if (NewState != DISABLE)
|
{
|
/* alow to enter sleep mode in stop mode */
|
FMC->FCPC0 |= FMC_FCPC0_CLK1MLCK_MASK;
|
}
|
else
|
{
|
/* Can not enter sleep mode in stop mode */
|
FMC->FCPC0 &= ~FMC_FCPC0_CLK1MLCK_MASK;
|
}
|
}
|
|
/**
|
* @brief ÉèÖÃflash¶ÁÈ¡µÈ´ýÖÜÆÚ.
|
* @param ReadWatiCycle:¶ÁÈ¡µÈ´ýÖÜÆÚ.
|
* @retval None
|
*/
|
void FLASH_SetReadWait(FLASH_ReadWaitCycleDef ReadWaitCycle)
|
{
|
uint32_t temp;
|
/* Check the parameters */
|
temp = FMC->FCPC0;
|
/* first clear the RWC bit */
|
temp &= ~FMC_FCPC0_RWC_MASK;
|
/* set the RWC bit */
|
temp |= ((uint32_t)ReadWaitCycle << FMC_FCPC0_RWC_SHIFT);
|
FMC->FCPC0 = temp;
|
}
|
|
/**
|
* @brief flashµÃµ½ÃüÁîÍê³ÉÖжϱêÖ¾
|
* @param None
|
* @retval ÖжÏ״̬±êÖ¾
|
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
|
* @arg 0 £ºÉÁ´æÃüÁîÕýÔÚ½øÐÐÖÐ
|
* @arg 1 £ºÉÁ´æÃüÁîÍê³É
|
*/
|
uint8_t FLASH_GetCmdFinshFlag(void)
|
{
|
uint8_t sta;
|
if ((FMC->FSTAT & FMC_FSTAT_CCIF_MASK) == FMC_FSTAT_CCIF_MASK)
|
{
|
sta = 1;
|
}
|
else
|
{
|
sta = 0;
|
}
|
return sta;
|
}
|
|
/**
|
* @brief »ñÈ¡´æ´¢Æ÷¿ØÖÆÃ¦±êÖ¾
|
* @param None
|
* @retval ´æ´¢Æ÷¿ØÖÆÃ¦±êÖ¾(Set or Reset)
|
*/
|
uint8_t FLASH_GetControllerBusyFlag(void)
|
{
|
uint8_t sta;
|
if ((FMC->FSTAT & FMC_FSTAT_MGBUSY_MASK) == FMC_FSTAT_MGBUSY_MASK)
|
{
|
sta = 1;
|
}
|
else
|
{
|
sta = 0;
|
}
|
return sta;
|
}
|
|
/**
|
* @brief flashÇå³ýÉÁ´æÃüÁîÖжϱêÖ¾
|
* @param None
|
* @retval None
|
*/
|
void FLASH_LaunchCMD(void)
|
{
|
/* Launch a command */
|
FMC->FSTAT |= 0x80000000u;
|
}
|
|
/**
|
* @brief flash¼ì²â´íÎó״̬.
|
* @param None
|
* @retval ·µ»ØFLASH״̬.
|
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
|
* @arg FLASH_ERR_ACCESS £ºflash·ÃÎÊ´íÎó±êÖ¾
|
* @arg FLASH_ERR_PROTECTION £ºflash±£»¤Î¥·´±êÖ¾
|
* @arg FLASH_ERR_ECC £ºECCУÑé´íÎó
|
* @arg FLASH_ERR_ERASEVERIFY £º²Á³ýÑéÖ¤´íÎó
|
*/
|
uint16_t FLASH_CheckErrStatus(void)
|
{
|
|
uint16_t Errstatus;
|
|
Errstatus = FLASH_ERR_SUCCESS;
|
|
/* Access Error */
|
if ((FMC->FSTAT & FMC_FSTAT_ACCERR_MASK) == FMC_FSTAT_ACCERR_MASK)
|
{
|
Errstatus |= (uint16_t)FLASH_ERR_ACCESS;
|
}
|
|
/* Flash Protection Violation */
|
if ((FMC->FSTAT & FMC_FSTAT_FPVIOL_MASK) == FMC_FSTAT_FPVIOL_MASK)
|
{
|
Errstatus |= (uint16_t)FLASH_ERR_PROTECTION;
|
}
|
|
/* ECC error */
|
if ((FMC->FSTAT & FMC_FSTAT_MGSTAT_MASK) == FLASH_FSTAT_MGSTAT0_MASK)
|
{
|
Errstatus |= (uint16_t)FLASH_ERR_ECC;
|
}
|
|
/* erase verify error */
|
if ((FMC->FSTAT & FMC_FSTAT_MGSTAT_MASK) == FLASH_FSTAT_MGSTAT1_MASK)
|
{
|
Errstatus |= (uint16_t)FLASH_ERR_ERASEVERIFY;
|
}
|
return (Errstatus);
|
}
|
|
/**
|
*
|
* @brief flash±à³ÌÁ½¸ö×ÖÊý¾Ý
|
* @param TargetAddress£º дÈëflashµÄµØÖ·
|
* Õâ¸ö²ÎÊý¿ÉÒÔÈ¡ÏÂÃæµÄÖµ:
|
* DwData0£ºÐ´ÈëÊý¾Ý¸ß×Ö
|
* DwData1£ºÐ´ÈëÊý¾ÝµÍ×Ö
|
* @return ·µ»Øflash error״̬.
|
*/
|
uint16_t FLASH_Program2LongWord(uint32_t TargetAddress, uint32_t DwData0, uint32_t DwData1)
|
{
|
|
uint16_t errorstatus;
|
|
errorstatus = FLASH_ERR_SUCCESS;
|
|
if ((TargetAddress & 0x03u) == 0x03u)
|
{
|
errorstatus = FLASH_ERR_INVALID_PARAM;
|
}
|
else
|
{
|
// Clear error flags
|
FMC->FSTAT = FMC_FSTAT_FPVIOL_MASK | FMC_FSTAT_ACCERR_MASK;
|
|
/* Write to specify the command code to be loaded */
|
FMC->FCCOBF0 = (((uint32_t)FLASH_CMD_PROGRAM << FMC_FCCOBF0_FCMD_SHIFT) | (TargetAddress));
|
|
/* Write to specify the Longword 0 program value to be loaded */
|
FMC->FCCOBF1 = DwData0;
|
|
/* Write to specify the Longword 0 program value to be loaded */
|
FMC->FCCOBF2 = DwData1;
|
}
|
|
return (errorstatus);
|
}
|
/**
|
* @brief Flash¶ÁË«×ÖÊý¾Ý
|
* @param TargetAddress£º дÈëflashµÄµØÖ·
|
* @retval ¶Á³öµÄÊý¾Ý
|
*/
|
|
uint64_t FLASH_ReadLongWord(const uint32_t *TargetAddress)
|
{
|
uint32_t rdata1, rdata2;
|
uint64_t data;
|
|
rdata1 = TargetAddress[0];
|
rdata2 = TargetAddress[1];
|
|
data = ((uint64_t)rdata2 << 32) | (uint64_t)rdata1;
|
|
return data;
|
}
|
|
void FLASH_ReadLongWordCmd(uint32_t TargetAddress)
|
{
|
|
FMC->FCCOBF0 = ((uint32_t)FLASH_CMD_READ << FMC_FCCOBF0_FCMD_SHIFT) | (TargetAddress);
|
|
FLASH_LaunchCMD();
|
}
|
|
/**
|
* @brief ²Á³ýÕû¸öflash
|
* @param None
|
* @retval ·µ»ØFLASH״̬.
|
*/
|
void FLASH_EraseChip(void)
|
{
|
|
FMC->FSTAT = FMC_FSTAT_FPVIOL_MASK | FMC_FSTAT_ACCERR_MASK;
|
|
/* Write to specify the command code to be loaded */
|
FMC->FCCOBF0 = ((uint32_t)FLASH_CMD_ERASE_CHIP << FMC_FCCOBF0_FCMD_SHIFT);
|
}
|
|
/**
|
* @brief FlashÉÈÇø²Á³ý
|
* @param TargetAddress: ²Á³ýÉÈÇøµÄµØÖ·
|
* @retval ·µ»ØFLASH״̬.
|
*/
|
uint16_t FLASH_EraseSector(uint32_t TargetAddress)
|
{
|
uint16_t errorstatus;
|
|
errorstatus = FLASH_ERR_SUCCESS;
|
|
if ((TargetAddress & 0x03u) == 0x03u)
|
{
|
errorstatus = FLASH_ERR_INVALID_PARAM;
|
}
|
else
|
{
|
// Clear error flags
|
FMC->FSTAT = FMC_FSTAT_FPVIOL_MASK | FMC_FSTAT_ACCERR_MASK;
|
|
/* Write to specify the command code to be loaded */
|
FMC->FCCOBF0 = (((uint32_t)FLASH_CMD_ERASE_SECTOR << FMC_FCCOBF0_FCMD_SHIFT) | (TargetAddress));
|
}
|
|
return (errorstatus);
|
}
|
|
/**
|
* @brief flashÖØÆô
|
* @param None
|
* @retval ·µ»ØFLASH״̬.
|
*/
|
void FLASH_PowerOnReset(void)
|
{
|
|
FMC->FSTAT = FMC_FSTAT_FPVIOL_MASK | FMC_FSTAT_ACCERR_MASK;
|
|
/* Write to specify the command code to be loaded */
|
FMC->FCCOBF0 = ((uint32_t)FLASH_CMD_POWER_ON_RESET << FMC_FCCOBF0_FCMD_SHIFT);
|
|
/* Launch the command */
|
FLASH_LaunchCMD();
|
}
|
|
/**
|
* @brief Ìṩ²Á³ýÉÈÇø½ÌÑÐ
|
* @param TargetAddress:²Á³ýÉÈÇøµÄµØÖ·
|
* @retval ·µ»ØFLASH²Ù×÷µÄ½á¹û
|
*/
|
uint16_t FLASH_EraseVerifySector(uint32_t TargetAddress)
|
{
|
uint16_t errorstatus = FLASH_ERR_SUCCESS;
|
|
if ((TargetAddress & 0x03u) == 0x03u)
|
{
|
errorstatus = FLASH_ERR_INVALID_PARAM;
|
}
|
else
|
{
|
// Clear error flags
|
FMC->FSTAT = FMC_FSTAT_FPVIOL_MASK | FMC_FSTAT_ACCERR_MASK;
|
|
/* Write to specify the command code to be loaded */
|
FMC->FCCOBF0 = ((uint32_t)FLASH_CMD_ERASE_VERIFY_SECTOR << FMC_FCCOBF0_FCMD_SHIFT) | (TargetAddress);
|
}
|
return (errorstatus);
|
}
|
|
/**
|
* @brief Flash ²Á³ýоƬ²Ù×÷»á²Á³ýÕû¸öflash¼ÇÒäÊý¾Ý.
|
* @param None
|
* @retval ·µ»ØFLASH״̬.
|
*/
|
void FLASH_EraseVerifyChip(void)
|
{
|
// uint16_t errorstatus;
|
|
// Clear error flags
|
FMC->FSTAT = FMC_FSTAT_FPVIOL_MASK | FMC_FSTAT_ACCERR_MASK;
|
|
/* Write to specify the command code to be loaded */
|
FMC->FCCOBF0 = ((uint32_t)FLASH_CMD_ERASE_VERIFY_CHIP << FMC_FCCOBF0_FCMD_SHIFT);
|
|
/* Launch the command */
|
FLASH_LaunchCMD();
|
}
|
|
/**
|
* @brief Flash´ÓмÓÔØ
|
* @param None
|
* @retval ·µ»ØFLASH״̬.
|
*/
|
void FLASH_ConfigReload(void)
|
{
|
// uint16_t errorstatus ;
|
|
// Clear error flags
|
FMC->FSTAT = FMC_FSTAT_FPVIOL_MASK | FMC_FSTAT_ACCERR_MASK;
|
|
/* Write to specify the command code to be loaded */
|
FMC->FRLD = FMC_FRLD_FRLD_MASK;
|
|
/* Launch the command */
|
FLASH_LaunchCMD();
|
}
|
|
/**
|
* @brief flash°²È«ÅäÖÃ.
|
* @param None
|
* @retval ·µ»ØFLASH°²È«ÅäÖÃ.
|
*/
|
uint8_t FLASH_GetFlashSecurity(void)
|
{
|
uint8_t flashsecurity;
|
|
/* Get the flash security configuration. */
|
flashsecurity = (uint8_t)((FMC->FSTAT & FMC_FSTAT_SEC_MASK) >> FMC_FSTAT_SEC_SHIFT);
|
|
return flashsecurity;
|
}
|
|
/**
|
* @brief flash±£»¤ÅäÖÃ.
|
* @param None
|
* @retval ·µ»ØFLASH±£»¤ÅäÖÃ.
|
*/
|
uint8_t FLASH_GetFlashProtection(void)
|
{
|
uint8_t flashprotection;
|
|
/* Get the flash protection configuration. */
|
flashprotection = (uint8_t)((FMC->FOSP & FLASH_PROTECT_MASK) >> 8u);
|
|
return flashprotection;
|
}
|
|
/**
|
* @brief flashÑ¡ÏîÅäÖÃ.
|
* @param None
|
* @retval ·µ»ØFLASHÑ¡ÏîÅäÖÃ.
|
*/
|
uint8_t FLASH_GetFlashOption(void)
|
{
|
uint8_t flashoption;
|
|
/* Get the flash option configuration. */
|
flashoption = (uint8_t)((FMC->FOSP & FMC_FOSP_FOPT_MASK) >> FMC_FOSP_FOPT_SHIFT);
|
|
return flashoption;
|
}
|
|
/**
|
* @brief ºóÃÅÃØÔ¿½âËø.
|
* @param KeyHigh:ºóÃÅÃØÔ¿¸ß32λ.
|
* @param Keylow:ºóÃÅÃØÔ¿µÍ32λ.
|
* @retval None.
|
*/
|
void FLASH_BackdoorUnlockFlash(uint32_t KeyHigh, uint32_t Keylow)
|
{
|
FMC->KEYLOW = Keylow;
|
FMC->KEYHIGH = (KeyHigh | FMC_FOSP_BACKDOOR_EN_MASK);
|
}
|
|
/**
|
* @}
|
*/
|
|
/**
|
* @}
|
*/
|
|
/**
|
* @}
|
*/
|
|
#ifdef __cplusplus
|
}
|
#endif /* __cplusplus */
|