2020-12-25 14:33:03 +08:00

384 lines
14 KiB
C

/**
*******************************************************************************
* @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)
*****************************************************************************/