/** ******************************************************************************* * @file hc32f4a0_ctc.c * @brief This file provides firmware functions to manage the Clock Trimming * Controller(CTC). @verbatim Change Logs: Date Author Notes 2020-09-01 Hongjh First version 2020-10-30 Hongjh Modify for refining CTC initialization structure @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_ctc.h" #include "hc32f4a0_utility.h" /** * @addtogroup HC32F4A0_DDL_Driver * @{ */ /** * @defgroup DDL_CTC CTC * @brief CTC Driver Library * @{ */ #if (DDL_CTC_ENABLE == DDL_ON) /******************************************************************************* * Local type definitions ('typedef') ******************************************************************************/ /******************************************************************************* * Local pre-processor symbols/macros ('#define') ******************************************************************************/ /** * @defgroup CTC_Local_Macros CTC Local Macros * @{ */ /** * @defgroup CTC_Check_Parameters_Validity CTC Check Parameters Validity * @{ */ #define IS_CTC_REF_CLK_SRC(x) \ ( ((x) == CTC_REF_CLK_XTAL) || \ ((x) == CTC_REF_CLK_XTAL32) || \ ((x) == CTC_REF_CLK_CTCREF)) #define IS_CTC_REF_CLK_DIV(x) \ ( ((x) == CTC_REF_CLK_DIV8) || \ ((x) == CTC_REF_CLK_DIV32) || \ ((x) == CTC_REF_CLK_DIV128) || \ ((x) == CTC_REF_CLK_DIV256) || \ ((x) == CTC_REF_CLK_DIV512) || \ ((x) == CTC_REF_CLK_DIV1024) || \ ((x) == CTC_REF_CLK_DIV2048) || \ ((x) == CTC_REF_CLK_DIV4096)) #define IS_CTC_OFFSET_VALUE(x) ((x) <= 0xFFUL) #define IS_CTC_RELOAD_VALUE(x) ((x) <= 0xFFFFUL) #define IS_CTC_TRIM_VALUE(x) ((x) <= 0x3FUL) #define IS_CTC_TOLERANCE_DEVIATION(x) (((x) >= 0.0F) && \ ((x) <= CTC_TOLERANCE_DEVIATION_MAX)) #define IS_CTC_FLAG(x) \ ( ((x) != 0UL) && \ (((x) | CTC_FLAG_ALL) == CTC_FLAG_ALL)) /** * @} */ /** * @} */ /******************************************************************************* * 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 CTC_Global_Functions CTC Global Functions * @{ */ /** * @brief Initialize CTC function. * @param [in] pstcCtcInit Pointer to a @ref stc_ctc_init_t structure. * @retval An en_result_t enumeration value: * - Ok: Initialize success * - ErrorNotReady: CTC state is busy * - ErrorInvalidParameter: If one of following cases matches: * - pstcCtcInit is NULL * - Reference frequency is out of range * - Calculate reload & offset value out of range */ en_result_t CTC_Init(const stc_ctc_init_t *pstcCtcInit) { float f32OffsetValue; uint32_t u32RegValue; uint32_t u32ReloadValue; uint32_t u32OffsetValue; uint32_t u32RefClockDiv; uint32_t u32Multiplier; uint64_t u64InterClock; uint32_t u32HrcFreq = HRC_VALUE; en_result_t enRet = ErrorNotReady; /* Check CTC status */ if (CTC_FLAG_BUSY != (READ_REG32_BIT(M4_CTC->STR, CTC_FLAG_BUSY))) { if ((NULL == pstcCtcInit) || (0UL == pstcCtcInit->u32RefClockFreq)) { enRet = ErrorInvalidParameter; } else { /* Check parameters */ DDL_ASSERT(IS_CTC_REF_CLK_SRC(pstcCtcInit->u32RefClockSrc)); DDL_ASSERT(IS_CTC_REF_CLK_DIV(pstcCtcInit->u32RefClockDiv)); DDL_ASSERT(IS_CTC_TRIM_VALUE(pstcCtcInit->u32TrimValue)); DDL_ASSERT(IS_CTC_TOLERANCE_DEVIATION(pstcCtcInit->f32ToleranceDeviation)); if (pstcCtcInit->u32RefClockDiv < CTC_REF_CLK_DIV128) { u32RefClockDiv = (8UL << (2UL * pstcCtcInit->u32RefClockDiv)); } else { u32RefClockDiv = (32UL << pstcCtcInit->u32RefClockDiv); } u64InterClock = ((uint64_t)u32HrcFreq) * ((uint64_t)(u32RefClockDiv)); u32Multiplier = (uint32_t)(u64InterClock / pstcCtcInit->u32RefClockFreq); /* Calculate offset value formula: OFSVAL = (Fhrc / (Fref * Fref_divsion)) * TA */ f32OffsetValue = ((float)u32Multiplier) * (pstcCtcInit->f32ToleranceDeviation); u32OffsetValue = (uint32_t)(f32OffsetValue); /* Calculate reload value formula: RLDVAL = (Fhrc / (Fref * Fref_divsion)) + OFSVAL */ u32ReloadValue = u32Multiplier + u32OffsetValue; if ((IS_CTC_OFFSET_VALUE(u32OffsetValue)) && (IS_CTC_RELOAD_VALUE(u32ReloadValue))) { /* Set CR1 */ u32RegValue = (pstcCtcInit->u32RefClockDiv | \ pstcCtcInit->u32RefClockSrc | \ (pstcCtcInit->u32TrimValue << CTC_CR1_TRMVAL_POS)); WRITE_REG32(M4_CTC->CR1, u32RegValue); /* Set CR2 */ u32RegValue = ((u32ReloadValue << CTC_CR2_RLDVAL_POS) | u32OffsetValue); WRITE_REG32(M4_CTC->CR2, u32RegValue); enRet = Ok; } } } return enRet; } /** * @brief Set the fields of structure stc_uart_init_t to default values. * @param [out] pstcCtcInit Pointer to a @ref stc_ctc_init_t structure. * @retval An en_result_t enumeration value: * - Ok: Initialize success * - ErrorInvalidParameter: pstcCtcInit is NULL */ en_result_t CTC_StructInit(stc_ctc_init_t *pstcCtcInit) { en_result_t enRet = ErrorInvalidParameter; /* Check parameters */ if (NULL != pstcCtcInit) { pstcCtcInit->u32RefClockFreq = 0UL; pstcCtcInit->u32RefClockSrc = CTC_REF_CLK_CTCREF; pstcCtcInit->u32RefClockDiv = CTC_REF_CLK_DIV8; pstcCtcInit->f32ToleranceDeviation = 0.0F; pstcCtcInit->u32TrimValue = 0UL; enRet = Ok; } return enRet; } /** * @brief De-Initialize CTC function. * @param None * @retval An en_result_t enumeration value: * - Ok: De-Initialize success * - ErrorNotReady: CTC state is busy */ en_result_t CTC_DeInit(void) { en_result_t enRet = ErrorNotReady; /* Check CTC status */ if (CTC_FLAG_BUSY != (READ_REG32_BIT(M4_CTC->STR, CTC_FLAG_BUSY))) { /* Configures the registers to reset value. */ WRITE_REG32(M4_CTC->CR1, 0UL); WRITE_REG32(M4_CTC->CR2, 0UL); enRet = Ok; } return enRet; } /** * @brief Set CTC reference clock division. * @param [in] u32Div CTC reference clock prescaler * This parameter can be one of the following values: * @arg CTC_REF_CLK_DIV8: REFCLK/8 * @arg CTC_REF_CLK_DIV32: REFCLK/32 * @arg CTC_REF_CLK_DIV128: REFCLK/128 * @arg CTC_REF_CLK_DIV256: REFCLK/256 * @arg CTC_REF_CLK_DIV512: REFCLK/512 * @arg CTC_REF_CLK_DIV1024: REFCLK/1024 * @arg CTC_REF_CLK_DIV2048: REFCLK/2048 * @arg CTC_REF_CLK_DIV4096: REFCLK/4096 * @retval None */ void CTC_SetRefClockDiv(uint32_t u32Div) { /* Check parameters */ DDL_ASSERT(IS_CTC_REF_CLK_DIV(u32Div)); MODIFY_REG32(M4_CTC->CR1, CTC_CR1_REFPSC, u32Div); } /** * @brief Set CTC reference clock source. * @param [in] u32ClockSrc CTC reference clock source * This parameter can be one of the following values: * @arg CTC_REF_CLK_CTCREF: Clock source CTCREF * @arg CTC_REF_CLK_XTAL: Clock source XTAL * @retval None */ void CTC_SetRefClockSrc(uint32_t u32ClockSrc) { /* Check parameters */ DDL_ASSERT(IS_CTC_REF_CLK_SRC(u32ClockSrc)); MODIFY_REG32(M4_CTC->CR1, CTC_CR1_REFCKS, u32ClockSrc); } /** * @brief Enable or disable CTC error interrupt function. * @param [in] enNewState The function new state. * This parameter can be one of the following values: * @arg Enable: Enable CTC error interrupt function. * @arg Disable: Disable CTC error interrupt function. * @retval None */ void CTC_IntCmd(en_functional_state_t enNewState) { /* Check parameters */ DDL_ASSERT(IS_FUNCTIONAL_STATE(enNewState)); WRITE_REG32(bM4_CTC->CR1_b.ERRIE, enNewState); } /** * @brief Get CTC flag. * @param [in] u32Flag CTC flag * This parameter can be any composed value of the following values:: * @arg CTC_FLAG_TRIM_OK: Trimming OK flag * @arg CTC_FLAG_TRIM_OVF: Trimming overflow flag * @arg CTC_FLAG_TRIM_UDF: Trimming underflow flag * @arg CTC_FLAG_BUSY: CTC busy flag * @retval Returned value can be one of the following values: * - Set: Any bit of the composed flag is set. * - Reset: All bit of the composed flag is reset. */ en_flag_status_t CTC_GetStatus(uint32_t u32Flag) { /* Check parameters */ DDL_ASSERT(IS_CTC_FLAG(u32Flag)); return ((0UL == READ_REG32_BIT(M4_CTC->STR, u32Flag)) ? Reset : Set); } /** * @brief Set CTC trimming value. * @param [in] u32TrimValue CTC trimming value * This parameter can be min=0 && max=0x3F * @retval None */ void CTC_SetTrimValue(uint32_t u32TrimValue) { /* Check parameters */ DDL_ASSERT(IS_CTC_TRIM_VALUE(u32TrimValue)); MODIFY_REG32(M4_CTC->CR1, CTC_CR1_TRMVAL, (u32TrimValue << CTC_CR1_TRMVAL_POS)); } /** * @brief Get CTC trimming value. * @param None * @retval CTC trimming value(between Min_Data=0 and Max_Data=0x3F) */ uint32_t CTC_GetTrimValue(void) { return (READ_REG32_BIT(M4_CTC->CR1, CTC_CR1_TRMVAL) >> CTC_CR1_TRMVAL_POS); } /** * @brief Set CTC reload value. * @param [in] u32ReloadValue CTC reload value * This parameter can be between Min_Data=0 and Max_Data=0xFFFF * @retval None */ void CTC_SetReloadValue(uint32_t u32ReloadValue) { /* Check parameters */ DDL_ASSERT(IS_CTC_RELOAD_VALUE(u32ReloadValue)); MODIFY_REG32(M4_CTC->CR2, CTC_CR2_RLDVAL, (u32ReloadValue << CTC_CR2_RLDVAL_POS)); } /** * @brief Get CTC reload value. * @param None * @retval CTC reload value (between Min_Data=0 and Max_Data=0xFFFF) */ uint16_t CTC_GetReloadValue(void) { return (uint16_t)(READ_REG32_BIT(M4_CTC->CR2, CTC_CR2_RLDVAL) >> CTC_CR2_RLDVAL_POS); } /** * @brief Set CTC offset value. * @param [in] u32OffsetValue CTC offset value * This parameter can be between Min_Data=0 and Max_Data=0xFF * @retval None */ void CTC_SetOffsetValue(uint32_t u32OffsetValue) { /* Check parameters */ DDL_ASSERT(IS_CTC_OFFSET_VALUE(u32OffsetValue)); MODIFY_REG32(M4_CTC->CR2, CTC_CR2_OFSVAL, (u32OffsetValue << CTC_CR2_OFSVAL_POS)); } /** * @brief Get CTC offset value. * @param None * @retval CTC offset value (between Min_Data=0 and Max_Data=0xFF) */ uint32_t CTC_GetOffsetValue(void) { return (READ_REG32_BIT(M4_CTC->CR2, CTC_CR2_OFSVAL) >> CTC_CR2_OFSVAL_POS); } /** * @} */ #endif /* DDL_CTC_ENABLE */ /** * @} */ /** * @} */ /****************************************************************************** * EOF (not truncated) *****************************************************************************/