PeripheralDriver_Flagchip_F.../Src/module_driver_tmu.c

533 lines
16 KiB
C

/**
* @file module_driver_tmu.c
* @author Flagchip
* @brief TMU driver source code
* @version 2.0.0
* @date 2024-08-20
*
* SDK Version: 2.6.0
*
* @copyright Copyright (c) 2020-2024 Flagchip Semiconductors Co., Ltd.
*
* @details
*/
/*********************************************************************************
* Revision History:
*
* Version Date Initials CR# Descriptions
* --------- ---------- ------------ ---------- ---------------
* 0.1.0 2022-12-30 Flagchip074 N/A First version for FC7xxx
* 0.2.0 2023-02-15 Flagchip074 N/A FC7xxx release version
******************************************************************************** */
#include "module_driver_tmu.h"
#if TMU_INSTANCE_COUNT > 0U
#if TMU_SUPPORT_TV_ECMP
#include "module_driver_adc.h"
#endif
#include "module_driver_pcc.h"
#ifndef TMU_DEV_ERROR_REPORT
#define TMU_DEV_ERROR_REPORT STD_OFF
#endif
#if TMU_DEV_ERROR_REPORT == STD_ON
#define TMU_ReportDevError(func, error) ReportDevError(TMU_MODULE_ID, func, error)
#endif
/********* Local Variables ************/
/** @brief TMU peripheral base pointers */
static TMU_Type *const s_apTmuBase[TMU_INSTANCE_COUNT] = TMU_BASE_PTRS;
#if TMU_SUPPORT_TV_ECMP
static ADC_Type *const s_apTmuAdcUsedBase[ADC_INSTANCE_COUNT] = ADC_BASE_PTRS;
#endif
/**
* @brief TMU interrupt process
*
*/
void TMU_ProcessIRQHandler(TMU_HandleType* pTmuHandle)
{
TMU_Type *const pTmu = s_apTmuBase[pTmuHandle->eIntance];
#if TMU_SUPPORT_TV_ECMP
ADC_Type *const pAdc = s_apTmuAdcUsedBase[pTmuHandle->u8AdcIntanceUsed];
if (TMU_HWA_GetVoltageTemperatureCompare1InterruptEnableStatus(pTmu) == true)
{
if (TMU_HWA_GetVoltageTemperatureCompareFlag1(pTmu) == true)
{
ADC_HWA_ClearECMPHighFlag(pAdc, ADC_ECMP1);
ADC_HWA_ClearECMPLowFlag(pAdc, ADC_ECMP1);
ADC_HWA_ClearECMPWinFlag(pAdc, ADC_ECMP1);
TMU_HWA_ClearVoltageTemperatureCompareFlag1(pTmu);
if (pTmuHandle->tSettings.TMU_TempCompareFlag1InterruptCallback != NULL)
{
pTmuHandle->tSettings.TMU_TempCompareFlag1InterruptCallback(pTmuHandle);
}
}
}
if (TMU_HWA_GetVoltageTemperatureCompare0InterruptEnableStatus(pTmu) == true)
{
if (TMU_HWA_GetVoltageTemperatureCompareFlag0(pTmu) == true)
{
ADC_HWA_ClearECMPHighFlag(pAdc, ADC_ECMP0);
ADC_HWA_ClearECMPLowFlag(pAdc, ADC_ECMP0);
ADC_HWA_ClearECMPWinFlag(pAdc, ADC_ECMP0);
TMU_HWA_ClearVoltageTemperatureCompareFlag0(pTmu);
if (pTmuHandle->tSettings.TMU_TempCompareFlag0InterruptCallback != NULL)
{
pTmuHandle->tSettings.TMU_TempCompareFlag0InterruptCallback(pTmuHandle);
}
}
}
#else
if (TMU_HWA_GetFlagTemperature150InterruptFlag(pTmu) == true)
{
if (TMU_HWA_Get150Flag(pTmu) == true)
{
if (pTmuHandle->tSettings.TMU_TempOver150InterruptCallback != NULL)
{
pTmuHandle->tSettings.TMU_TempOver150InterruptCallback(pTmuHandle);
}
TMU_HWA_Clear150Flag(pTmu);
}
}
if (TMU_HWA_GetFlagTemperature125InterruptFlag(pTmu) == true)
{
if (TMU_HWA_Get125Flag(pTmu) == true)
{
if (pTmuHandle->tSettings.TMU_TempOver125InterruptCallback != NULL)
{
pTmuHandle->tSettings.TMU_TempOver125InterruptCallback(pTmuHandle);
}
TMU_HWA_Clear125Flag(pTmu);
}
}
if (TMU_HWA_GetFlagTemperatureReadyInterruptFlag(pTmu) == true)
{
if (TMU_HWA_GetFlagTemperatureReady(pTmu) == true)
{
if (pTmuHandle->tSettings.TMU_TempFlagReadyInterruptCallback != NULL)
{
pTmuHandle->tSettings.TMU_TempFlagReadyInterruptCallback(pTmuHandle);
}
TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_UNLOCK);
TMU_HWA_ClearFlagTemperatureReady(pTmu);
TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK);
}
}
if (TMU_HWA_GetVoltageTemperatureReadyInterruptFlag(pTmu) == true)
{
if (TMU_HWA_GetVoltageTemperatureReady(pTmu) == true)
{
if (pTmuHandle->tSettings.TMU_TempVoltageReadyInterruptCallback != NULL)
{
pTmuHandle->tSettings.TMU_TempVoltageReadyInterruptCallback(pTmuHandle);
}
TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_UNLOCK);
TMU_HWA_ClearVoltageTemperatureReady(pTmu);
TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK);
}
}
#endif
}
/**
* @brief Initialize the TMU instance
*
* @param pTmuHandle: TMU processing handle
* @param pInitCfg: the configurations of the TMU instance
*/
void TMU_Init(TMU_HandleType* pTmuHandle, const TMU_InitType *const pInitCfg)
{
#if TMU_DEV_ERROR_REPORT == STD_ON
if((pTmuHandle == NULL) || (pInitCfg == NULL))
{
TMU_ReportDevError(TMU_INIT_ID, TMU_E_PARAM_POINTER);
}
else if(pTmuHandle->eIntance >= TMU_INSTANCE_MAX)
{
TMU_ReportDevError(TMU_INIT_ID, TMU_E_PARAM_INSTANCE);
}
else
{
#endif
TMU_Type *const pTmu = s_apTmuBase[pTmuHandle->eIntance];
#if !TMU_SUPPORT_TV_ECMP
uint32_t u32FlagCtrl;
uint32_t u32VoltageCtrl;
uint8_t u8FlagStartupCnt;
uint8_t u8VoltageStartupCnt;
PCC_ClkSrcType eAdcClkName = PCC_CLK_TMU0;
uint32_t u32TmuClk;
u32TmuClk = PCC_GetPccFunctionClock(eAdcClkName);
u8FlagStartupCnt = (uint8_t)((u32TmuClk * 11U) / 127000000U + 1U);
u8VoltageStartupCnt = (uint8_t)((u32TmuClk * 5U) / 127000000U + 1U);
if (u8FlagStartupCnt > 15U)
{
u8FlagStartupCnt = 15U;
}
if (u8VoltageStartupCnt > 7U)
{
u8VoltageStartupCnt = 7U;
}
pTmuHandle->tStatus.bTemperatureOver125IntEn = pInitCfg->bTemperatureOver125IntEn;
pTmuHandle->tStatus.bTemperatureOver150IntEn = pInitCfg->bTemperatureOver150IntEn;
pTmuHandle->tStatus.bFlagTempReadyIntEn = pInitCfg->bFlagTempReadyIntEn;
pTmuHandle->tStatus.bVoltageTempReadyIntEn = pInitCfg->bVoltageTempReadyIntEn;
u32FlagCtrl = TMU_TF_CTRL_TF_HYSOFF(pInitCfg->eFlagTempHysteresisCon) |
TMU_TF_CTRL_TF_START_CNT(u8FlagStartupCnt) |
#ifdef TMU_SUPPORT_STOP
TMU_TF_CTRL_TF_STOP_EN(pInitCfg->bFlagTempStopModeEn) |
#endif
TMU_TF_CTRL_TF_FILT_BYP(pInitCfg->eFlagTempFilterBypassCon);
TMU_HWA_SetFlagTempCtrl(pTmu, u32FlagCtrl);
u32VoltageCtrl = TMU_TV_CTRL_TV_START_CNT(u8VoltageStartupCnt);
#else
uint32_t u32VoltageCtrl = 0U;
pTmuHandle->tStatus.bVoltageTempCompareFlag1IntEn = pInitCfg->bVoltageTempCompareFlag1IntEn;
pTmuHandle->tStatus.bVoltageTempCompareFlag0IntEn = pInitCfg->bVoltageTempCompareFlag0IntEn;
#endif
#ifdef TMU_SUPPORT_STOP
u32VoltageCtrl |= TMU_TV_CTRL_TV_STOP_EN(pInitCfg->bVoltageTempStopModeEn);
#endif
TMU_HWA_SetVoltageTempCtrl(pTmu, u32VoltageCtrl);
TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK);
#if TMU_DEV_ERROR_REPORT == STD_ON
}
#endif
}
#if !TMU_SUPPORT_TV_ECMP
/**
* @brief Enable the Flag-based temperature sensor
*
* @param pTmuHandle: TMU processing handle
* @return TMU_StatusType TMU_STATUS_SUCCESS when enable successfully, others fail
*/
TMU_StatusType TMU_FlagTempEnable(TMU_HandleType* pTmuHandle)
{
TMU_StatusType eRet = TMU_STATUS_ERROR;
#if TMU_DEV_ERROR_REPORT == STD_ON
if(pTmuHandle->eIntance >= TMU_INSTANCE_MAX)
{
TMU_ReportDevError(TMU_INIT_ID, TMU_E_PARAM_INSTANCE);
}
else
{
#endif
uint32_t u32TimeOut = 15000000U;
TMU_Type *const pTmu = s_apTmuBase[pTmuHandle->eIntance];
TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_UNLOCK);
TMU_HWA_SetFlagTemperature150InterruptFlag(pTmu, pTmuHandle->tStatus.bTemperatureOver150IntEn);
TMU_HWA_SetFlagTemperature125InterruptFlag(pTmu, pTmuHandle->tStatus.bTemperatureOver125IntEn);
TMU_HWA_SetFlagTemperatureEnableStatus(pTmu, true);
while ((TMU_HWA_GetFlagTemperatureReady(pTmu) != true) && (u32TimeOut != 0U))
{
u32TimeOut--;
}
if (u32TimeOut != 0U)
{
TMU_HWA_SetFlagTemperatureReadyInterruptFlag(pTmu, pTmuHandle->tStatus.bFlagTempReadyIntEn);
eRet = TMU_STATUS_SUCCESS;
}
else
{
eRet = TMU_STATUS_TIMEOUT;
}
TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK);
#if TMU_DEV_ERROR_REPORT == STD_ON
}
#endif
return eRet;
}
/**
* @brief Disable the Flag-based temperature sensor
*
* @param pTmuHandle: TMU processing handle
* @return TMU_StatusType TMU_STATUS_SUCCESS when disable successfully, others fail
*/
TMU_StatusType TMU_FlagTempDisable(TMU_HandleType* pTmuHandle)
{
TMU_StatusType eRet = TMU_STATUS_ERROR;
#if TMU_DEV_ERROR_REPORT == STD_ON
if(pTmuHandle->eIntance >= TMU_INSTANCE_MAX)
{
TMU_ReportDevError(TMU_INIT_ID, TMU_E_PARAM_INSTANCE);
}
else
{
#endif
uint32_t u32TimeOut = 15000000U;
TMU_Type *const pTmu = s_apTmuBase[pTmuHandle->eIntance];
TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_UNLOCK);
/* Before clearing the flag-enable bit, the bit TF_RDYF_IE, TF_150F_IE, and TF_125F_IE must be cleared first. */
TMU_HWA_SetFlagTemperature150InterruptFlag(pTmu, false);
TMU_HWA_SetFlagTemperature125InterruptFlag(pTmu, false);
TMU_HWA_SetFlagTemperatureReadyInterruptFlag(pTmu, false);
TMU_HWA_SetFlagTemperatureEnableStatus(pTmu, false);
TMU_HWA_ClearFlagTemperatureReady(pTmu);
while ((TMU_HWA_GetFlagTemperatureEnableStatus(pTmu) == true) && (u32TimeOut != 0U))
{
u32TimeOut--;
}
if (u32TimeOut != 0U)
{
eRet = TMU_STATUS_SUCCESS;
}
else
{
eRet = TMU_STATUS_TIMEOUT;
}
TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK);
#if TMU_DEV_ERROR_REPORT == STD_ON
}
#endif
return eRet;
}
#endif
/**
* @brief Enable the Voltage-based temperature sensor
*
* @param pTmuHandle: TMU processing handle
* @return TMU_StatusType TMU_STATUS_SUCCESS when enable successfully, others fail
*/
TMU_StatusType TMU_VoltageTempEnable(TMU_HandleType* pTmuHandle)
{
TMU_StatusType eRet = TMU_STATUS_ERROR;
#if TMU_DEV_ERROR_REPORT == STD_ON
if(pTmuHandle->eIntance >= TMU_INSTANCE_MAX)
{
TMU_ReportDevError(TMU_INIT_ID, TMU_E_PARAM_INSTANCE);
}
else
{
#endif
uint32_t u32TimeOut = 15000000U;
TMU_Type *const pTmu = s_apTmuBase[pTmuHandle->eIntance];
TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_UNLOCK);
TMU_HWA_SetVoltageTemperatureEnableStatus(pTmu, true);
while ((TMU_HWA_GetVoltageTemperatureReady(pTmu) != true) && (u32TimeOut != 0U))
{
u32TimeOut--;
}
if (u32TimeOut != 0U)
{
#if !TMU_SUPPORT_TV_ECMP
TMU_HWA_SetVoltageTemperatureReadyInterruptFlag(pTmu, pTmuHandle->tStatus.bVoltageTempReadyIntEn);
#endif
eRet = TMU_STATUS_SUCCESS;
}
else
{
eRet = TMU_STATUS_TIMEOUT;
}
TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK);
#if TMU_DEV_ERROR_REPORT == STD_ON
}
#endif
return eRet;
}
/**
* @brief Disable the Voltage-based temperature sensor
*
* @param pTmuHandle: TMU processing handle
* @return TMU_StatusType TMU_STATUS_SUCCESS when disable successfully, others fail
*/
TMU_StatusType TMU_VoltageTempDisable(TMU_HandleType* pTmuHandle)
{
TMU_StatusType eRet = TMU_STATUS_ERROR;
#if TMU_DEV_ERROR_REPORT == STD_ON
if(pTmuHandle->eIntance >= TMU_INSTANCE_MAX)
{
TMU_ReportDevError(TMU_INIT_ID, TMU_E_PARAM_INSTANCE);
}
else
{
#endif
uint32_t u32TimeOut = 15000000U;
TMU_Type *const pTmu = s_apTmuBase[pTmuHandle->eIntance];
TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_UNLOCK);
#if !TMU_SUPPORT_TV_ECMP
/* Before clearing the Voltage-enable bit, the bit TV_RDYF_IE must be cleared first. */
TMU_HWA_SetVoltageTemperatureReadyInterruptFlag(pTmu, false);
#endif
TMU_HWA_SetVoltageTemperatureEnableStatus(pTmu, false);
#if !TMU_SUPPORT_TV_ECMP
TMU_HWA_ClearVoltageTemperatureReady(pTmu);
#endif
while ((TMU_HWA_GetVoltageTemperatureEnableStatus(pTmu) == true) && (u32TimeOut != 0U))
{
u32TimeOut--;
}
if (u32TimeOut != 0U)
{
eRet = TMU_STATUS_SUCCESS;
}
else
{
eRet = TMU_STATUS_TIMEOUT;
}
TMU_HWA_SetTemperatureLockStatus(pTmu, TMU_TF_TV_LOCK);
#if TMU_DEV_ERROR_REPORT == STD_ON
}
#endif
return eRet;
}
#if !TMU_SUPPORT_TV_ECMP
/**
* @brief Check if cleaning flag is required
*
* @param pTmuHandle: TMU processing handle
*/
void TMU_TempOverClear(TMU_HandleType* pTmuHandle)
{
#if TMU_DEV_ERROR_REPORT == STD_ON
if(pTmuHandle->eIntance >= TMU_INSTANCE_MAX)
{
TMU_ReportDevError(TMU_INIT_ID, TMU_E_PARAM_INSTANCE);
}
else
{
#endif
TMU_Type *const pTmu = s_apTmuBase[pTmuHandle->eIntance];
if (TMU_HWA_Get150Flag(pTmu))
{
if (!TMU_HWA_Get150Status(pTmu))
{
TMU_HWA_Clear150Flag(pTmu);
}
}
if (TMU_HWA_Get125Flag(pTmu))
{
if (!TMU_HWA_Get125Status(pTmu))
{
TMU_HWA_Clear125Flag(pTmu);
}
}
#if TMU_DEV_ERROR_REPORT == STD_ON
}
#endif
}
#endif
#ifdef TMU_SUPPORT_STOP
#if !TMU_SUPPORT_TV_ECMP
/**
* @brief Set the Flag-based temperature sensor is enabled/disabled in stop mode
*
*@param pTmuHandle: TMU processing handle
* @param bEnable: whether Flag-based temperature sensor is enabled in stop mode if TF_EN is active.
*/
void TMU_FlagTempSetStopMode(TMU_HandleType* pTmuHandle, bool bEnable)
{
#if TMU_DEV_ERROR_REPORT == STD_ON
if(pTmuHandle->eIntance >= TMU_INSTANCE_MAX)
{
TMU_ReportDevError(TMU_INIT_ID, TMU_E_PARAM_INSTANCE);
}
else
{
#endif
TMU_Type *const pTmu = s_apTmuBase[pTmuHandle->eIntance];
TMU_HWA_ConfigFlagTemperatureStopMode(pTmu, bEnable);
#if TMU_DEV_ERROR_REPORT == STD_ON
}
#endif
}
#endif
/**
* @brief Set the Voltage-based temperature sensor is enabled/disabled in stop mode
*
*@param pTmuHandle: TMU processing handle
* @param bEnable: whether Voltage-based temperature sensor is enabled in stop mode if TV_EN is active.
*/
void TMU_VoltageTempSetStopMode(TMU_HandleType* pTmuHandle, bool bEnable)
{
#if TMU_DEV_ERROR_REPORT == STD_ON
if(pTmuHandle->eIntance >= TMU_INSTANCE_MAX)
{
TMU_ReportDevError(TMU_INIT_ID, TMU_E_PARAM_INSTANCE);
}
else
{
#endif
TMU_Type *const pTmu = s_apTmuBase[pTmuHandle->eIntance];
TMU_HWA_ConfigVoltageTemperatureStopMode(pTmu, bEnable);
#if TMU_DEV_ERROR_REPORT == STD_ON
}
#endif
}
#endif
#ifdef TMU_SUPPORT_TRIM
/**
* @brief Get the temperature code from ADC
*
* @param pTmuHandle: TMU processing handle
* @return uint32_t the value records the ADC conversion results for voltage-based temperature sensor result in 135 Celsius
*/
uint32_t TMU_GetTcode(TMU_HandleType* pTmuHandle)
{
#if TMU_DEV_ERROR_REPORT == STD_ON
if(pTmuHandle->eIntance >= TMU_INSTANCE_MAX)
{
TMU_ReportDevError(TMU_INIT_ID, TMU_E_PARAM_INSTANCE);
return 0U;
}
else
{
#endif
TMU_Type *const pTmu = s_apTmuBase[pTmuHandle->eIntance];
return TMU_HWA_GetTemperatureCode(pTmu);
#if TMU_DEV_ERROR_REPORT == STD_ON
}
#endif
}
/**
* @brief Get the slope factor
*
* @param pTmuHandle: TMU processing handle
* @return uint32_t the value records the slope factor for voltage-based temperature sensor
*/
uint32_t TMU_GetTslope(TMU_HandleType* pTmuHandle)
{
#if TMU_DEV_ERROR_REPORT == STD_ON
if(pTmuHandle->eIntance >= TMU_INSTANCE_MAX)
{
TMU_ReportDevError(TMU_INIT_ID, TMU_E_PARAM_INSTANCE);
return 0U;
}
else
{
#endif
TMU_Type *const pTmu = s_apTmuBase[pTmuHandle->eIntance];
return TMU_HWA_GetSlopeFactor(pTmu);
#if TMU_DEV_ERROR_REPORT == STD_ON
}
#endif
}
#endif
#endif /* #if TMU_INSTANCE_COUNT > 0U */