PeripheralDriver_Flagchip_F.../Src/fc7xxx_driver_fmc.c

231 lines
8.0 KiB
C

/**
* @file fc7xxx_driver_fmc.c
* @author Flagchip
* @brief FC7xxx Fmc driver source code
* @version 0.1.0
* @date 2024-1-5
*
* @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd.
*/
/* ********************************************************************************
* Revision History:
*
* Version Date Initials CR# Descriptions
* --------- ---------- ------------ ---------- ---------------
* 0.1.0 2024-1-5 Flagchip120 N/A First version for FC7240
******************************************************************************** */
#include "fc7xxx_driver_fmc.h"
/* ################################################################################## */
/* ####################################### Macro #################################### */
/* ################################################################################## */
/* ################################ Local Variables ################################# */
static FMC_Type *const s_apFmcBase[FMC_INSTANCE_COUNT] = FMC_BASE_PTRS;
/* ################################################################################## */
/* ########################### Local Prototype Functions ############################ */
/**
* \brief FMC PFlash Driver Function for lock/unlock sector
*
* \param pFMC FMC instance
* \param u32Address sector address
* \param bLock 0U-unlock, 1U-lock
*/
static FMC_Lock_StatusType FMCDRIVER_PFlashLockRegion(const FMC_InstanceType eInstance, uint32_t u32Address, uint8_t bLock);
/**
* \brief FMC DFlash Driver Function for lock/unlock sector
*
* \param pFMC FMC instance
* \param u32Address sector address
* \param bLock 0U-unlock, 1U-lock
*/
static FMC_Lock_StatusType FMCDRIVER_DFlashLockRegion(const FMC_InstanceType eInstance, uint32_t u32Address, uint8_t bLock);
/* ################################################################################## */
/* ########################### Global Prototype Functions ########################### */
/* ################################################################################## */
/* ################################ Local Functions ################################# */
/**
* \brief FMC PFlash Driver Function for lock/unlock sector
*
* \param eInstance FMC instance
* \param u32Address sector address
* \param bLock 0U-unlock, 1U-lock
*/
static FMC_Lock_StatusType FMCDRIVER_PFlashLockRegion(const FMC_InstanceType eInstance, uint32_t u32Address, uint8_t bLock)
{
FMC_Type *const pFMC = s_apFmcBase[eInstance];
FMC_Lock_StatusType tRetVal;
uint32_t u32Index;
uint32_t u32Length;
uint32_t u32Temp;
tRetVal = FMC_LOCK_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_START + PFLASH_TOTAL_SIZE)))
{
/* 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 768KB */
{
u32Temp = ((uint32_t)1UL << ((u32Address - PFLASH_ADDR_START - PFLASH_BANK_SIZE * u32Index) >> 16));
u32Temp = bLock ? (FMC_HWA_GetFBCPELCKValue(pFMC, u32Index) | u32Temp) : (FMC_HWA_GetFBCPELCKValue(pFMC, u32Index) & ~u32Temp);
FMC_HWA_SetFBCPELCKValue(pFMC, u32Index, u32Temp);
}
else /* last 256KB */
{
u32Temp = ((u32Address - PFLASH_ADDR_START - PFLASH_BANK_SIZE * u32Index - PFLASH_PHANTOM_OFFSET) >> 13);
u32Temp = ((uint32_t)1UL << u32Temp);
u32Temp = bLock ? (FMC_HWA_GetFBFPELCKValue(pFMC, u32Index) | u32Temp) : (FMC_HWA_GetFBFPELCKValue(pFMC, u32Index) & ~u32Temp);
FMC_HWA_SetFBFPELCKValue(pFMC, u32Index, u32Temp);
}
}
else
{
tRetVal = FMC_LOCK_ERROR_INVALID_ADDR;
}
return tRetVal;
}
/**
* \brief FMC DFlash Driver Function for lock/unlock sector
*
* \param eInstance FMC instance
* \param u32Address sector address
* \param bLock 0U-unlock, 1U-lock
*/
static FMC_Lock_StatusType FMCDRIVER_DFlashLockRegion(const FMC_InstanceType eInstance, uint32_t u32Address, uint8_t bLock)
{
FMC_Type *const pFMC = s_apFmcBase[eInstance];
FMC_Lock_StatusType tRetVal;
uint32_t u32Index;
uint32_t u32Temp;
tRetVal = FMC_LOCK_ERROR_OK;
/* 1 bank contains only 128KB, only used FB_FPELCK */
u32Index = 2U;
if ((u32Address >= DFLASH_ADDR_START) && (u32Address <= DFLASH_ADDR_END))
{
u32Temp = 1UL << ((u32Address - DFLASH_ADDR_START - DFLASH_BANK0_SIZE * (u32Index - 2U)) >> 13);
u32Temp = bLock ? (FMC_HWA_GetFBFPELCKValue(pFMC, u32Index) | u32Temp) : (FMC_HWA_GetFBFPELCKValue(pFMC, u32Index) & ~u32Temp);
FMC_HWA_SetFBFPELCKValue(pFMC, u32Index, u32Temp);
}
else
{
tRetVal = FMC_LOCK_ERROR_INVALID_ADDR;
}
return tRetVal;
}
/* ################################################################################## */
/* ################################# Global Functions ############################### */
/**
* \brief FMC Driver Function for flash lock
*
* \param pFmcParam FMC driver flash lock parameter
* \return ErrorType
*/
FMC_Lock_StatusType FMCDRIVER_FlashLock(FMC_DRIVER_Lock_ParamType *pFmcParam)
{
uint32_t u32Addr, u32Length, u32LockSize, u32TempAddr;
FMC_Lock_StatusType tRetVal;
tRetVal = FMC_LOCK_ERROR_OK;
u32Addr = pFmcParam->u32Address;
u32Length = pFmcParam->u32Length;
u32LockSize = (pFmcParam->bClass == FMC_Page) ? FLASH_PROGRAM_PAGE_SIZE : FLASH_ERASE_SECTOR_SIZE;
/* Address and length should aligned by page/sector */
if (pFmcParam->u32Address & (u32LockSize - 1U))
{
tRetVal = FMC_LOCK_ERROR_INVALID_ADDR;
pFmcParam->u32ErrorAddress = pFmcParam->u32Address;
}
if (pFmcParam->u32Length & (u32LockSize - 1U))
{
tRetVal = FMC_LOCK_ERROR_INVALID_SIZE;
pFmcParam->u32ErrorAddress = pFmcParam->u32Address;
}
if (tRetVal == FMC_LOCK_ERROR_OK)
{
for (u32TempAddr = u32Addr; u32TempAddr < u32Addr + u32Length; u32TempAddr += u32LockSize)
{
if (pFmcParam->bFlash == FMC_PFlash)
{
tRetVal = FMCDRIVER_PFlashLockRegion(pFmcParam->bFMC, u32TempAddr, pFmcParam->bLock);
}
else
{
tRetVal = FMCDRIVER_DFlashLockRegion(pFmcParam->bFMC, u32TempAddr, pFmcParam->bLock);
}
}
}
return tRetVal;
}
/**
* \brief FMC set ota active block
*
* \param eInstance FMC instance
* \param bLock 0U-active block 0, 1U-active block 1
*/
void FMCDRIVER_SwapBlock(const FMC_InstanceType eInstance, FMC_API_ACTIVE_BLOCK_TYPE bActive)
{
FMC_Type *const pFMC = s_apFmcBase[eInstance];
// if (0U == FMC_HWA_GetOTACtrlValue(pFMC, 0))
// {
FMC_HWA_SetOTAActive(pFMC, 0, bActive);
FMC_HWA_SetOTAEnable(pFMC, 0);
// }
}
/**
* \brief Get current active OTA block
*
* \param eInstance FMC instance
* \return Current active block (FMC_Active0 or FMC_Active1)
* Returns FMC_Active0 by default if OTA is not enabled or error
*/
FMC_API_ACTIVE_BLOCK_TYPE FMCDRIVER_GetActiveBlock(const FMC_InstanceType eInstance)
{
FMC_Type *const pFMC = s_apFmcBase[eInstance];
// Validate instance
if ((eInstance >= FMC_INSTANCE_COUNT) || (pFMC == NULL))
{
return FMC_Active0;
}
// Read OTA_CTRL register
uint32_t u32OTACtrl = FMC_HWA_GetOTACtrlValue(pFMC, 0U);
// Check if OTA is enabled (0xA = enabled)
uint32_t u32OTAEn = (u32OTACtrl & FMC_OTA_CTRL_OTA_EN_MASK) >> FMC_OTA_CTRL_OTA_EN_SHIFT;
if (u32OTAEn != 0xA)
{
// OTA not enabled - no swapping configured, return default Bank 0
return FMC_Active0;
}
// OTA is enabled - read which bank is active
uint32_t u32Active = (u32OTACtrl & FMC_OTA_CTRL_OTA_ACTIVE_MASK) >> FMC_OTA_CTRL_OTA_ACTIVE_SHIFT;
return (FMC_API_ACTIVE_BLOCK_TYPE)u32Active;
}