/**
******************************************************************************
* @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.
*
*
© COPYRIGHT 2019 Chipways
******************************************************************************
*/
#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 */