PeripheralDriver_Flagchip_F.../Src/fc7xxx_driver_flash.c

999 lines
31 KiB
C

/**
* @file fc7xxx_driver_flash.c
* @author Flagchip
* @brief FC7xxx Flash driver source code
* @version 0.1.0
* @date 2024-01-11
*
* @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd.
*
*/
/* ********************************************************************************
* Revision History:
*
* Version Date Initials CR# Descriptions
* --------- ---------- ------------ ---------- ---------------
* 0.1.0 2024-01-11 Flagchip054 N/A First version for FC7240
******************************************************************************** */
#include "fc7xxx_driver_flash.h"
/* ################################################################################## */
/* ####################################### Macro #################################### */
#define STATUS_SUCCESS 0x001UL
#define STATUS_HVOP 0x8001UL
#define FLASH_API_DISABLE 0x0UL
#define FLASH_API_ENABLE 0x1UL
#define FLASH_API_SIZE_8M 0x0UL
#define WDG_TUNE_DISABLE 0x1u
#define FLASH_AUTO_HOLD_ENABLE 0x1UL
#define FLASH_AUTO_HOLD_DISABLE 0x0UL
#define FLASH_REG_BIT_CFG_DISABLE 0x0UL
#define FLASH_REG_BIT_CFG_ENABLE 0x1UL
#define FLASH_REG_BIT_CFG_HOLD 0x2UL
#define INVAILD_ADDR ((void*)0xFFFFFFFFU)
#define FLS_MAX_ERASE_BLANK_CHECK (256U)
#define FLS_ABT_TIMEOUT_VALUE (1000000U)
#define FLS_ASYNC_WRITE_TIMEOUT_VALUE (1000U)
#define FLS_ASYNC_ERASE_TIMEOUT_VALUE (500000U)
/*=================================================================================================
* LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
=================================================================================================*/
typedef uint32_t status_t;
typedef struct {
uint32_t blk_sel;
uint32_t dest;
} FLASH_DRV_ERASESECTOR_CFG_T;
typedef struct {
uint32_t dest;
uint32_t size;
uint32_t *pData;
uint32_t wdg_tune;
uint32_t pgff;
} FLASH_DRV_PRGM_CFG_T;
typedef struct
{
uint16 u16FlashRomApiMajorVersion;
uint16 u16FlashRomApiMinorVersion;
status_t (*FLASH_DRV_EraseBlock)(FLASH_API_BLOCK_SELECT_TYPE blk_se, uint32_t int_en, uint32_t type);
status_t (*FLASH_DRV_EraseBlock_Clear)(void);
status_t (*FLASH_DRV_EraseSector)(FLASH_DRV_ERASESECTOR_CFG_T * flash_api_cfg, uint32_t int_en, uint32_t type);
status_t (*FLASH_DRV_EraseSector_Clear)(void);
uint32_t RESERVED2[2U];
status_t (*FLASH_DRV_Program)(FLASH_DRV_PRGM_CFG_T * flash_api_cfg, uint32_t int_en, uint32_t type);
status_t (*FLASH_DRV_Program_Clear)(void);
uint32_t RESERVED3[6U];
status_t (*FLASH_DRV_HV_Status_Check)(void);
uint32_t RESERVED4[8U];
status_t (*FLASH_DRV_ENABLE_HOLD_CFG)(uint32_t flash_api_cfg);
}FLASH_ROM_API_ENTRY_T;
/** flash driver header for finding function in special address */
#define FLASHAPI_IN_ROM_ADDR 0x04810200U /* flash api address in rom */
const FLASH_ROM_API_ENTRY_T *s_pFlashDriver_RomApiHeader;
/* ################################################################################## */
/* ################################ Local Variables ################################# */
/* ################################################################################## */
/* ########################### Local Prototype Functions ############################ */
/* ################################################################################## */
/* ########################### Global Prototype Functions ########################### */
/* ################################################################################## */
/* ################################ Local Functions ################################# */
/**
* \brief PFlash Driver Function for Erasing Address Check
*
* \param pFlashParam flash driver erase parameter
*/
static FLASH_StatusType FLASHDRIVER_LL_PFlashEraseCheck(FLASH_DRIVER_ParamType *pFlashParam)
{
FLASH_StatusType tRetVal;
if (s_pFlashDriver_RomApiHeader != (FLASH_ROM_API_ENTRY_T *)FLASHAPI_IN_ROM_ADDR)
{
tRetVal = FLASH_ERROR_NO_INIT;
}
else
{
tRetVal = FLASH_ERROR_OK;
/* check address align */
if (pFlashParam->u32Address & (PFLASH_ERASE_SECTOR_SIZE - 1U))
{
tRetVal = FLASH_ERROR_INVALID_ADDR;
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
}
else
{
/* check length align */
if (pFlashParam->u32Length & (PFLASH_ERASE_SECTOR_SIZE - 1U))
{
tRetVal = FLASH_ERROR_INVALID_SIZE;
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
}
}
}
return tRetVal;
}
/**
* \brief DFlash Driver Function for Erasing Address Check
*
* \param pFlashParam flash driver erase parameter
*/
static FLASH_StatusType FLASHDRIVER_LL_DFlashEraseCheck(FLASH_DRIVER_ParamType *pFlashParam)
{
FLASH_StatusType tRetVal;
if (s_pFlashDriver_RomApiHeader != (FLASH_ROM_API_ENTRY_T *)FLASHAPI_IN_ROM_ADDR)
{
tRetVal = FLASH_ERROR_NO_INIT;
}
else
{
tRetVal = FLASH_ERROR_OK;
/* check address align */
if (pFlashParam->u32Address & (DFLASH_ERASE_SECTOR_SIZE - 1U))
{
tRetVal = FLASH_ERROR_INVALID_ADDR;
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
}
else
{
/* check length align */
if (pFlashParam->u32Length & (DFLASH_ERASE_SECTOR_SIZE - 1U))
{
tRetVal = FLASH_ERROR_INVALID_SIZE;
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
}
}
}
return tRetVal;
}
/**
* \brief PFlash Driver Function for Writing address Check
*
* \param pFlashParam flash driver write parameter
*/
static FLASH_StatusType FLASHDRIVER_PFlashWriteCheck(FLASH_DRIVER_ParamType *pFlashParam)
{
FLASH_StatusType tRetVal;
if (s_pFlashDriver_RomApiHeader != (FLASH_ROM_API_ENTRY_T *)FLASHAPI_IN_ROM_ADDR)
{
tRetVal = FLASH_ERROR_NO_INIT;
}
else
{
tRetVal = FLASH_ERROR_OK;
/* check address align */
if (pFlashParam->u32Address & (PFLASH_PROGRAM_PAGE_MIN_SIZE - 1U))
{
tRetVal = FLASH_ERROR_INVALID_ADDR;
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
}
else
{
/* check length align */
if (pFlashParam->u32Length & (PFLASH_PROGRAM_PAGE_MIN_SIZE - 1U))
{
tRetVal = FLASH_ERROR_INVALID_SIZE;
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
}
}
}
return tRetVal;
}
/**
* \brief DFlash Driver Function for Writing address Check
*
* \param pFlashParam flash driver write parameter
*/
static FLASH_StatusType FLASHDRIVER_DFlashWriteCheck(FLASH_DRIVER_ParamType *pFlashParam)
{
FLASH_StatusType tRetVal;
if (s_pFlashDriver_RomApiHeader != (FLASH_ROM_API_ENTRY_T *)FLASHAPI_IN_ROM_ADDR)
{
tRetVal = FLASH_ERROR_NO_INIT;
}
else
{
tRetVal = FLASH_ERROR_OK;
/* check address align */
if (pFlashParam->u32Address & (DFLASH_PROGRAM_PAGE_MIN_SIZE - 1U))
{
tRetVal = FLASH_ERROR_INVALID_ADDR;
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
}
else
{
/* check length align */
if (pFlashParam->u32Length & (DFLASH_PROGRAM_PAGE_MIN_SIZE - 1U))
{
tRetVal = FLASH_ERROR_INVALID_SIZE;
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
}
}
}
return tRetVal;
}
/**
* \brief PFlash Driver Function for lock/unlock sector
*
* \param u32Address sector address
* \param bLock 0U-unlock, 1U-lock
*/
static void FLASHDRIVER_PFlashLockBlock(FLASH_API_BLOCK_SELECT_TYPE blk_sel, uint8_t bLock)
{
uint32_t u32Index;
uint32_t u32Temp;
u32Index = (uint32_t)blk_sel;
/* 1 bank contains more than 256KB, used FB_CPELCK for first and last 256KB used FB_FPELCK */
/* PFLASH bank index */
u32Temp = bLock ? 0xFFFFFFFFUL : 0x0UL;
if(blk_sel < FLASH_DATA_BLOCK_SELECT0)
{
FMC1->FB_CPELCK[u32Index] = u32Temp;
FMC1->FB_FPELCK[u32Index] = u32Temp;
}
else
{
FMC1->FB_FPELCK[u32Index] = u32Temp;
}
}
/**
* \brief PFlash Driver Function for lock/unlock sector
*
* \param u32Address sector address
* \param bLock 0U-unlock, 1U-lock
*/
static FLASH_StatusType FLASHDRIVER_PFlashLockSector(uint32_t u32Address, uint8_t bLock)
{
FLASH_StatusType tRetVal;
uint32_t u32Index;
uint32_t u32Length;
uint32_t u32Temp;
tRetVal = FLASH_ERROR_OK;
/* 1 bank contains more than 256KB, used FB_CPELCK for first and last 256KB used FB_FPELCK */
if ((u32Address >= PFLASH_ADDR_START) && (u32Address <= PFLASH_ADDR_END))
{
/* PFLASH bank index */
u32Index = (u32Address - PFLASH_ADDR_START) / PFLASH_BANK_SIZE;
u32Length = ((u32Address - PFLASH_ADDR_START) % PFLASH_BANK_SIZE) ;
if (u32Length < (PFLASH_BANK_SIZE - FLASH_256KB_SIZE)) /* first 1792KB */
{
u32Temp = ((uint32_t)1UL << ((u32Address - PFLASH_ADDR_START - PFLASH_BANK_SIZE * u32Index) >> 16));
u32Temp = bLock ? 0xFFFFFFFFUL : (0xFFFFFFFFUL ^ u32Temp);
FMC1->FB_CPELCK[u32Index] = u32Temp;
}
else /* last 256KB */
{
u32Temp = ((u32Address - PFLASH_ADDR_START - PFLASH_BANK_SIZE * u32Index - PFLASH_LAST256K_OFFSET) >> 13);
u32Temp = ((uint32_t)1UL << u32Temp);
u32Temp = bLock ? 0xFFFFFFFFUL : (0xFFFFFFFFUL ^ u32Temp);
/* 0x1C0000UL */
FMC1->FB_FPELCK[u32Index] = u32Temp;
}
}
else
{
tRetVal = FLASH_ERROR_INVALID_ADDR;
}
return tRetVal;
}
/**
* \brief DFlash Driver Function for lock/unlock sector
*
* \param u32Address sector address
* \param bLock 0U-unlock, 1U-lock
*/
static FLASH_StatusType FLASHDRIVER_DFlashLockSector(uint32_t u32Address, uint8_t bLock)
{
FLASH_StatusType tRetVal;
uint32_t u32Index;
uint32_t u32Temp;
tRetVal = FLASH_ERROR_OK;
/* 1 bank contains only 256KB, only used FB_FPELCK */
u32Index = 2U;
if ((u32Address >= DFLASH_ADDR_START) && (u32Address <= DFLASH_ADDR_END))
{
u32Temp = 0xFFFFFFFFUL ^ (1UL << ((u32Address - DFLASH_ADDR_START - DFLASH_BANK0_SIZE * (u32Index - 2U)) >> 13));
FMC1->FB_FPELCK[u32Index] = bLock ? 0xFFFFFFFFUL : u32Temp ;
}
else
{
tRetVal = FLASH_ERROR_INVALID_ADDR;
}
return tRetVal;
}
/**
* \brief Get Flash Configuration
*
* \param u32Address the flash address
* \param pFlash_api_cfg out flash parameter
*/
static FLASH_StatusType FLASHDRIVER_GetFlashConfig(uint32_t u32Address, FLASH_DRV_ERASESECTOR_CFG_T *pFlash_api_cfg)
{
FLASH_StatusType tRetVal;
tRetVal = FLASH_ERROR_OK;
if ((u32Address >= PFLASH_ADDR_START) && (u32Address < PFLASH_ADDR_START + PFLASH_BANK_SIZE))
{
pFlash_api_cfg->blk_sel = FLASH_BLOCK_SELECT0;
pFlash_api_cfg->dest = u32Address;
}
else if ((u32Address >= PFLASH_ADDR_START) && (u32Address < PFLASH_ADDR_START + PFLASH_BANK_SIZE*2U))
{
pFlash_api_cfg->blk_sel = FLASH_BLOCK_SELECT1;
pFlash_api_cfg->dest = u32Address;
}
else if ((u32Address >= DFLASH_ADDR_START) && (u32Address < DFLASH_ADDR_START + DFLASH_BANK0_SIZE))
{
pFlash_api_cfg->blk_sel = FLASH_DATA_BLOCK_SELECT0;
pFlash_api_cfg->dest = u32Address;
}
else
{
tRetVal = FLASH_ERROR_INVALID_ADDR;
}
return tRetVal;
}
/* ################################################################################## */
/* ################################# Global Functions ############################### */
void FLASHDRIVER_Init(void)
{
s_pFlashDriver_RomApiHeader = (FLASH_ROM_API_ENTRY_T *)FLASHAPI_IN_ROM_ADDR;
}
/**
* \brief PFlash Driver Function for Erasing
*
* \param pFlashParam flash driver erase parameter
* \return ErrorType
*/
FLASH_StatusType FLASHDRIVER_FlashEraseBlock(FLASH_API_BLOCK_SELECT_TYPE blk_sel)
{
uint32_t u32TryCount;
FLASH_StatusType tRetVal;
uint32_t u32Temp;
tRetVal = FLASH_ERROR_OK;
if(blk_sel > FLASH_DATA_BLOCK_SELECT0)
{
tRetVal = FLASH_ERROR_INVALID_PARAM;
}
else
{
s_pFlashDriver_RomApiHeader->FLASH_DRV_ENABLE_HOLD_CFG(FLASH_AUTO_HOLD_ENABLE);
FLASHDRIVER_PFlashLockBlock(blk_sel, 0);
__asm(" cpsid i");
u32Temp = s_pFlashDriver_RomApiHeader-> FLASH_DRV_EraseBlock(blk_sel, FLASH_API_DISABLE, 0);
__asm(" cpsie i");
tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED;
/* check erase operation valid */
if (tRetVal != FLASH_ERROR_OK)
{
}
else
{
/* check erasing still in progress */
tRetVal = FLASH_ERROR_FAILED;
u32TryCount = 0;
while ((tRetVal != FLASH_ERROR_OK) && (u32TryCount++ < 1000000))
{
u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_HV_Status_Check();
/* check if finished */
if (u32Temp == STATUS_HVOP)
{
tRetVal = FLASH_ERROR_FAILED;
}
else
{
tRetVal = FLASH_ERROR_OK;
}
}
if (tRetVal != FLASH_ERROR_OK)
{
/* erasing timeout, exit */
*(uint32_t*)(0x00000014U) = *((uint32_t*)0x40020004U);
}
else
{
/* check erasing result */
u32Temp = s_pFlashDriver_RomApiHeader-> FLASH_DRV_EraseBlock_Clear();
tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED;
}
}
}
return tRetVal;
}
/**
* \brief PFlash Driver Function for Erasing
*
* \param pFlashParam flash driver erase parameter
* \return ErrorType
*/
FLASH_StatusType FLASHDRIVER_PFlashEraseSector(FLASH_DRIVER_ParamType *pFlashParam)
{
uint32_t u32Addr, u32Length;
uint32_t u32TryCount;
FLASH_DRV_ERASESECTOR_CFG_T tFlash_api_cfg;
FLASH_StatusType tRetVal;
uint32_t u32Temp;
tRetVal = FLASH_ERROR_OK;
/* FLASH_DRV_WDG_CFG_T tFlash_wdg_cfg; */
u32Addr = pFlashParam->u32Address;
u32Length = pFlashParam->u32Length;
tRetVal = FLASH_ERROR_OK;
pFlashParam->u32ErrorAddress = 0x0U;
tRetVal = FLASHDRIVER_LL_PFlashEraseCheck(pFlashParam);
if (tRetVal == FLASH_ERROR_OK)
{
/* config flash wdog */
//ConfigFlashWdog();
s_pFlashDriver_RomApiHeader->FLASH_DRV_ENABLE_HOLD_CFG(FLASH_AUTO_HOLD_ENABLE);
pFlashParam->u32Length = PFLASH_ERASE_SECTOR_SIZE;
/* loop erase */
for (pFlashParam->u32Address = u32Addr; pFlashParam->u32Address < u32Addr + u32Length;
pFlashParam->u32Address += PFLASH_ERASE_SECTOR_SIZE)
{
FLASHDRIVER_PFlashLockSector(pFlashParam->u32Address, 0U);
FLASHDRIVER_GetFlashConfig(pFlashParam->u32Address, &tFlash_api_cfg);
/* start erase */
__asm(" cpsid i");
u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_EraseSector(&tFlash_api_cfg, FLASH_API_DISABLE, 0);
__asm(" cpsie i");
tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED;
/* check erase operation valid */
if (tRetVal != FLASH_ERROR_OK)
{
/* erase operation failed, exit */
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
break;
}
else
{
/* check erasing still in progress */
tRetVal = FLASH_ERROR_FAILED;
u32TryCount = 0;
while ((tRetVal != FLASH_ERROR_OK) && (u32TryCount++ < 100000))
{
u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_HV_Status_Check();
/* check if finished */
if (u32Temp == STATUS_HVOP)
{
tRetVal = FLASH_ERROR_FAILED;
}
else
{
tRetVal = FLASH_ERROR_OK;
}
}
if (tRetVal != FLASH_ERROR_OK)
{
/* erasing timeout, exit */
*(uint32_t*)(0x00000014U) = *((uint32_t*)0x40020004U);
break;
}
else
{
/* check erasing result */
u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_EraseSector_Clear();
tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED;
if (tRetVal != FLASH_ERROR_OK)
{
/* erasing failed, exit */
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
break;
}
else
{
if (tRetVal != FLASH_ERROR_OK)
{
/* erasing failed, exit */
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
break;
}
else
{
/* trigger watchdog function */
if (pFlashParam->wdTriggerFct != ((void *)0))
{
pFlashParam->wdTriggerFct();
}
}
}
}
}
/* lock sector */
FLASHDRIVER_PFlashLockSector(pFlashParam->u32Address, 1U);
}
}
return tRetVal;
}
/**
* \brief PFlash Driver Function for Writing
*
* \param pFlashParam flash driver write parameter
* \return ErrorType
*/
FLASH_StatusType FLASHDRIVER_PFlashWrite(FLASH_DRIVER_ParamType *pFlashParam)
{
uint32_t u32Addr, u32Length, u32DataAddr, u32AlignLen, u32TempLen;
/* uint8_t *pTempBuf; */
uint32_t u32AlignOffset, u32Index, u32Count;
uint32_t u32TryCount;
FLASH_DRV_PRGM_CFG_T tFlash_api_cfg;
FLASH_StatusType tRetVal;
uint32_t u32Temp;
tRetVal = FLASH_ERROR_OK;
u32Addr = pFlashParam->u32Address;
u32Length = pFlashParam->u32Length;
pFlashParam->u32ErrorAddress = 0x0U;
tRetVal = FLASHDRIVER_PFlashWriteCheck(pFlashParam);
if (tRetVal == FLASH_ERROR_OK)
{
/* config flash wdog */
//ConfigFlashWdog();
s_pFlashDriver_RomApiHeader->FLASH_DRV_ENABLE_HOLD_CFG(FLASH_AUTO_HOLD_ENABLE);
/* align address, write must align to FLASH_PROGRAM_PAGE_MAX_SIZE */
u32AlignOffset = u32Addr & (PFLASH_PROGRAM_PAGE_MAX_SIZE - 1U);
u32AlignLen = u32Length + u32AlignOffset;
u32Count = u32AlignLen & (PFLASH_PROGRAM_PAGE_MAX_SIZE - 1U);
u32Count = u32Count > 0U ? 1U : 0U;
u32Count += u32AlignLen / PFLASH_PROGRAM_PAGE_MAX_SIZE;
u32DataAddr = (uint32_t)pFlashParam->pData;
u32TempLen = u32AlignLen;
for (u32Index = 0U; u32Index < u32Count; u32Index++)
{
/* real write length in this cycle */
u32TempLen = u32Length + u32AlignOffset;
u32TempLen = u32TempLen >= PFLASH_PROGRAM_PAGE_MAX_SIZE ? PFLASH_PROGRAM_PAGE_MAX_SIZE : u32TempLen;
u32TempLen -= u32AlignOffset;
pFlashParam->u32Address = u32Addr;
pFlashParam->u32Length = u32TempLen;
/* unlock sector */
FLASHDRIVER_PFlashLockSector(pFlashParam->u32Address, 0U);
tFlash_api_cfg.pgff = FLASH_REG_BIT_CFG_DISABLE;
tFlash_api_cfg.dest = pFlashParam->u32Address;
tFlash_api_cfg.size = (pFlashParam->u32Length / 4); /* one data is 4 bytes */
tFlash_api_cfg.pData = (uint32_t *)u32DataAddr;
tFlash_api_cfg.wdg_tune = WDG_TUNE_DISABLE;
/* next address and length */
u32Addr += u32TempLen;
u32DataAddr += u32TempLen;
u32Length -= u32TempLen;
u32AlignOffset = 0U;
/* start write */
__asm(" cpsid i");
u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_Program(&tFlash_api_cfg, FLASH_API_DISABLE, 0);
__asm(" cpsie i");
tRetVal = u32Temp == STATUS_SUCCESS ? FLASH_ERROR_OK : FLASH_ERROR_FAILED;
/* check erase operation valid */
if (tRetVal != FLASH_ERROR_OK)
{
/* write operation failed, exit */
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
break;
}
else
{
/* FLASHDRIVER_LL_Delay(); */
/* check write still in progress */
tRetVal = FLASH_ERROR_FAILED;
u32TryCount = 0;
while ((tRetVal != FLASH_ERROR_OK) && (u32TryCount++ < 10000))
{
u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_HV_Status_Check();
/* check if finished */
if (u32Temp == STATUS_HVOP)
{
tRetVal = FLASH_ERROR_FAILED;
}
else
{
tRetVal = FLASH_ERROR_OK;
}
}
if (tRetVal != FLASH_ERROR_OK)
{
/* erasing timeout, exit */
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
break;
}
else
{
/* check write result */
u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_Program_Clear();
tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED;
if (tRetVal != FLASH_ERROR_OK)
{
/* write failed, exit */
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
break;
}
else
{
/* trigger watchdog function */
if (pFlashParam->wdTriggerFct != ((void *)0))
{
pFlashParam->wdTriggerFct();
}
}
}
}
/* lock sector */
FLASHDRIVER_PFlashLockSector(pFlashParam->u32Address, 1U);
}
}
return tRetVal;
}
/**
* \brief DFlash Driver Function for Erasing
*
* \param pFlashParam flash driver erase parameter
* \return ErrorType
*/
FLASH_StatusType FLASHDRIVER_DFlashEraseSector(FLASH_DRIVER_ParamType *pFlashParam)
{
uint32_t u32Addr, u32Length;
uint32_t u32TryCount;
FLASH_DRV_ERASESECTOR_CFG_T tFlash_api_cfg;
FLASH_StatusType tRetVal;
uint32_t u32Temp;
tRetVal = FLASH_ERROR_OK;
u32Addr = pFlashParam->u32Address;
u32Length = pFlashParam->u32Length;
tRetVal = FLASH_ERROR_OK;
pFlashParam->u32ErrorAddress = 0x0U;
tRetVal = FLASHDRIVER_LL_DFlashEraseCheck(pFlashParam);
if (tRetVal == FLASH_ERROR_OK)
{
/* config flash wdog */
//ConfigFlashWdog();
s_pFlashDriver_RomApiHeader->FLASH_DRV_ENABLE_HOLD_CFG(FLASH_AUTO_HOLD_ENABLE);
pFlashParam->u32Length = DFLASH_ERASE_SECTOR_SIZE;
/* loop erase */
for (pFlashParam->u32Address = u32Addr; pFlashParam->u32Address < u32Addr + u32Length;
pFlashParam->u32Address += DFLASH_ERASE_SECTOR_SIZE)
{
/* unlock data flash */
FLASHDRIVER_DFlashLockSector(pFlashParam->u32Address, 0U);
FLASHDRIVER_GetFlashConfig(pFlashParam->u32Address, &tFlash_api_cfg);
/* start erase */
__asm(" cpsid i");
u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_EraseSector(&tFlash_api_cfg, FLASH_API_DISABLE, 0);
__asm(" cpsie i");
tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED;
/* check erase operation valid */
if (tRetVal != FLASH_ERROR_OK)
{
/* erase operation failed, exit */
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
break;
}
else
{
/* check erasing still in progress */
tRetVal = FLASH_ERROR_FAILED;
u32TryCount = 0;
while ((tRetVal != FLASH_ERROR_OK) && (u32TryCount++ < 100000))
{
u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_HV_Status_Check();
/* check if finished */
if (u32Temp == STATUS_HVOP)
{
tRetVal = FLASH_ERROR_FAILED;
}
else
{
tRetVal = FLASH_ERROR_OK;
}
}
if (tRetVal != FLASH_ERROR_OK)
{
/* erasing timeout, exit */
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
break;
}
else
{
/* check erasing result */
u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_EraseSector_Clear();
tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED;
if (tRetVal != FLASH_ERROR_OK)
{
/* erasing failed, exit */
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
break;
}
else
{
if (tRetVal != FLASH_ERROR_OK)
{
/* erasing failed, exit */
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
break;
}
else
{
/* trigger watchdog function */
if (pFlashParam->wdTriggerFct != ((void *)0))
{
pFlashParam->wdTriggerFct();
}
}
}
}
}
/* lock data flash */
FLASHDRIVER_DFlashLockSector(pFlashParam->u32Address, 1U);
}
}
return tRetVal;
}
/**
* \brief DFlash Driver Function for Writing
*
* \param pFlashParam flash driver write parameter
* \return ErrorType
*/
FLASH_StatusType FLASHDRIVER_DFlashWrite(FLASH_DRIVER_ParamType *pFlashParam)
{
uint32_t u32Addr, u32Length, u32DataAddr, u32AlignLen, u32TempLen;
/* uint8_t *pTempBuf; */
uint32_t u32AlignOffset, u32Index, u32Count;
uint32_t u32TryCount;
FLASH_DRV_PRGM_CFG_T tFlash_api_cfg;
FLASH_StatusType tRetVal;
uint32_t u32Temp;
tRetVal = FLASH_ERROR_OK;
u32Addr = pFlashParam->u32Address;
u32Length = pFlashParam->u32Length;
pFlashParam->u32ErrorAddress = 0x0U;
tRetVal = FLASHDRIVER_DFlashWriteCheck(pFlashParam);
if (tRetVal == FLASH_ERROR_OK)
{
/* config flash wdog */
//ConfigFlashWdog();
s_pFlashDriver_RomApiHeader->FLASH_DRV_ENABLE_HOLD_CFG(FLASH_AUTO_HOLD_ENABLE);
/* align address, write must align to FLASH_PROGRAM_PAGE_MAX_SIZE */
u32AlignOffset = u32Addr & (DFLASH_PROGRAM_PAGE_MAX_SIZE - 1U);
u32AlignLen = u32Length + u32AlignOffset;
u32Count = u32AlignLen & (DFLASH_PROGRAM_PAGE_MAX_SIZE - 1U);
u32Count = u32Count > 0U ? 1U : 0U;
u32Count += u32AlignLen / DFLASH_PROGRAM_PAGE_MAX_SIZE;
u32DataAddr = (uint32_t)pFlashParam->pData;
u32TempLen = u32AlignLen;
for (u32Index = 0U; u32Index < u32Count; u32Index++)
{
/* real write length in this cycle */
u32TempLen = u32Length + u32AlignOffset;
u32TempLen = u32TempLen >= DFLASH_PROGRAM_PAGE_MAX_SIZE ? DFLASH_PROGRAM_PAGE_MAX_SIZE : u32TempLen;
u32TempLen -= u32AlignOffset;
pFlashParam->u32Address = u32Addr;
pFlashParam->u32Length = u32TempLen;
/* unlock sector */
FLASHDRIVER_DFlashLockSector(pFlashParam->u32Address, 0U);
tFlash_api_cfg.pgff = FLASH_REG_BIT_CFG_DISABLE;
tFlash_api_cfg.dest = pFlashParam->u32Address;
tFlash_api_cfg.size = (pFlashParam->u32Length / 4); /* one data is 4 bytes */
tFlash_api_cfg.pData = (uint32_t *)u32DataAddr;
tFlash_api_cfg.wdg_tune = WDG_TUNE_DISABLE;
/* next address and length */
u32Addr += u32TempLen;
u32DataAddr += u32TempLen;
u32Length -= u32TempLen;
u32AlignOffset = 0U;
/* start write */
__asm(" cpsid i");
u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_Program(&tFlash_api_cfg, FLASH_API_DISABLE, 0);
__asm(" cpsie i");
tRetVal = u32Temp == STATUS_SUCCESS ? FLASH_ERROR_OK : FLASH_ERROR_FAILED;
/* check erase operation valid */
if (tRetVal != FLASH_ERROR_OK)
{
/* write operation failed, exit */
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
break;
}
else
{
/* FLASHDRIVER_LL_Delay(); */
/* check write still in progress */
tRetVal = FLASH_ERROR_FAILED;
u32TryCount = 0;
while ((tRetVal != FLASH_ERROR_OK) && (u32TryCount++ < 10000))
{
u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_HV_Status_Check();
/* check if finished */
if (u32Temp == STATUS_HVOP)
{
tRetVal = FLASH_ERROR_FAILED;
}
else
{
tRetVal = FLASH_ERROR_OK;
}
}
if (tRetVal != FLASH_ERROR_OK)
{
/* erasing timeout, exit */
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
break;
}
else
{
/* check write result */
u32Temp = s_pFlashDriver_RomApiHeader->FLASH_DRV_Program_Clear();
tRetVal = (u32Temp == STATUS_SUCCESS) ? FLASH_ERROR_OK : FLASH_ERROR_FAILED;
if (tRetVal != FLASH_ERROR_OK)
{
/* write failed, exit */
pFlashParam->u32ErrorAddress = pFlashParam->u32Address;
break;
}
else
{
/* trigger watchdog function */
if (pFlashParam->wdTriggerFct != ((void *)0))
{
pFlashParam->wdTriggerFct();
}
}
}
}
/* lock data flash */
FLASHDRIVER_DFlashLockSector(pFlashParam->u32Address, 1U);
}
}
return tRetVal;
}