PeripheralDriver_Flagchip_F.../Src/module_driver_eftu_cmu.c

274 lines
8.2 KiB
C

#include "module_driver_eftu_cmu.h"
#if defined(EFTU_INSTANCE_COUNT) && (EFTU_INSTANCE_COUNT > 0)
static EFTU_CMU_Type *const s_pEftuCmuBasePtrs[EFTU_CMU_INSTANCE_COUNT] =
{
(EFTU_CMU_Type *)(EFTU0_BASE + EFTU_CMU_BASE),
};
#ifndef CMU_DEV_ERROR_REPORT
#define CMU_DEV_ERROR_REPORT STD_OFF
#endif
#if CMU_DEV_ERROR_REPORT == STD_ON
#define CMU_ReportDevError(func, error) ReportDevError(EFTU_CMU_MODULE_ID, func, error)
#endif
/**
* @brief Cmu Global clock configuration.
* @param pCmuHandle EFTU CMU processing handle
*/
void EFTU_CMU_Init(EFTU_CMU_HandleType *pCmuHandle)
{
#if CMU_DEV_ERROR_REPORT == STD_ON
if (((uint32_t)pCmuHandle->freqBusClock == 0U) || ((uint32_t)pCmuHandle->freqGlobalClock == 0U))
{
CMU_ReportDevError(EFTU_CMU_INIT_ID, EFTU_CMU_E_PARAM_COUNT);
}
else
#endif
{
/*
* freqGlobalClock = DEN/NUM *freqBusClock;
* */
EFTU_CMU_Type *pCmu = s_pEftuCmuBasePtrs[0];
float fTempFreq;
float freqBusClock = pCmuHandle->fBusClock;
float freqGlobalClock = pCmuHandle->fGlobalClock;
float fDistance = pCmuHandle->fGlobalClock;;
uint8_t u8Num, u8Den, u8DenBest = 1, u8NumBest = 1;
float fTempBusDivider;
for (u8Num = 1; u8Num < 0xFF; u8Num++)
{
boolean endLoop = FALSE;
fTempBusDivider = freqBusClock / u8Num;
for (u8Den = u8Num; u8Den > 0; u8Den--)
{
float dis;
fTempFreq = fTempBusDivider * u8Den;
dis = (float)fabsf(freqGlobalClock - fTempFreq);
if (dis < fDistance)
{
fDistance = dis;
u8DenBest = u8Den;
u8NumBest = u8Num;
}
if (fDistance < 0.1f)
{
endLoop = TRUE;
break;
}
}
if (endLoop)
{
break;
}
}
EFTU_CMU_HWA_SetGclkNum(pCmu, u8NumBest);
EFTU_CMU_HWA_SetGclkDen(pCmu, u8DenBest);
pCmuHandle->tStatus.pCmu = pCmu;
}
}
/**
* @brief Cmu external clock configuration.
* @param pCmuHandle EFTU CMU processing handle
* @param eEclk Cmu external clock Index
* @param fFrequence Cmu external clock frequency
*/
void EFTU_CMU_SetEClock(EFTU_CMU_HandleType *pCmuHandle, EFTU_CMU_ClkSrcType eEclk, float fFrequence)
{
#if CMU_DEV_ERROR_REPORT == STD_ON
if (((uint32_t)pCmuHandle->freqBusClock == 0U) || ((uint32_t)pCmuHandle->freqGlobalClock == 0U) || ((uint32_t)fFrequence == 0U))
{
CMU_ReportDevError(EFTU_CMU_SET_ECLK_ID, EFTU_CMU_E_PARAM_COUNT);
}
else if (pCmuHandle->tStatus.pCmu == NULL)
{
CMU_ReportDevError(EFTU_CMU_SET_ECLK_ID, EFTU_CMU_UNINIT);
}
else if ((eEclk != EFTU_ECLK_0) && (eEclk != EFTU_ECLK_1))
{
CMU_ReportDevError(EFTU_CMU_SET_ECLK_ID, EFTU_CMU_E_PARAM_CHANNEL);
}
else
#endif
{
/*
* freqEClock = DEN/NUM *freqGlobalClock;
* */
EFTU_CMU_Type *pCmu = s_pEftuCmuBasePtrs[0];
float fTempfreq;
float freqInClock = pCmuHandle->fBusClock;
float bDis = fFrequence;
uint8_t u8Num, u8Den, u8DenBest = 1, u8NumBest = 1;
float fTempGlobalDivider;
for (u8Num = 1; u8Num < 0xFF; u8Num++)
{
boolean endLoop = FALSE;
fTempGlobalDivider = freqInClock / u8Num;
for (u8Den = u8Num; u8Den > 0; u8Den--)
{
float dis;
fTempfreq = fTempGlobalDivider * u8Den;
dis = (float)fabsf(fFrequence - fTempfreq);
if (dis < bDis)
{
bDis = dis;
u8DenBest = u8Den;
u8NumBest = u8Num;
}
if (bDis < 0.1f)
{
endLoop = TRUE;
break;
}
}
if (endLoop)
{
break;
}
}
if (EFTU_ECLK_0 == eEclk)
{
EFTU_CMU_HWA_SetEclk0Num(pCmu, u8NumBest);
EFTU_CMU_HWA_SetEclk0Den(pCmu, u8DenBest);
}
else /*EFTU_ECLK_1*/
{
EFTU_CMU_HWA_SetEclk1Num(pCmu, u8NumBest);
EFTU_CMU_HWA_SetEclk1Den(pCmu, u8DenBest);
}
pCmuHandle->tStatus.afExternalClock[eEclk-EFTU_ECLK_0] = fFrequence;
}
}
/**
* @brief Cmu clock configuration.
* @param pCmuHandle EFTU CMU processing handle
* @param eClk Cmu clock Index
* @param eClockSource Cmu clock source
* @param fFrequence Cmu clock frequency
*/
void EFTU_CMU_SetCmuClock(EFTU_CMU_HandleType *pCmuHandle, EFTU_CMU_ClkSrcType eClk, EFTU_CMU_ClkCtrlSrcType eClockSource, float fFrequence)
{
#if CMU_DEV_ERROR_REPORT == STD_ON
if (((uint32_t)pCmuHandle->freqBusClock == 0U) || ((uint32_t)pCmuHandle->freqGlobalClock == 0U) || ((uint32_t)fFrequence == 0U))
{
CMU_ReportDevError(EFTU_CMU_SET_CMUCLK_ID, EFTU_CMU_E_PARAM_COUNT);
}
else if (pCmuHandle->tStatus.pCmu == NULL)
{
CMU_ReportDevError(EFTU_CMU_SET_CMUCLK_ID, EFTU_CMU_UNINIT);
}
else if (eEclk > EFTU_CMU_CLK_7)
{
CMU_ReportDevError(EFTU_CMU_SET_CMUCLK_ID, EFTU_CMU_E_PARAM_CHANNEL);
}
else
#endif
{
float ftempDivider;
if (eClockSource == CMU_GCLK_EN)
{
ftempDivider = pCmuHandle->fGlobalClock / fFrequence - 1 ;
}
else /*CMU_ECLK1_EN*/
{
ftempDivider = pCmuHandle->tStatus.afExternalClock[1] / fFrequence - 1 ;
}
uint32 cnt = (uint32)ftempDivider;
if ((ftempDivider - (float)cnt) > 0.5f)
{
/* Round to nearest */
cnt++;
}
EFTU_CMU_HWA_SetCmuclkCnt(pCmuHandle->tStatus.pCmu, cnt, eClk);
if (eClockSource == CMU_GCLK_EN)
{
for(uint8 u8Instance = 0u ; u8Instance< EFTU_INSTANCE_COUNT ;u8Instance++)
{
pCmuHandle->tStatus.fCmuClock[u8Instance][eClk] = pCmuHandle->fGlobalClock /(((float)cnt+1));
}
}
else/*CMU_ECLK1_EN*/
{
for(uint8 u8Instance = 0u ; u8Instance< EFTU_INSTANCE_COUNT ;u8Instance++)
{
pCmuHandle->tStatus.fCmuClock[u8Instance][eClk] = pCmuHandle->tStatus.afExternalClock[1]/(((float)cnt+1));
}
}
EFTU_CMU_HWA_SetCmuClkSrc(pCmuHandle->tStatus.pCmu,eClk,eClockSource);
}
}
/**
* @brief Cmu clock 8 configuration.
* @param pCmuHandle EFTU CMU processing handle
* @param eCmu8ClockSrc Cmu clock 8 source
*/
void EFTU_CMU_SetCmuClk8Src(EFTU_CMU_HandleType *pCmuHandle, EFTU_CMU_Clk8CtrlSrcType eCmu8ClockSrc)
{
#if CMU_DEV_ERROR_REPORT == STD_ON
if (pCmuHandle->tStatus.pCmu == NULL)
{
CMU_ReportDevError(EFTU_CMU_SET_CLK8_ID, EFTU_CMU_UNINIT);
}
else
#endif
{
if (eCmu8ClockSrc == CLUSTER_RES_CONST_1)
{
pCmuHandle->tStatus.fClock8 = pCmuHandle->fBusClock;
}
else
{
pCmuHandle->tStatus.fClock8 = pCmuHandle->tStatus.afExternalClock[0];
}
EFTU_CMU_HWA_SetCmuClk8Src(pCmuHandle->tStatus.pCmu, eCmu8ClockSrc);
}
}
/**
* @brief Enable Cmu clock
* @param pCmuHandle EFTU CMU processing handle
* @param eChannel Clock Index
*/
void EFTU_CMU_EnableClock(EFTU_CMU_HandleType *pCmuHandle, EFTU_CMU_ClkSrcType eChannel)
{
#if CMU_DEV_ERROR_REPORT == STD_ON
if (pCmuHandle->tStatus.pCmu == NULL)
{
CMU_ReportDevError(EFTU_CMU_ENABLE_CLK_ID, EFTU_CMU_UNINIT);
}
else
#endif
{
EFTU_CMU_HWA_EnableClock(pCmuHandle->tStatus.pCmu, eChannel);
}
}
/**
* @brief Disable Cmu clock
* @param pCmuHandle EFTU CMU processing handle
* @param eChannel Clock Index
*/
void EFTU_CMU_DisableClock(EFTU_CMU_HandleType *pCmuHandle, EFTU_CMU_ClkSrcType eChannel)
{
#if CMU_DEV_ERROR_REPORT == STD_ON
if (pCmuHandle->tStatus.pCmu == NULL)
{
CMU_ReportDevError(EFTU_CMU_ENABLE_CLK_ID, EFTU_CMU_UNINIT);
}
else
#endif
{
EFTU_CMU_HWA_DisableClock(pCmuHandle->tStatus.pCmu, eChannel);
}
}
#endif /* defined(EFTU_INSTANCE_COUNT) && (EFTU_INSTANCE_COUNT > 0) */