359 lines
10 KiB
C
359 lines
10 KiB
C
/*!
|
|
\file gd32f4xx_ctc.c
|
|
\brief CTC driver
|
|
*/
|
|
|
|
/*
|
|
Copyright (C) 2016 GigaDevice
|
|
|
|
2016-08-15, V1.0.0, firmware for GD32F4xx
|
|
*/
|
|
|
|
#include "gd32f4xx_ctc.h"
|
|
|
|
#define CTC_FLAG_MASK ((uint32_t)0x00000700U)
|
|
|
|
/*!
|
|
\brief reset CTC clock trim controller
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_deinit(void)
|
|
{
|
|
/* reset CTC */
|
|
rcu_periph_reset_enable(RCU_CTCRST);
|
|
rcu_periph_reset_disable(RCU_CTCRST);
|
|
}
|
|
|
|
/*!
|
|
\brief configure the IRC48M trim value
|
|
\param[in] ctc_trim_value: 8-bit IRC48M trim value
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_irc48m_trim_value_config(uint8_t ctc_trim_value)
|
|
{
|
|
/* clear TRIMVALUE bits */
|
|
CTC_CTL0 &= (~(uint32_t)CTC_CTL0_TRIMVALUE);
|
|
/* set TRIMVALUE bits */
|
|
CTC_CTL0 |= ((uint32_t)ctc_trim_value << 8);
|
|
}
|
|
|
|
/*!
|
|
\brief generate software reference source sync pulse
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_software_refsource_pulse_generate(void)
|
|
{
|
|
CTC_CTL0 |= (uint32_t)CTC_CTL0_SWREFPUL;
|
|
}
|
|
|
|
/*!
|
|
\brief configure hardware automatically trim mode
|
|
\param[in] ctc_hardmode:
|
|
\arg CTC_HARDWARE_TRIM_MODE_ENABLE: hardware automatically trim mode enable
|
|
\arg CTC_HARDWARE_TRIM_MODE_DISABLE: hardware automatically trim mode disable
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_hardware_trim_mode_config(uint32_t ctc_hardmode)
|
|
{
|
|
CTC_CTL0 &= (uint32_t)(~CTC_CTL0_AUTOTRIM);
|
|
CTC_CTL0 |= (uint32_t)ctc_hardmode;
|
|
}
|
|
|
|
/*!
|
|
\brief enable CTC counter
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_counter_enable(void)
|
|
{
|
|
CTC_CTL0 |= (uint32_t)CTC_CTL0_CNTEN;
|
|
}
|
|
|
|
/*!
|
|
\brief disable CTC counter
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_counter_disable(void)
|
|
{
|
|
CTC_CTL0 &= (uint32_t)(~CTC_CTL0_CNTEN);
|
|
}
|
|
|
|
/*!
|
|
\brief configure reference signal source polarity
|
|
\param[in] ctc_polarity:
|
|
\arg CTC_REFSOURCE_POLARITY_FALLING: reference signal source polarity is falling edge
|
|
\arg CTC_REFSOURCE_POLARITY_RISING: reference signal source polarity is rising edge
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_refsource_polarity_config(uint32_t ctc_polarity)
|
|
{
|
|
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPOL);
|
|
CTC_CTL1 |= (uint32_t)ctc_polarity;
|
|
}
|
|
|
|
/*!
|
|
\brief select USBFS or USBHS SOF signal
|
|
\param[in] ctc_usbsof:
|
|
\arg CTC_USBSOFSEL_USBHS: USBHS SOF signal is selected
|
|
\arg CTC_USBSOFSEL_USBFS: USBFS SOF signal is selected
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_usbsof_signal_select(uint32_t ctc_usbsof)
|
|
{
|
|
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_USBSOFSEL);
|
|
CTC_CTL1 |= (uint32_t)ctc_usbsof;
|
|
}
|
|
|
|
/*!
|
|
\brief select reference signal source
|
|
\param[in] ctc_refs:
|
|
\arg CTC_REFSOURCE_GPIO: GPIO is selected
|
|
\arg CTC_REFSOURCE_LXTAL: LXTAL is clock selected
|
|
\arg CTC_REFSOURCE_USBSOF: USBSOF is selected
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_refsource_signal_select(uint32_t ctc_refs)
|
|
{
|
|
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL);
|
|
CTC_CTL1 |= (uint32_t)ctc_refs;
|
|
}
|
|
|
|
/*!
|
|
\brief configure reference signal source prescaler
|
|
\param[in] ctc_prescaler:
|
|
\arg CTC_REFSOURCE_PSC_OFF: reference signal not divided
|
|
\arg CTC_REFSOURCE_PSC_DIV2: reference signal divided by 2
|
|
\arg CTC_REFSOURCE_PSC_DIV4: reference signal divided by 4
|
|
\arg CTC_REFSOURCE_PSC_DIV8: reference signal divided by 8
|
|
\arg CTC_REFSOURCE_PSC_DIV16: reference signal divided by 16
|
|
\arg CTC_REFSOURCE_PSC_DIV32: reference signal divided by 32
|
|
\arg CTC_REFSOURCE_PSC_DIV64: reference signal divided by 64
|
|
\arg CTC_REFSOURCE_PSC_DIV128: reference signal divided by 128
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_refsource_prescaler_config(uint32_t ctc_prescaler)
|
|
{
|
|
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPSC);
|
|
CTC_CTL1 |= (uint32_t)ctc_prescaler;
|
|
}
|
|
|
|
/*!
|
|
\brief configure clock trim base limit value
|
|
\param[in] ctc_limit_value: 8-bit clock trim base limit value
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_clock_limit_value_config(uint8_t ctc_limit_value)
|
|
{
|
|
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_CKLIM);
|
|
CTC_CTL1 |= (uint32_t)((uint32_t)ctc_limit_value << 16);
|
|
}
|
|
|
|
/*!
|
|
\brief configure CTC counter reload value
|
|
\param[in] ctc_reload_value: 16-bit CTC counter reload value
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_counter_reload_value_config(uint16_t ctc_reload_value)
|
|
{
|
|
CTC_CTL1 &= (uint32_t)(~CTC_CTL1_RLVALUE);
|
|
CTC_CTL1 |= (uint32_t)ctc_reload_value;
|
|
}
|
|
|
|
/*!
|
|
\brief read CTC counter capture value when reference sync pulse occurred
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval the 16-bit CTC counter capture value
|
|
*/
|
|
uint16_t ctc_counter_capture_value_read(void)
|
|
{
|
|
uint16_t capture_value = 0U;
|
|
capture_value = (uint16_t)((CTC_STAT & CTC_STAT_REFCAP)>> 16);
|
|
return (capture_value);
|
|
}
|
|
|
|
/*!
|
|
\brief read CTC trim counter direction when reference sync pulse occurred
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval FlagStatus: SET or RESET
|
|
\arg SET: CTC trim counter direction is down-counting
|
|
\arg RESET: CTC trim counter direction is up-counting
|
|
*/
|
|
FlagStatus ctc_counter_direction_read(void)
|
|
{
|
|
if(RESET != (CTC_STAT & CTC_STAT_REFDIR)){
|
|
return SET;
|
|
}else{
|
|
return RESET;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief read CTC counter reload value
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval the 16-bit CTC counter reload value
|
|
*/
|
|
uint16_t ctc_counter_reload_value_read(void)
|
|
{
|
|
uint16_t reload_value = 0U;
|
|
reload_value = (uint16_t)(CTC_CTL1 & CTC_CTL1_RLVALUE);
|
|
return (reload_value);
|
|
}
|
|
|
|
/*!
|
|
\brief read the IRC48M trim value
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval the 8-bit IRC48M trim value
|
|
*/
|
|
uint8_t ctc_irc48m_trim_value_read(void)
|
|
{
|
|
uint8_t trim_value = 0U;
|
|
trim_value = (uint8_t)((CTC_CTL0 & CTC_CTL0_TRIMVALUE) >> 8);
|
|
return (trim_value);
|
|
}
|
|
|
|
/*!
|
|
\brief enable the CTC interrupt
|
|
\param[in] ctc_interrupt: CTC interrupt enable
|
|
\arg CTC_INT_CKOKIE: clock trim OK interrupt enable
|
|
\arg CTC_INT_CKWARNIE: clock trim warning interrupt enable
|
|
\arg CTC_INT_ERRIE: error interrupt enable
|
|
\arg CTC_INT_EREFIE: expect reference interrupt enable
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_interrupt_enable(uint32_t ctc_interrupt)
|
|
{
|
|
CTC_CTL0 |= (uint32_t)ctc_interrupt;
|
|
}
|
|
|
|
/*!
|
|
\brief disable the CTC interrupt
|
|
\param[in] ctc_interrupt: CTC interrupt enable source
|
|
\arg CTC_INT_CKOKIE: clock trim OK interrupt enable
|
|
\arg CTC_INT_CKWARNIE: clock trim warning interrupt enable
|
|
\arg CTC_INT_ERRIE: error interrupt enable
|
|
\arg CTC_INT_EREFIE: expect reference interrupt enable
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_interrupt_disable(uint32_t ctc_interrupt)
|
|
{
|
|
CTC_CTL0 &= (uint32_t)(~ctc_interrupt);
|
|
}
|
|
|
|
/*!
|
|
\brief get CTC interrupt flag
|
|
\param[in] ctc_interrupt: the CTC interrupt flag
|
|
\arg CTC_INT_CKOK: clock trim OK interrupt
|
|
\arg CTC_INT_CKWARN: clock trim warning interrupt
|
|
\arg CTC_INT_ERR: error interrupt
|
|
\arg CTC_INT_EREF: expect reference interrupt
|
|
\arg CTC_INT_CKERR: clock trim error bit interrupt
|
|
\arg CTC_INT_REFMISS: reference sync pulse miss interrupt
|
|
\arg CTC_INT_TRIMERR: trim value error interrupt
|
|
\param[out] none
|
|
\retval FlagStatus: SET or RESET
|
|
*/
|
|
FlagStatus ctc_interrupt_flag_get(uint32_t ctc_interrupt)
|
|
{
|
|
uint32_t interrupt = 0U, intenable = 0U;
|
|
|
|
if(ctc_interrupt & CTC_FLAG_MASK){
|
|
intenable = CTC_CTL0 & CTC_INT_ERRIE;
|
|
}else{
|
|
intenable = CTC_CTL0 & ctc_interrupt;
|
|
}
|
|
interrupt = CTC_STAT & ctc_interrupt;
|
|
|
|
if(interrupt && intenable){
|
|
return SET;
|
|
}else{
|
|
return RESET;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief clear CTC interrupt flag
|
|
\param[in] ctc_interrupt: the CTC interrupt flag
|
|
\arg CTC_INT_CKOK: clock trim OK interrupt
|
|
\arg CTC_INT_CKWARN: clock trim warning interrupt
|
|
\arg CTC_INT_ERR: error interrupt
|
|
\arg CTC_INT_EREF: expect reference interrupt
|
|
\arg CTC_INT_CKERR: clock trim error bit interrupt
|
|
\arg CTC_INT_REFMISS: reference sync pulse miss interrupt
|
|
\arg CTC_INT_TRIMERR: trim value error interrupt
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_interrupt_flag_clear(uint32_t ctc_interrupt)
|
|
{
|
|
if(ctc_interrupt & CTC_FLAG_MASK){
|
|
CTC_INTC |= CTC_INTC_ERRIC;
|
|
}else{
|
|
CTC_INTC |= ctc_interrupt;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief get CTC flag
|
|
\param[in] ctc_flag: the CTC flag
|
|
\arg CTC_FLAG_CKOK: clock trim OK flag
|
|
\arg CTC_FLAG_CKWARN: clock trim warning flag
|
|
\arg CTC_FLAG_ERR: error flag
|
|
\arg CTC_FLAG_EREF: expect reference flag
|
|
\arg CTC_FLAG_CKERR: clock trim error bit
|
|
\arg CTC_FLAG_REFMISS: reference sync pulse miss
|
|
\arg CTC_FLAG_TRIMERR: trim value error bit
|
|
\param[out] none
|
|
\retval FlagStatus: SET or RESET
|
|
*/
|
|
FlagStatus ctc_flag_get(uint32_t ctc_flag)
|
|
{
|
|
if(RESET != (CTC_STAT & ctc_flag)){
|
|
return SET;
|
|
}else{
|
|
return RESET;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
\brief clear CTC flag
|
|
\param[in] ctc_flag: the CTC flag
|
|
\arg CTC_FLAG_CKOK: clock trim OK flag
|
|
\arg CTC_FLAG_CKWARN: clock trim warning flag
|
|
\arg CTC_FLAG_ERR: error flag
|
|
\arg CTC_FLAG_EREF: expect reference flag
|
|
\arg CTC_FLAG_CKERR: clock trim error bit
|
|
\arg CTC_FLAG_REFMISS: reference sync pulse miss
|
|
\arg CTC_FLAG_TRIMERR: trim value error bit
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ctc_flag_clear(uint32_t ctc_flag)
|
|
{
|
|
if(ctc_flag & CTC_FLAG_MASK){
|
|
CTC_INTC |= CTC_INTC_ERRIC;
|
|
}else{
|
|
CTC_INTC |= ctc_flag;
|
|
}
|
|
}
|