aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hc32f460/driver/src/hc32f460_efm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hc32f460/driver/src/hc32f460_efm.c')
-rw-r--r--lib/hc32f460/driver/src/hc32f460_efm.c938
1 files changed, 938 insertions, 0 deletions
diff --git a/lib/hc32f460/driver/src/hc32f460_efm.c b/lib/hc32f460/driver/src/hc32f460_efm.c
new file mode 100644
index 00000000..d8583efe
--- /dev/null
+++ b/lib/hc32f460/driver/src/hc32f460_efm.c
@@ -0,0 +1,938 @@
+/******************************************************************************
+ * Copyright (C) 2020, Huada Semiconductor Co., Ltd. All rights reserved.
+ *
+ * This software component is licensed by HDSC under BSD 3-Clause license
+ * (the "License"); You may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ * opensource.org/licenses/BSD-3-Clause
+ */
+/******************************************************************************/
+/** \file hc32f460_efm.c
+ **
+ ** A detailed description is available at
+ ** @link EfmGroup EFM description @endlink
+ **
+ ** - 2018-10-29 CDT First version for Device Driver Library of EFM.
+ **
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Include files
+ ******************************************************************************/
+#include "hc32f460_efm.h"
+#include "hc32f460_utility.h"
+
+/**
+ *******************************************************************************
+ ** \addtogroup EfmGroup
+ ******************************************************************************/
+//@{
+
+/*******************************************************************************
+ * Local type definitions ('typedef')
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Local pre-processor symbols/macros ('#define')
+ ******************************************************************************/
+#define EFM_LOCK (0x00000000u)
+#define EFM_UNLOCK (0x00000001u)
+#define EFM_KEY1 (0x0123ul)
+#define EFM_KEY2 (0x3210ul)
+
+#define EFM_PROTECT_ADDR_MSK (0x000FFFFFu)
+
+/* Parameter validity check for pointer. */
+#define IS_VALID_POINTER(x) (NULL != (x))
+
+/* Parameter validity check for flash latency. */
+#define IS_VALID_FLASH_LATENCY(x) \
+( ((x) == EFM_LATENCY_0) || \
+ ((x) == EFM_LATENCY_1) || \
+ ((x) == EFM_LATENCY_2) || \
+ ((x) == EFM_LATENCY_3) || \
+ ((x) == EFM_LATENCY_4) || \
+ ((x) == EFM_LATENCY_5) || \
+ ((x) == EFM_LATENCY_6) || \
+ ((x) == EFM_LATENCY_7) || \
+ ((x) == EFM_LATENCY_8) || \
+ ((x) == EFM_LATENCY_9) || \
+ ((x) == EFM_LATENCY_10) || \
+ ((x) == EFM_LATENCY_11) || \
+ ((x) == EFM_LATENCY_12) || \
+ ((x) == EFM_LATENCY_13) || \
+ ((x) == EFM_LATENCY_14) || \
+ ((x) == EFM_LATENCY_15))
+
+/* Parameter validity check for read mode. */
+#define IS_VALID_READ_MD(MD) \
+( ((MD) == NormalRead) || \
+ ((MD) == UltraPowerRead))
+
+/* Parameter validity check for erase/program mode. */
+#define IS_VALID_ERASE_PGM_MD(MD) \
+( ((MD) == EFM_MODE_READONLY) || \
+ ((MD) == EFM_MODE_SINGLEPROGRAM) || \
+ ((MD) == EFM_MODE_SINGLEPROGRAMRB) || \
+ ((MD) == EFM_MODE_SEQUENCEPROGRAM) || \
+ ((MD) == EFM_MODE_SECTORERASE) || \
+ ((MD) == EFM_MODE_CHIPERASE))
+
+/* Parameter validity check for flash flag. */
+#define IS_VALID_FLASH_FLAG(flag) \
+( ((flag) == EFM_FLAG_WRPERR) || \
+ ((flag) == EFM_FLAG_PEPRTERR) || \
+ ((flag) == EFM_FLAG_PGSZERR) || \
+ ((flag) == EFM_FLAG_PGMISMTCH) || \
+ ((flag) == EFM_FLAG_EOP) || \
+ ((flag) == EFM_FLAG_COLERR) || \
+ ((flag) == EFM_FLAG_RDY))
+
+/* Parameter validity check for flash clear flag. */
+#define IS_VALID_CLEAR_FLASH_FLAG(flag) \
+( ((flag) == EFM_FLAG_WRPERR) || \
+ ((flag) == EFM_FLAG_PEPRTERR) || \
+ ((flag) == EFM_FLAG_PGSZERR) || \
+ ((flag) == EFM_FLAG_PGMISMTCH) || \
+ ((flag) == EFM_FLAG_EOP) || \
+ ((flag) == EFM_FLAG_COLERR))
+
+/* Parameter validity check for flash interrupt. */
+#define IS_VALID_EFM_INT_SEL(int) \
+( ((int) == PgmErsErrInt) || \
+ ((int) == EndPgmInt) || \
+ ((int) == ColErrInt))
+
+/* Parameter validity check for flash address. */
+#define IS_VALID_FLASH_ADDR(addr) \
+( ((addr) == 0x00000000u) || \
+ (((addr) >= 0x00000001u) && \
+ ((addr) <= 0x0007FFDFu)))
+
+/* Parameter validity check for flash address. */
+#define IS_VALID_OTP_LOCK_ADDR(addr) \
+( ((addr) >= 0x03000FC0u) || \
+ ((addr) <= 0x03000FF8u))
+/*******************************************************************************
+ * Global variable definitions (declared in header file with 'extern')
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Local function prototypes ('static')
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Local variable definitions ('static')
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Function implementation - global ('extern') and local ('static')
+ ******************************************************************************/
+/**
+ *******************************************************************************
+ ** \brief Unlock the flash.
+ **
+ ** \param None
+ **
+ ** \retval None
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+void EFM_Unlock(void)
+{
+ M4_EFM->FAPRT = EFM_KEY1;
+ M4_EFM->FAPRT = EFM_KEY2;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Lock the flash.
+ **
+ ** \param None
+ **
+ ** \retval None
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+void EFM_Lock(void)
+{
+ if(EFM_UNLOCK == M4_EFM->FAPRT)
+ {
+ M4_EFM->FAPRT = EFM_KEY2;
+ M4_EFM->FAPRT = EFM_KEY2;
+ }
+}
+
+/**
+ *******************************************************************************
+ ** \brief Enable or disable the flash.
+ **
+ ** \param [in] enNewState The new state of the flash.
+ ** \arg Enable Enable flash.
+ ** \arg Disable Stop flash.
+ **
+ ** \retval None
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+void EFM_FlashCmd(en_functional_state_t enNewState)
+{
+ DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
+
+ M4_EFM->FSTP_f.FSTP = ((Enable == enNewState) ? 0ul : 1ul);
+}
+/**
+ *******************************************************************************
+ ** \brief Sets the code latency value..
+ **
+ ** \param [in] u32Latency specifies the FLASH Latency value.
+ ** \arg EFM_LATENCY_0 FLASH 0 Latency cycle
+ ** \arg EFM_LATENCY_1 FLASH 1 Latency cycle
+ ** \arg EFM_LATENCY_2 FLASH 2 Latency cycles
+ ** \arg EFM_LATENCY_3 FLASH 3 Latency cycles
+ ** \arg EFM_LATENCY_4 FLASH 4 Latency cycles
+ ** \arg EFM_LATENCY_5 FLASH 5 Latency cycles
+ ** \arg EFM_LATENCY_6 FLASH 6 Latency cycles
+ ** \arg EFM_LATENCY_7 FLASH 7 Latency cycles
+ ** \arg EFM_LATENCY_8 FLASH 8 Latency cycles
+ ** \arg EFM_LATENCY_9 FLASH 9 Latency cycles
+ ** \arg EFM_LATENCY_10 FLASH 10 Latency cycles
+ ** \arg EFM_LATENCY_11 FLASH 11 Latency cycles
+ ** \arg EFM_LATENCY_12 FLASH 12 Latency cycles
+ ** \arg EFM_LATENCY_13 FLASH 13 Latency cycles
+ ** \arg EFM_LATENCY_14 FLASH 14 Latency cycles
+ ** \arg EFM_LATENCY_15 FLASH 15 Latency cycles
+ **
+ ** \retval None
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+void EFM_SetLatency(uint32_t u32Latency)
+{
+ DDL_ASSERT(IS_VALID_FLASH_LATENCY(u32Latency));
+
+ M4_EFM->FRMC_f.FLWT = u32Latency;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Enable or disable the flash instruction cache.
+ **
+ ** \param [in] enNewState The new state of the flash instruction cache.
+ ** \arg Enable Enable flash instruction cache.
+ ** \arg Disable Disable flash instruction cache.
+ **
+ ** \retval None
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+void EFM_InstructionCacheCmd(en_functional_state_t enNewState)
+{
+ DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
+
+ M4_EFM->FRMC_f.CACHE = enNewState;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Enable or disable the data cache reset.
+ **
+ ** \param [in] enNewState The new state of the data cache reset.
+ ** \arg Enable Enable data cache reset.
+ ** \arg Disable Disable data cache reset.
+ **
+ ** \retval None
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+void EFM_DataCacheRstCmd(en_functional_state_t enNewState)
+{
+ DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
+
+ M4_EFM->FRMC_f.CRST = enNewState;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Set the flash read mode.
+ **
+ ** \param [in] enReadMD The flash read mode.
+ ** \arg NormalRead Normal read mode.
+ ** \arg UltraPowerRead Ultra_Low power read mode.
+ **
+ ** \retval None.
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+void EFM_SetReadMode(en_efm_read_md_t enReadMD)
+{
+ DDL_ASSERT(IS_VALID_READ_MD(enReadMD));
+ M4_EFM->FRMC_f.SLPMD = enReadMD;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Enable or disable erase / program.
+ **
+ ** \param [in] enNewState The new state of the erase / program.
+ ** \arg Enable Enable erase / program.
+ ** \arg Disable Disable erase / program.
+ **
+ ** \retval None
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+void EFM_ErasePgmCmd(en_functional_state_t enNewState)
+{
+ DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
+
+ M4_EFM->FWMC_f.PEMODE = enNewState;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Set the flash erase program mode.
+ **
+ ** \param [in] u32Mode The flash erase program mode.
+ ** \arg EFM_MODE_READONLY The flash read only.
+ ** \arg EFM_MODE_SINGLEPROGRAM The flash single program.
+ ** \arg EFM_MODE_SINGLEPROGRAMRB The flash single program with read back.
+ ** \arg EFM_MODE_SEQUENCEPROGRAM The flash sequence program.
+ ** \arg EFM_MODE_SECTORERASE The flash sector erase.
+ ** \arg EFM_MODE_CHIPERASE The flash mass erase.
+ **
+ ** \retval en_result_t.
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+en_result_t EFM_SetErasePgmMode(uint32_t u32Mode)
+{
+ en_result_t enRet = Ok;
+ uint16_t u16Timeout = 0u;
+
+ DDL_ASSERT(IS_VALID_ERASE_PGM_MD(u32Mode));
+
+ while(1ul != M4_EFM->FSR_f.RDY)
+ {
+ u16Timeout++;
+ if(u16Timeout > 0x1000u)
+ {
+ enRet = ErrorTimeout;
+ break;
+ }
+ }
+ if(Ok == enRet)
+ {
+ M4_EFM->FWMC_f.PEMODE = Enable;
+ M4_EFM->FWMC_f.PEMOD = u32Mode;
+ M4_EFM->FWMC_f.PEMODE = Disable;
+ }
+
+ return enRet;
+}
+/**
+ *******************************************************************************
+ ** \brief Enable or disable the specified interrupt.
+ **
+ ** \param [in] enInt The specified interrupt.
+ ** \arg PgmErsErrInt Program erase error interrupt.
+ ** \arg EndPgmInt End of Program interrupt.
+ ** \arg ReadErrInt Read collided error flag.
+ **
+ ** \param [in] enNewState The new state of the specified interrupt.
+ ** \arg Enable Enable the specified interrupt.
+ ** \arg Disable Disable the specified interrupt.
+ **
+ ** \retval None
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+void EFM_InterruptCmd(en_efm_int_sel_t enInt, en_functional_state_t enNewState)
+{
+ DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState));
+ DDL_ASSERT(IS_VALID_EFM_INT_SEL(enInt));
+
+ switch(enInt)
+ {
+ case PgmErsErrInt:
+ M4_EFM->FITE_f.PEERRITE = enNewState;
+ break;
+ case EndPgmInt:
+ M4_EFM->FITE_f.OPTENDITE = enNewState;
+ break;
+ case ColErrInt:
+ M4_EFM->FITE_f.COLERRITE = enNewState;
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ *******************************************************************************
+ ** \brief Checks whether the specified FLASH flag is set or not..
+ **
+ ** \param [in] u32flag Specifies the FLASH flag to check.
+ ** \arg EFM_FLAG_WRPERR Flash write protect error flag.
+ ** \arg EFM_FLAG_PEPRTERR Flash program protect area error flag.
+ ** \arg EFM_FLAG_PGSZERR Flash program size error flag.
+ ** \arg EFM_FLAG_PGMISMTCH Flash program miss match flag.
+ ** \arg EFM_FLAG_EOP Flash end of program flag.
+ ** \arg EFM_FLAG_COLERR Flash collision error flag.
+ ** \arg EFM_FLAG_RDY Flash ready flag.
+ **
+ ** \retval The flash status.
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+en_flag_status_t EFM_GetFlagStatus(uint32_t u32flag)
+{
+ DDL_ASSERT(IS_VALID_FLASH_FLAG(u32flag));
+
+ return ((0ul == (M4_EFM->FSR & u32flag)) ? Reset :Set);
+}
+
+/**
+ *******************************************************************************
+ ** \brief Checks whether the specified FLASH flag is set or not..
+ **
+ ** \param [in] u32flag Specifies the FLASH flag to clear.
+ ** \arg EFM_FLAG_WRPERR Flash write protect error flag.
+ ** \arg EFM_FLAG_PEPRTERR Flash program protect area error flag.
+ ** \arg EFM_FLAG_PGSZERR Flash program size error flag.
+ ** \arg EFM_FLAG_PGMISMTCH Flash program miss match flag.
+ ** \arg EFM_FLAG_EOP Flash end of program flag.
+ ** \arg EFM_FLAG_COLERR Flash collision error flag.
+ **
+ ** \retval The flash status.
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+void EFM_ClearFlag(uint32_t u32flag)
+{
+ //DDL_ASSERT(IS_VALID_CLEAR_FLASH_FLAG(u32flag));
+
+ M4_EFM->FSCLR = u32flag;
+}
+/**
+ *******************************************************************************
+ ** \brief Get the flash status.
+ **
+ ** \param None
+ **
+ ** \retval The flash status.
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+en_efm_flash_status_t EFM_GetStatus(void)
+{
+ en_efm_flash_status_t enFlashStatus = FlashEOP;
+
+ if(1ul == M4_EFM->FSR_f.RDY )
+ {
+ enFlashStatus = FlashReady;
+ }
+ else if(1ul == M4_EFM->FSR_f.COLERR)
+ {
+ enFlashStatus = FlashRWErr;
+ }
+ else if(1ul == M4_EFM->FSR_f.OPTEND)
+ {
+ enFlashStatus = FlashEOP;
+ }
+ else if(1ul == M4_EFM->FSR_f.PGMISMTCH)
+ {
+ enFlashStatus = FlashPgMissMatch;
+ }
+ else if(1ul == M4_EFM->FSR_f.PGSZERR)
+ {
+ enFlashStatus = FlashPgSizeErr;
+ }
+ else if(1ul == M4_EFM->FSR_f.PEPRTERR)
+ {
+ enFlashStatus = FlashPgareaPErr;
+ }
+ else if(1ul == M4_EFM->FSR_f.PEWERR)
+ {
+ enFlashStatus = FlashWRPErr;
+ }
+ else
+ {
+ //else
+ }
+
+ return enFlashStatus;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Set flash the windows protect address.
+ **
+ ** \param [in] stcAddr The specified windows protect address.
+ ** \arg StartAddr The start of windows protect address.
+ ** \arg EndAddr The end of windows protect address.
+ **
+ ** \retval None
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+void EFM_SetWinProtectAddr(stc_efm_win_protect_addr_t stcAddr)
+{
+ M4_EFM->FPMTSW_f.FPMTSW = (stcAddr.StartAddr & EFM_PROTECT_ADDR_MSK);
+ M4_EFM->FPMTEW_f.FPMTEW = (stcAddr.EndAddr & EFM_PROTECT_ADDR_MSK);
+}
+
+/**
+ *******************************************************************************
+ ** \brief Set bus state while flash program & erase.
+ **
+ ** \param [in] enState The specified bus state while flash program & erase.
+ ** \arg BusBusy The bus busy.
+ ** \arg BusRelease The bus release.
+ **
+ ** \retval None
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+void EFM_SetBusState(en_efm_bus_sta_t enState)
+{
+ M4_EFM->FWMC_f.BUSHLDCTL = enState;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Flash single program without read back.
+ **
+ ** \param [in] u32Addr The specified program address.
+ ** \param [in] u32Data The specified program data.
+ **
+ ** \retval en_result_t
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+en_result_t EFM_SingleProgram(uint32_t u32Addr, uint32_t u32Data)
+{
+ en_result_t enRet = Ok;
+ uint8_t u8tmp;
+ uint16_t u16Timeout = 0u;
+
+ DDL_ASSERT(IS_VALID_FLASH_ADDR(u32Addr));
+
+ /* CLear the error flag. */
+ EFM_ClearFlag(EFM_FLAG_WRPERR | EFM_FLAG_PEPRTERR | EFM_FLAG_PGSZERR |
+ EFM_FLAG_PGMISMTCH | EFM_FLAG_EOP | EFM_FLAG_COLERR);
+
+ /* read back CACHE */
+ u8tmp = (uint8_t)M4_EFM->FRMC_f.CACHE;
+
+ M4_EFM->FRMC_f.CACHE = Disable;
+
+ /* Enable program. */
+ EFM_ErasePgmCmd(Enable);
+ /* Set single program mode. */
+ M4_EFM->FWMC_f.PEMOD = EFM_MODE_SINGLEPROGRAM;
+ /* program data. */
+ *(uint32_t*)u32Addr = u32Data;
+
+ while(1ul != M4_EFM->FSR_f.RDY)
+ {
+ u16Timeout++;
+ if(u16Timeout > 0x1000u)
+ {
+ enRet = ErrorTimeout;
+ }
+ }
+
+ if(u32Data != *(uint32_t*)u32Addr)
+ {
+ enRet = Error;
+ }
+
+ EFM_ClearFlag(EFM_FLAG_EOP);
+ /* Set read only mode. */
+ M4_EFM->FWMC_f.PEMOD = EFM_MODE_READONLY;
+ EFM_ErasePgmCmd(Disable);
+
+ /* recover CACHE */
+ M4_EFM->FRMC_f.CACHE = u8tmp;
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Flash single program with read back.
+ **
+ ** \param [in] u32Addr The specified program address.
+ ** \param [in] u32Data The specified program data.
+ **
+ ** \retval en_result_t
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+en_result_t EFM_SingleProgramRB(uint32_t u32Addr, uint32_t u32Data)
+{
+ en_result_t enRet = Ok;
+ uint8_t u8tmp = 0u;
+ uint16_t u16Timeout = 0u;
+
+ DDL_ASSERT(IS_VALID_FLASH_ADDR(u32Addr));
+
+ /* CLear the error flag. */
+ EFM_ClearFlag(EFM_FLAG_WRPERR | EFM_FLAG_PEPRTERR | EFM_FLAG_PGSZERR |
+ EFM_FLAG_PGMISMTCH | EFM_FLAG_EOP | EFM_FLAG_COLERR);
+
+ /* read back CACHE */
+ u8tmp = (uint8_t)M4_EFM->FRMC_f.CACHE;
+
+ M4_EFM->FRMC_f.CACHE = Disable;
+
+ /* Enable program. */
+ EFM_ErasePgmCmd(Enable);
+ /* Set single program with read back mode. */
+ M4_EFM->FWMC_f.PEMOD = EFM_MODE_SINGLEPROGRAMRB;
+ /* program data. */
+ *(uint32_t*)u32Addr = u32Data;
+
+ while(1ul != M4_EFM->FSR_f.RDY)
+ {
+ u16Timeout++;
+ if(u16Timeout > 0x1000u)
+ {
+ enRet = ErrorTimeout;
+ }
+ }
+
+ if(1ul == M4_EFM->FSR_f.PGMISMTCH)
+ {
+ enRet = Error;
+ }
+
+ EFM_ClearFlag(EFM_FLAG_EOP);
+ /* Set read only mode. */
+ M4_EFM->FWMC_f.PEMOD = EFM_MODE_READONLY;
+ EFM_ErasePgmCmd(Disable);
+
+ /* recover CACHE */
+ M4_EFM->FRMC_f.CACHE = u8tmp;
+
+ return enRet;
+}
+
+static void *EFM_Memcpy(void *pvDst, void *pvSrc, uint32_t u32Count)
+{
+ uint8_t *u8TmpDst = (uint8_t *)pvDst;
+ uint8_t *u8TmpSrc = (uint8_t *)pvSrc;
+
+ DDL_ASSERT(IS_VALID_POINTER(pvDst));
+ DDL_ASSERT(IS_VALID_POINTER(pvSrc));
+
+ while (u32Count--)
+ {
+ *u8TmpDst++ = *u8TmpSrc++;
+ }
+
+ return pvDst;
+}
+/**
+ *******************************************************************************
+ ** \brief Flash sequence program.
+ **
+ ** \param [in] u32Addr The specified program address.
+ ** \param [in] u32Len The len of specified program data.
+ ** \param [in] *pBuf The pointer of specified program data.
+ **
+ ** \retval en_result_t
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+en_result_t EFM_SequenceProgram(uint32_t u32Addr, uint32_t u32Len, void *pBuf)
+{
+ en_result_t enRet = Ok;
+ uint8_t u8tmp;
+ uint32_t i;
+ uint16_t u16Timeout = 0u;
+ uint32_t u32Tmp = 0xFFFFFFFFul;
+ uint32_t *u32pSrc = pBuf;
+ uint32_t *u32pDest = (uint32_t *)u32Addr;
+ uint32_t u32LoopWords = u32Len >> 2ul;
+ uint32_t u32RemainBytes = u32Len % 4ul;
+
+ DDL_ASSERT(IS_VALID_FLASH_ADDR(u32Addr));
+ DDL_ASSERT(IS_VALID_POINTER(pBuf));
+
+ /* CLear the error flag. */
+ EFM_ClearFlag(EFM_FLAG_WRPERR | EFM_FLAG_PEPRTERR | EFM_FLAG_PGSZERR |
+ EFM_FLAG_PGMISMTCH | EFM_FLAG_EOP | EFM_FLAG_COLERR);
+
+ /* read back CACHE */
+ u8tmp = (uint8_t)M4_EFM->FRMC_f.CACHE;
+
+ M4_EFM->FRMC_f.CACHE = Disable;
+
+ /* Enable program. */
+ EFM_ErasePgmCmd(Enable);
+ /* Set sequence program mode. */
+ M4_EFM->FWMC_f.PEMOD = EFM_MODE_SEQUENCEPROGRAM;
+ /* clear read collided error flag.*/
+ EFM_ClearFlag(EFM_FLAG_COLERR);
+ EFM_ClearFlag(EFM_FLAG_WRPERR);
+
+ /* program data. */
+ for(i = 0ul; i < u32LoopWords; i++)
+ {
+ *u32pDest++ = *u32pSrc++;
+ /* wait operate end. */
+ while(1ul != M4_EFM->FSR_f.OPTEND)
+ {
+ u16Timeout++;
+ if(u16Timeout > 0x1000u)
+ {
+ enRet = ErrorTimeout;
+ }
+ }
+ /* clear end flag. */
+ EFM_ClearFlag(EFM_FLAG_EOP);
+ }
+ if(u32RemainBytes)
+ {
+ EFM_Memcpy(&u32Tmp, u32pSrc, u32RemainBytes);
+ *u32pDest++ = u32Tmp;
+ }
+
+ /* Set read only mode. */
+ M4_EFM->FWMC_f.PEMOD = EFM_MODE_READONLY;
+
+ u16Timeout = 0u;
+ while(1ul != M4_EFM->FSR_f.RDY)
+ {
+ u16Timeout++;
+ if(u16Timeout > 0x1000u)
+ {
+ enRet = ErrorTimeout;
+ }
+ }
+
+ EFM_ClearFlag(EFM_FLAG_EOP);
+ EFM_ErasePgmCmd(Disable);
+
+ /* recover CACHE */
+ M4_EFM->FRMC_f.CACHE = u8tmp;
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Flash sector erase.
+ **
+ ** \param [in] u32Addr The uncertain(random) address in the specified sector.
+ **
+ ** \retval en_result_t
+ **
+ ** \note The address should be word align.
+ **
+ ******************************************************************************/
+en_result_t EFM_SectorErase(uint32_t u32Addr)
+{
+ uint8_t u8tmp;
+ uint16_t u16Timeout = 0u;
+ en_result_t enRet = Ok;
+
+ DDL_ASSERT(IS_VALID_FLASH_ADDR(u32Addr));
+
+ /* CLear the error flag. */
+ EFM_ClearFlag(EFM_FLAG_WRPERR | EFM_FLAG_PEPRTERR | EFM_FLAG_PGSZERR |
+ EFM_FLAG_PGMISMTCH | EFM_FLAG_EOP | EFM_FLAG_COLERR);
+
+ /* read back CACHE */
+ u8tmp = (uint8_t)M4_EFM->FRMC_f.CACHE;
+
+ M4_EFM->FRMC_f.CACHE = Disable;
+
+ /* Enable erase. */
+ EFM_ErasePgmCmd(Enable);
+ /* Set sector erase mode. */
+ M4_EFM->FWMC_f.PEMOD = EFM_MODE_SECTORERASE;
+
+ *(uint32_t*)u32Addr = 0x12345678u;
+
+ while(1ul != M4_EFM->FSR_f.RDY)
+ {
+ u16Timeout++;
+ if(u16Timeout > 0x1000u)
+ {
+ enRet = ErrorTimeout;
+ }
+ }
+
+ EFM_ClearFlag(EFM_FLAG_EOP);
+ /* Set read only mode. */
+ M4_EFM->FWMC_f.PEMOD = EFM_MODE_READONLY;
+ EFM_ErasePgmCmd(Disable);
+
+ /* recover CACHE */
+ M4_EFM->FRMC_f.CACHE = u8tmp;
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Flash mass erase.
+ **
+ ** \param [in] u32Addr The uncertain(random) address in the flash.
+ **
+ ** \retval en_result_t
+ **
+ ** \note The address should be word align.
+ **
+ ******************************************************************************/
+en_result_t EFM_MassErase(uint32_t u32Addr)
+{
+ uint8_t u8tmp;
+ uint16_t u16Timeout = 0u;
+ en_result_t enRet = Ok;
+
+ DDL_ASSERT(IS_VALID_FLASH_ADDR(u32Addr));
+
+ /* CLear the error flag. */
+ EFM_ClearFlag(EFM_FLAG_WRPERR | EFM_FLAG_PEPRTERR | EFM_FLAG_PGSZERR |
+ EFM_FLAG_PGMISMTCH | EFM_FLAG_EOP | EFM_FLAG_COLERR);
+
+ /* read back CACHE */
+ u8tmp = (uint8_t)M4_EFM->FRMC_f.CACHE;
+
+ M4_EFM->FRMC_f.CACHE = Disable;
+
+ /* Enable erase. */
+ EFM_ErasePgmCmd(Enable);
+ /* Set sector erase mode. */
+ M4_EFM->FWMC_f.PEMOD = EFM_MODE_CHIPERASE;
+
+ *(uint32_t*)u32Addr = 0x12345678u;
+
+ while(1ul != M4_EFM->FSR_f.RDY)
+ {
+ u16Timeout++;
+ if(u16Timeout > 0x1000u)
+ {
+ enRet = ErrorTimeout;
+ }
+ }
+
+ EFM_ClearFlag(EFM_FLAG_EOP);
+ /* Set read only mode. */
+ M4_EFM->FWMC_f.PEMOD = EFM_MODE_READONLY;
+ EFM_ErasePgmCmd(Disable);
+
+ /* recover CACHE */
+ M4_EFM->FRMC_f.CACHE = u8tmp;
+
+ return enRet;
+}
+
+/**
+ *******************************************************************************
+ ** \brief Get flash switch status.
+ **
+ ** \param None.
+ **
+ ** \retval en_flag_status_t
+ ** \arg Set The flash has switched, the start address is sector1.
+ ** \arg Reset The flash did not switch, the start address is sector0.
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+en_flag_status_t EFM_GetSwitchStatus(void)
+{
+ return ((0u == M4_EFM->FSWP_f.FSWP) ? Set : Reset);
+}
+
+/**
+ *******************************************************************************
+ ** \brief Lock OTP data block.
+ **
+ ** \param u32Addr The addr to lock.
+ **
+ ** \retval en_result_t
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+en_result_t EFM_OtpLock(uint32_t u32Addr)
+{
+ DDL_ASSERT(IS_VALID_OTP_LOCK_ADDR(u32Addr));
+ uint16_t u16Timeout = 0u;
+ en_result_t enRet = Ok;
+
+ /* Enable program. */
+ EFM_ErasePgmCmd(Enable);
+ /* Set single program mode. */
+ M4_EFM->FWMC_f.PEMOD = EFM_MODE_SINGLEPROGRAM;
+
+ /* Lock the otp block. */
+ *(uint32_t*)u32Addr = 0ul;
+
+ while(1ul != M4_EFM->FSR_f.RDY)
+ {
+ u16Timeout++;
+ if(u16Timeout > 0x1000u)
+ {
+ enRet = ErrorTimeout;
+ }
+ }
+
+ EFM_ClearFlag(EFM_FLAG_EOP);
+ /* Set read only mode. */
+ M4_EFM->FWMC_f.PEMOD = EFM_MODE_READONLY;
+ EFM_ErasePgmCmd(Disable);
+
+ return enRet;
+}
+/**
+ *******************************************************************************
+ ** \brief read unique ID.
+ **
+ ** \param None
+ **
+ ** \retval uint32_t
+ **
+ ** \note None
+ **
+ ******************************************************************************/
+stc_efm_unique_id_t EFM_ReadUID(void)
+{
+ stc_efm_unique_id_t stcUID;
+
+ stcUID.uniqueID1 = M4_EFM->UQID1;
+ stcUID.uniqueID2 = M4_EFM->UQID2;
+ stcUID.uniqueID3 = M4_EFM->UQID3;
+
+ return stcUID;
+}
+
+//@} // EfmGroup
+
+/*******************************************************************************
+ * EOF (not truncated)
+ ******************************************************************************/