rt-thread/bsp/hc32f4a0/Libraries/HC32F4A0_StdPeriph_Driver/src/hc32f4a0_ctc.c

400 lines
13 KiB
C

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