/** ******************************************************************************* * @file hc32f4a0_fcm.c * @brief This file provides firmware functions to manage the Frequency Clock * Measurement (FCM). @verbatim Change Logs: Date Author Notes 2020-03-09 Zhangxl First version @endverbatim ******************************************************************************* * Copyright (C) 2020, Huada Semiconductor Co., Ltd. All rights reserved. * * This software component is licensed by HDSC under BSD 3-Clause license * (the "License"); You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ******************************************************************************* */ /******************************************************************************* * Include files ******************************************************************************/ #include "hc32f4a0_fcm.h" #include "hc32f4a0_utility.h" /** * @addtogroup HC32F4A0_DDL_Driver * @{ */ /** * @defgroup DDL_FCM FCM * @brief FCM Driver Library * @{ */ #if (DDL_FCM_ENABLE == DDL_ON) /******************************************************************************* * Local type definitions ('typedef') ******************************************************************************/ /******************************************************************************* * Local pre-processor symbols/macros ('#define') ******************************************************************************/ /** * @defgroup FCM_Local_Macros FCM Local Macros * @{ */ /** * @defgroup FCM_Check_Parameters_Validity FCM Check Parameters Validity * @{ */ /*! Parameter validity check for FCM target clock source. */ #define IS_FCM_TAR_SOURCE(src) \ ( ((src) == FCM_TAR_CLK_XTAL) || \ ((src) == FCM_TAR_CLK_XTAL32) || \ ((src) == FCM_TAR_CLK_HRC) || \ ((src) == FCM_TAR_CLK_LRC) || \ ((src) == FCM_TAR_CLK_SWDTLRC) || \ ((src) == FCM_TAR_CLK_PCLK1) || \ ((src) == FCM_TAR_CLK_PLLAP) || \ ((src) == FCM_TAR_CLK_MRC) || \ ((src) == FCM_TAR_CLK_PLLHP) || \ ((src) == FCM_TAR_CLK_RTCLRC)) /*! Parameter validity check for FCM target clock division. */ #define IS_FCM_TAR_DIV(div) \ ( ((div) == FCM_TAR_CLK_DIV1) || \ ((div) == FCM_TAR_CLK_DIV4) || \ ((div) == FCM_TAR_CLK_DIV8) || \ ((div) == FCM_TAR_CLK_DIV32)) /*! Parameter validity check for FCM external reference input function. */ #define IS_FCM_EX_REF_FUNC(func) \ ( ((func) == FCM_EX_REF_OFF) || \ ((func) == FCM_EX_REF_ON)) /*! Parameter validity check for FCM reference clock edge. */ #define IS_FCM_REF_EDGE(edge) \ ( ((edge) == FCM_REF_CLK_RISING) || \ ((edge) == FCM_REF_CLK_FALLING) || \ ((edge) == FCM_REF_CLK_BOTH)) /*! Parameter validity check for FCM digital filter function. */ #define IS_FCM_DF(df) \ ( ((df) == FCM_DF_OFF) || \ ((df) == FCM_DF_MCKS_DIV1) || \ ((df) == FCM_DF_MCKS_DIV4) || \ ((df) == FCM_DF_MCKS_DIV16)) /*! Parameter validity check for FCM reference clock source. */ #define IS_FCM_REF_SOURCE(src) \ ( ((src) == FCM_REF_CLK_EXINPUT) || \ ((src) == FCM_REF_CLK_XTAL) || \ ((src) == FCM_REF_CLK_XTAL32) || \ ((src) == FCM_REF_CLK_HRC) || \ ((src) == FCM_REF_CLK_LRC) || \ ((src) == FCM_REF_CLK_SWDTLRC) || \ ((src) == FCM_REF_CLK_PCLK1) || \ ((src) == FCM_REF_CLK_PCLKAP) || \ ((src) == FCM_REF_CLK_MRC) || \ ((src) == FCM_REF_CLK_PLLHP) || \ ((src) == FCM_REF_CLK_RTCLRC)) /*! Parameter validity check for FCM reference clock division. */ #define IS_FCM_REF_DIV(div) \ ( ((div) == FCM_REF_CLK_DIV32) || \ ((div) == FCM_REF_CLK_DIV128) || \ ((div) == FCM_REF_CLK_DIV1024) || \ ((div) == FCM_REF_CLK_DIV8192)) /*! Parameter validity check for FCM abnormal reset function. */ #define IS_FCM_RESET_FUNC(func) \ ( ((func) == FCM_RST_OFF) || \ ((func) == FCM_RST_ON)) /*! Parameter validity check for FCM abnormal behavior function. */ #define IS_FCM_ERR_HANDLE(hd) \ ( ((hd) == FCM_ERR_INT) || \ ((hd) == FCM_ERR_RESET)) /*! Parameter validity check for FCM interrupt. */ #define IS_FCM_INT(it) (((it) | FCM_INT_MSK) == FCM_INT_MSK) /*! Parameter validity check for FCM flag state. */ #define IS_FCM_FLAG(flag) \ ( ((flag) != 0x00UL) && \ (((flag) | FCM_FLAG_MSK) == FCM_FLAG_MSK)) /** * @} */ /** * @} */ /******************************************************************************* * Global variable definitions (declared in header file with 'extern') ******************************************************************************/ /******************************************************************************* * Local function prototypes ('static') ******************************************************************************/ /******************************************************************************* * Local variable definitions ('static') ******************************************************************************/ /******************************************************************************* * Function implementation - global ('extern') and local ('static') ******************************************************************************/ /** * @defgroup FCM_Global_Functions FCM Global Functions * @{ */ /** * @brief Initialize FCM. * @param [in] pstcFcmInit Pointer to a stc_fcm_init_t structure * that contains configuration information. * @retval Ok: FCM initialize successful * ErrorInvalidParameter: NULL pointer */ en_result_t FCM_Init(const stc_fcm_init_t *pstcFcmInit) { en_result_t enRet = Ok; /* Check if pointer is NULL */ if (NULL == pstcFcmInit) { enRet = ErrorInvalidParameter; } else { /* Parameter validity checking */ DDL_ASSERT(IS_FCM_TAR_SOURCE(pstcFcmInit->u32TarClk)); DDL_ASSERT(IS_FCM_TAR_DIV(pstcFcmInit->u32TarClkDiv)); DDL_ASSERT(IS_FCM_EX_REF_FUNC(pstcFcmInit->u32ExRefClkEn)); DDL_ASSERT(IS_FCM_REF_EDGE(pstcFcmInit->u32RefClkEdge)); DDL_ASSERT(IS_FCM_DF(pstcFcmInit->u32DigFilter)); DDL_ASSERT(IS_FCM_REF_SOURCE(pstcFcmInit->u32RefClk)); DDL_ASSERT(IS_FCM_REF_DIV(pstcFcmInit->u32RefClkDiv)); DDL_ASSERT(IS_FCM_RESET_FUNC(pstcFcmInit->u32RstEn)); DDL_ASSERT(IS_FCM_ERR_HANDLE(pstcFcmInit->u32IntRstSel)); DDL_ASSERT(IS_FCM_INT(pstcFcmInit->u32IntType)); WRITE_REG32(M4_FCM->LVR, pstcFcmInit->u16LowerLimit); WRITE_REG32(M4_FCM->UVR, pstcFcmInit->u16UpperLimit); WRITE_REG32(M4_FCM->MCCR, (pstcFcmInit->u32TarClk | pstcFcmInit->u32TarClkDiv)); WRITE_REG32(M4_FCM->RCCR, (pstcFcmInit->u32ExRefClkEn | pstcFcmInit->u32RefClkEdge | \ pstcFcmInit->u32DigFilter | pstcFcmInit->u32RefClk | \ pstcFcmInit->u32RefClkDiv)); WRITE_REG32(M4_FCM->RIER, (pstcFcmInit->u32RstEn | pstcFcmInit->u32IntRstSel | \ pstcFcmInit->u32IntType)); } return enRet; } /** * @brief Initialize FCM structure. Fill each pstcFcmInit with * default value * @param [in] pstcFcmInit Pointer to a stc_fcm_init_t structure * that contains configuration information. * @retval Ok: FCM structure initialize successful * ErrorInvalidParameter: NULL pointer */ en_result_t FCM_StructInit(stc_fcm_init_t *pstcFcmInit) { en_result_t enRet = Ok; /* Check if pointer is NULL */ if (NULL == pstcFcmInit) { enRet = ErrorInvalidParameter; } else { /* Reset FCM init structure parameters values */ pstcFcmInit->u16LowerLimit = 0U; pstcFcmInit->u16UpperLimit = 0U; pstcFcmInit->u32TarClk = FCM_TAR_CLK_XTAL; pstcFcmInit->u32TarClkDiv = FCM_TAR_CLK_DIV1; pstcFcmInit->u32ExRefClkEn = FCM_EX_REF_OFF; pstcFcmInit->u32RefClkEdge = FCM_REF_CLK_RISING; pstcFcmInit->u32DigFilter = FCM_DF_OFF; pstcFcmInit->u32RefClk = FCM_REF_CLK_XTAL; pstcFcmInit->u32RefClkDiv = FCM_REF_CLK_DIV32; pstcFcmInit->u32RstEn = FCM_RST_OFF; pstcFcmInit->u32IntRstSel = FCM_ERR_INT; pstcFcmInit->u32IntType = (FCM_ERR_INT_OFF | FCM_END_INT_OFF | FCM_OVF_INT_OFF); } return enRet; } /** * @brief De-Initialize FCM. * @param None * @retval None */ void FCM_DeInit(void) { WRITE_REG32(M4_FCM->STR, FCM_REG_RESET_VALUE); WRITE_REG32(M4_FCM->CLR, FCM_FLAG_MSK); WRITE_REG32(M4_FCM->LVR, FCM_REG_RESET_VALUE); WRITE_REG32(M4_FCM->UVR, FCM_REG_RESET_VALUE); WRITE_REG32(M4_FCM->MCCR,FCM_REG_RESET_VALUE); WRITE_REG32(M4_FCM->RCCR,FCM_REG_RESET_VALUE); WRITE_REG32(M4_FCM->RIER,FCM_REG_RESET_VALUE); } /** * @brief Get FCM state, get FCM overflow, complete, error flag. * @param [in] u32Flag FCM flags. * @arg FCM_FLAG_ERR: FCM error. * @arg FCM_FLAG_END: FCM measure end. * @arg FCM_FLAG_OVF: FCM overflow. * @retval en_flag_status_t: FCM flag status. */ en_flag_status_t FCM_GetStatus(uint32_t u32Flag) { DDL_ASSERT(IS_FCM_FLAG(u32Flag)); return (READ_REG32_BIT(M4_FCM->SR, u32Flag) ? Set : Reset); } /** * @brief Clear FCM state, Clear FCM overflow, complete, error flag. * @param [in] u32Flag FCM flags. * @arg FCM_FLAG_ERR: FCM error. * @arg FCM_FLAG_END: FCM measure end. * @arg FCM_FLAG_OVF: FCM overflow. * @arg FCM_FLAG_MSK: All above 3 flags of FCM. * @retval None. */ void FCM_ClearStatus(uint32_t u32Flag) { DDL_ASSERT(IS_FCM_FLAG(u32Flag)); SET_REG32_BIT(M4_FCM->CLR, u32Flag); } /** * @brief Get FCM counter value. * @param None * @retval FCM counter value. */ uint16_t FCM_GetCounter(void) { return (uint16_t)(READ_REG32(M4_FCM->CNTR) & 0xFFFFU); } /** * @brief FCM target clock type and division config. * @param [in] u32Tar Target clock type. * @arg FCM_TAR_CLK_XTAL * @arg FCM_TAR_CLK_XTAL32 * @arg FCM_TAR_CLK_HRC * @arg FCM_TAR_CLK_LRC * @arg FCM_TAR_CLK_SWDTLRC * @arg FCM_TAR_CLK_PCLK1 * @arg FCM_TAR_CLK_PLLAP * @arg FCM_TAR_CLK_MRC * @arg FCM_TAR_CLK_PLLHP * @arg FCM_TAR_CLK_RTCLRC * @param [in] u32Div Target clock division. * @arg FCM_TAR_CLK_DIV1 * @arg FCM_TAR_CLK_DIV4 * @arg FCM_TAR_CLK_DIV8 * @arg FCM_TAR_CLK_DIV32 * @retval None. */ void FCM_SetTarClk(uint32_t u32Tar, uint32_t u32Div) { DDL_ASSERT(IS_FCM_TAR_SOURCE(u32Tar)); DDL_ASSERT(IS_FCM_TAR_DIV(u32Div)); WRITE_REG32(M4_FCM->MCCR, (u32Tar | u32Div)); } /** * @brief FCM reference clock type and division config. * @param [in] u32Ref Reference clock type. * @arg FCM_REF_CLK_EXINPUT * @arg FCM_REF_CLK_XTAL * @arg FCM_REF_CLK_XTAL32 * @arg FCM_REF_CLK_HRC * @arg FCM_REF_CLK_LRC * @arg FCM_REF_CLK_SWDTLRC * @arg FCM_REF_CLK_PCLK1 * @arg FCM_REF_CLK_PCLKAP * @arg FCM_REF_CLK_MRC * @arg FCM_REF_CLK_PLLHP * @arg FCM_REF_CLK_RTCLRC * @param [in] u32Div Reference clock division. * @arg FCM_REF_CLK_DIV32 * @arg FCM_REF_CLK_DIV128 * @arg FCM_REF_CLK_DIV1024 * @arg FCM_REF_CLK_DIV8192 * @retval None. */ void FCM_SetRefClk(uint32_t u32Ref, uint32_t u32Div) { DDL_ASSERT(IS_FCM_REF_SOURCE(u32Ref)); DDL_ASSERT(IS_FCM_REF_DIV(u32Div)); MODIFY_REG32(M4_FCM->RCCR, \ (FCM_RCCR_INEXS | FCM_RCCR_RCKS | FCM_RCCR_RDIVS), \ (u32Ref | u32Div)); } /** * @brief FCM function config. * @param [in] enNewState * @arg Enable * @arg Disable * @retval None. */ void FCM_Cmd(en_functional_state_t enNewState) { DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState)); WRITE_REG32(bM4_FCM->STR_b.START, enNewState); } /** * @} */ #endif /* DDL_FCM_ENABLE */ /** * @} */ /** * @} */ /****************************************************************************** * EOF (not truncated) *****************************************************************************/