PeripheralDriver_Flagchip_F.../Src/fc7xxx_driver_ptimer.c

327 lines
10 KiB
C

/**
* @file fc7xxx_driver_ptimer.c
* @author Flagchip0126
* @brief FC7xxx PTIMER driver source code
* @version 0.1.0
* @date 2024-01-15
*
* @copyright Copyright (c) 2024 Flagchip Semiconductors Co., Ltd.
*
*/
/* ********************************************************************************
* Revision History:
*
* Version Date Author CR# Descriptions
* --------- ---------- ------------ ---------- ---------------
* 0.1.0 2024-01-15 Flagchip0126 N/A First version for FC7240
******************************************************************************** */
#include <interrupt_manager.h>
#include "fc7xxx_driver_ptimer.h"
#include "fc7xxx_driver_scg.h"
#include "HwA_scm.h"
static PTIMER_Type *const s_apPtimerBase[PTIMER_INSTANCE_COUNT] = PTIMER_BASE_PTRS;
static uint8_t s_u8ChnNum[PTIMER_INSTANCE_COUNT] = {0U};
static PTIMER_InterruptCallbackType s_apPtimerIntNotify[PTIMER_INSTANCE_COUNT] = {NULL};
static PTIMER_SeqErrorCallbackType s_apPtimerSeqErrorNotify[ADC_INSTANCE_COUNT] = {NULL};
/**
* @brief Calculate the delay value base on the delay micro seconds
*
* @param eInstance the Ptimer instance to use
* @param u32DelayUs the delay time in micro seconds
* @return uint16_t the delay time in ptimer clock count
*/
static uint16_t PTIMER_CalcDelayValue(const PTIMER_InstanceType eInstance, const uint32_t u32DelayUs);
/**
* @brief the internal Ptimer interrupt handler
*
* @param eInstance the Ptimer instance to use
*/
static void PTIMERn_IRQHandler(const PTIMER_InstanceType eInstance);
void PTIMER0_IRQHandler(void);
void PTIMER1_IRQHandler(void);
static uint16_t PTIMER_CalcDelayValue(const PTIMER_InstanceType eInstance, const uint32_t u32DelayUs)
{
DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT);
const PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance];
uint32_t u32DelayVal;
uint32_t u32SysFreq;
uint32_t u32PtimerFreqUs = 0U;
PTIMER_ClockPreDividerType ePreDivider = PTIMER_HWA_GetDivPrescaler(pPtimer);
PTIMER_ClockPreDivMultiplyFactorType ePreDivMultFactor = PTIMER_HWA_GetDivMultiply(pPtimer);
uint8_t u8Prescaler = (1U << ePreDivider);
uint8_t u8PrescalerMult = 1U;
switch (ePreDivMultFactor)
{
case PTIMER_PRE_DIVIDER_MULTIPLY_BY_1:
u8PrescalerMult = 1U;
break;
case PTIMER_PRE_DIVIDER_MULTIPLY_BY_10:
u8PrescalerMult = 10U;
break;
case PTIMER_PRE_DIVIDER_MULTIPLY_BY_20:
u8PrescalerMult = 20U;
break;
case PTIMER_PRE_DIVIDER_MULTIPLY_BY_40:
u8PrescalerMult = 40U;
break;
default:
u8PrescalerMult = 1U;
break;
}
u32SysFreq = SCG_GetScgClockFreq(SCG_CORE_CLK);
u32PtimerFreqUs = u32SysFreq / 1000000U;
u32DelayVal = (u32DelayUs * u32PtimerFreqUs) / ((uint32_t)u8Prescaler * u8PrescalerMult);
DEV_ASSERT(u32DelayVal < (1U << 16U));
return (uint16_t)u32DelayVal;
}
void PTIMER0_IRQHandler(void)
{
PTIMERn_IRQHandler(PTIMER_INSTANCE_0);
}
void PTIMER1_IRQHandler(void)
{
PTIMERn_IRQHandler(PTIMER_INSTANCE_1);
}
static void PTIMERn_IRQHandler(const PTIMER_InstanceType eInstance)
{
PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance];
uint8_t u8Channel;
if (PTIMER_HWA_GetInterruptFlag(pPtimer) == true)
{
PTIMER_HWA_ClearInterruptFlag(pPtimer);
if (s_apPtimerIntNotify[eInstance] != NULL)
{
s_apPtimerIntNotify[eInstance]();
}
}
for (u8Channel = 0U; u8Channel < s_u8ChnNum[eInstance]; u8Channel++)
{
if (PTIMER_HWA_GetChannelSequenceErrorFlag(pPtimer, u8Channel) == true)
{
PTIMER_HWA_ClearChannelSequenceErrorFlag(pPtimer, u8Channel);
if (s_apPtimerSeqErrorNotify[eInstance] != NULL)
{
s_apPtimerSeqErrorNotify[eInstance](u8Channel);
}
}
}
}
void PTIMER_DeInit(const PTIMER_InstanceType eInstance)
{
DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT);
PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance];
uint8_t u8Chn;
/* Reset PTIMER Status Ctrl Register */
PTIMER_HWA_SetStatusCtrl(pPtimer, 0U);
/* Enable PTIMER */
PTIMER_HWA_Enable(pPtimer);
/* Reset PTIMER Max Cnt Register */
PTIMER_HWA_SetMaxCount(pPtimer, 0xFFFFU);
/* Reset PTIMER Int Dly Register */
PTIMER_HWA_SetInterruptDelay(pPtimer, 0xFFFFU);
for (u8Chn = 0U; u8Chn < PTIMER_DLY_CNT; u8Chn++)
{
PTIMER_HWA_SetChannelControl(pPtimer, u8Chn, false, false, false);
PTIMER_HWA_ClearChannelCounterFlag(pPtimer, u8Chn);
PTIMER_HWA_ClearChannelSequenceErrorFlag(pPtimer, u8Chn);
PTIMER_HWA_SetChannelDelay(pPtimer, u8Chn, 0U);
}
/* For Pulse out trigger. */
PTIMER_HWA_DisablePulseOut(pPtimer);
PTIMER_HWA_SetPulseOutDelay(pPtimer, 0U, 0U);
PTIMER_HWA_LoadValue(pPtimer);
PTIMER_HWA_Disable(pPtimer);
}
void PTIMER_Init(const PTIMER_InstanceType eInstance, const PTIMER_InitType *const pInitCfg)
{
DEV_ASSERT(pInitCfg != NULL_PTR);
DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT);
PTIMER_Type *const pPtimer = s_apPtimerBase[(uint8_t)eInstance];
PTIMER_DeInit(eInstance);
PTIMER_HWA_SetLoadMode(pPtimer, pInitCfg->eLoadValueMode);
PTIMER_HWA_SetDivPrescaler(pPtimer, pInitCfg->eClkPreDiv);
PTIMER_HWA_SetTriggerSource(pPtimer, pInitCfg->eTriggerInput);
PTIMER_HWA_SetDivMultiply(pPtimer, pInitCfg->eClkPreMultFactor);
PTIMER_HWA_SetContinuoiusModeFlag(pPtimer, pInitCfg->bContinuousModeEnable);
PTIMER_HWA_SetDMAEnableFlag(pPtimer, pInitCfg->bDmaEnable);
}
void PTIMER_InitChannel(const PTIMER_InstanceType eInstance,
const PTIMER_ChannelCfgType aChannelCfg[], const uint8_t u8ChnNum)
{
DEV_ASSERT(aChannelCfg != NULL_PTR);
DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT);
DEV_ASSERT(u8ChnNum <= PTIMER_DLY_CNT);
PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance];
uint8_t u8ChnIdx;
uint16_t u16PtimerChannelDelay ;
for (u8ChnIdx = 0U; u8ChnIdx < u8ChnNum; u8ChnIdx++)
{
PTIMER_HWA_SetChannelControl(pPtimer, u8ChnIdx, aChannelCfg[u8ChnIdx].bPreTriggerEnable,
aChannelCfg[u8ChnIdx].bPreTriggerOutputEnable, aChannelCfg[u8ChnIdx].bPreTriggerBackToBackEnable);
u16PtimerChannelDelay = PTIMER_CalcDelayValue(eInstance, aChannelCfg[u8ChnIdx].u32DelayUs);
PTIMER_HWA_SetChannelDelay(pPtimer, u8ChnIdx, u16PtimerChannelDelay);
}
s_u8ChnNum[eInstance] = u8ChnNum;
}
void PTIMER_InitInterrupt(const PTIMER_InstanceType eInstance,
const PTIMER_InterruptType *const pInterruptCfg)
{
DEV_ASSERT(pInterruptCfg != NULL_PTR);
DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT);
PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance];
PTIMER_HWA_SetSeqErrIntEnableFlag(pPtimer, pInterruptCfg->bSeqErrIntEnable);
uint16_t u16IntDelay = PTIMER_CalcDelayValue(eInstance, pInterruptCfg->u32IntDelayPeriodUs);
PTIMER_HWA_SetInterruptDelay(pPtimer, u16IntDelay);
PTIMER_HWA_SetInterruptEnableFlag(pPtimer, pInterruptCfg->bDelayIntEnable);
if (pInterruptCfg->bDelayIntEnable)
{
s_apPtimerIntNotify[eInstance] = pInterruptCfg->pIntNotify;
}
else
{
s_apPtimerIntNotify[eInstance] = NULL;
}
if (pInterruptCfg->bSeqErrIntEnable)
{
s_apPtimerSeqErrorNotify[eInstance] = pInterruptCfg->pSeqErrorNotify;
}
else
{
s_apPtimerSeqErrorNotify[eInstance] = NULL;
}
if ((pInterruptCfg->bSeqErrIntEnable == true) || (pInterruptCfg->bDelayIntEnable == true))
{
switch ((uint8_t)eInstance)
{
case (uint8_t)PTIMER_INSTANCE_0:
IntMgr_EnableInterrupt(PTIMER0_IRQn);
break;
case (uint8_t)PTIMER_INSTANCE_1:
IntMgr_EnableInterrupt(PTIMER1_IRQn);
break;
default:
break;
}
}
}
void PTIMER_SetPeriod(const PTIMER_InstanceType eInstance, uint32_t u32PeriodUs)
{
DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT);
PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance];
uint16_t u16MaxCnt = PTIMER_CalcDelayValue(eInstance, u32PeriodUs);
PTIMER_HWA_SetMaxCount(pPtimer, u16MaxCnt);
}
void PTIMER_SetPulseOut(const PTIMER_InstanceType eInstance, const PTIMER_PulseOutType *pPulseOutCfg)
{
DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT);
DEV_ASSERT(pPulseOutCfg != NULL_PTR);
PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance];
uint16_t u16PulseOutCfgDlyHigh = PTIMER_CalcDelayValue(eInstance, pPulseOutCfg->u32PulseOutDlyHighUs);
uint16_t u16PulseOutCfgDlyLow = PTIMER_CalcDelayValue(eInstance, pPulseOutCfg->u32PulseOutDlyLowUs);
PTIMER_HWA_SetPulseOutDelay(pPtimer, u16PulseOutCfgDlyHigh, u16PulseOutCfgDlyLow);
}
void PTIMER_LoadValue(const PTIMER_InstanceType eInstance)
{
DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT);
PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance];
PTIMER_HWA_LoadValue(pPtimer);
}
void PTIMER_Enable(const PTIMER_InstanceType eInstance)
{
DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT);
PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance];
PTIMER_HWA_Enable(pPtimer);
}
void PTIMER_Disable(const PTIMER_InstanceType eInstance)
{
DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT);
PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance];
PTIMER_HWA_Disable(pPtimer);
}
void PTIMER_EnablePulseOut(const PTIMER_InstanceType eInstance)
{
DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT);
PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance];
PTIMER_HWA_EnablePulseOut(pPtimer);
}
void PTIMER_DisablePulseOut(const PTIMER_InstanceType eInstance)
{
DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT);
PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance];
PTIMER_HWA_DisablePulseOut(pPtimer);
}
void PTIMER_SelectInstance01BackToBackMode(SCM_PTimerLMSelType ePTimerLoopMode)
{
SCM_HWA_PTimerLoopModeSel(ePTimerLoopMode);
}
void PTIMER_GenerateSWTrigger(const PTIMER_InstanceType eInstance)
{
DEV_ASSERT((uint8_t)eInstance < PTIMER_INSTANCE_COUNT);
PTIMER_Type *const pPtimer = s_apPtimerBase[eInstance];
PTIMER_HWA_GenerateSwTrigger(pPtimer);
}