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