274 lines
8.2 KiB
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) */
|