1 /*!
2 \file gd32f3x0_ctc.c
3 \brief CTC driver
4
5 \version 2017-06-06, V1.0.0, firmware for GD32F3x0
6 \version 2019-06-01, V2.0.0, firmware for GD32F3x0
7 \version 2020-09-30, V2.1.0, firmware for GD32F3x0
8 */
9
10 /*
11 Copyright (c) 2020, GigaDevice Semiconductor Inc.
12
13 Redistribution and use in source and binary forms, with or without modification,
14 are permitted provided that the following conditions are met:
15
16 1. Redistributions of source code must retain the above copyright notice, this
17 list of conditions and the following disclaimer.
18 2. Redistributions in binary form must reproduce the above copyright notice,
19 this list of conditions and the following disclaimer in the documentation
20 and/or other materials provided with the distribution.
21 3. Neither the name of the copyright holder nor the names of its contributors
22 may be used to endorse or promote products derived from this software without
23 specific prior written permission.
24
25 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 OF SUCH DAMAGE.
35 */
36
37 #include "gd32f3x0_ctc.h"
38
39 #define CTC_FLAG_MASK ((uint32_t)0x00000700U)
40
41 /*!
42 \brief reset CTC clock trim controller
43 \param[in] none
44 \param[out] none
45 \retval none
46 */
ctc_deinit(void)47 void ctc_deinit(void)
48 {
49 /* reset CTC */
50 rcu_periph_reset_enable(RCU_CTCRST);
51 rcu_periph_reset_disable(RCU_CTCRST);
52 }
53
54 /*!
55 \brief configure reference signal source polarity
56 \param[in] polarity:
57 only one parameter can be selected which is shown as below:
58 \arg CTC_REFSOURCE_POLARITY_FALLING: reference signal source polarity is falling edge
59 \arg CTC_REFSOURCE_POLARITY_RISING: reference signal source polarity is rising edge
60 \param[out] none
61 \retval none
62 */
ctc_refsource_polarity_config(uint32_t polarity)63 void ctc_refsource_polarity_config(uint32_t polarity)
64 {
65 CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPOL);
66 CTC_CTL1 |= (uint32_t)polarity;
67 }
68
69 /*!
70 \brief select reference signal source
71 \param[in] refs:
72 only one parameter can be selected which is shown as below:
73 \arg CTC_REFSOURCE_GPIO: GPIO is selected
74 \arg CTC_REFSOURCE_LXTAL: LXTAL is clock selected
75 \arg CTC_REFSOURCE_USBSOF: USBSOF is selected
76 \param[out] none
77 \retval none
78 */
ctc_refsource_signal_select(uint32_t refs)79 void ctc_refsource_signal_select(uint32_t refs)
80 {
81 CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL);
82 CTC_CTL1 |= (uint32_t)refs;
83 }
84
85 /*!
86 \brief configure reference signal source prescaler
87 \param[in] prescaler:
88 only one parameter can be selected which is shown as below:
89 \arg CTC_REFSOURCE_PSC_OFF: reference signal not divided
90 \arg CTC_REFSOURCE_PSC_DIV2: reference signal divided by 2
91 \arg CTC_REFSOURCE_PSC_DIV4: reference signal divided by 4
92 \arg CTC_REFSOURCE_PSC_DIV8: reference signal divided by 8
93 \arg CTC_REFSOURCE_PSC_DIV16: reference signal divided by 16
94 \arg CTC_REFSOURCE_PSC_DIV32: reference signal divided by 32
95 \arg CTC_REFSOURCE_PSC_DIV64: reference signal divided by 64
96 \arg CTC_REFSOURCE_PSC_DIV128: reference signal divided by 128
97 \param[out] none
98 \retval none
99 */
ctc_refsource_prescaler_config(uint32_t prescaler)100 void ctc_refsource_prescaler_config(uint32_t prescaler)
101 {
102 CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPSC);
103 CTC_CTL1 |= (uint32_t)prescaler;
104 }
105
106 /*!
107 \brief configure clock trim base limit value
108 \param[in] limit_value: 8-bit clock trim base limit value
109 \arg 0x00-0xFF
110 \param[out] none
111 \retval none
112 */
ctc_clock_limit_value_config(uint8_t limit_value)113 void ctc_clock_limit_value_config(uint8_t limit_value)
114 {
115 CTC_CTL1 &= (uint32_t)(~CTC_CTL1_CKLIM);
116 CTC_CTL1 |= CTL1_CKLIM(limit_value);
117 }
118
119 /*!
120 \brief configure CTC counter reload value
121 \param[in] reload_value: 16-bit CTC counter reload value
122 \arg 0x0000-0xFFFF
123 \param[out] none
124 \retval none
125 */
ctc_counter_reload_value_config(uint16_t reload_value)126 void ctc_counter_reload_value_config(uint16_t reload_value)
127 {
128 CTC_CTL1 &= (uint32_t)(~CTC_CTL1_RLVALUE);
129 CTC_CTL1 |= (uint32_t)reload_value;
130 }
131
132 /*!
133 \brief enable CTC trim counter
134 \param[in] none
135 \param[out] none
136 \retval none
137 */
ctc_counter_enable(void)138 void ctc_counter_enable(void)
139 {
140 CTC_CTL0 |= (uint32_t)CTC_CTL0_CNTEN;
141 }
142
143 /*!
144 \brief disable CTC trim counter
145 \param[in] none
146 \param[out] none
147 \retval none
148 */
ctc_counter_disable(void)149 void ctc_counter_disable(void)
150 {
151 CTC_CTL0 &= (uint32_t)(~CTC_CTL0_CNTEN);
152 }
153
154 /*!
155 \brief configure the IRC48M trim value
156 \param[in] trim_value: 8-bit IRC48M trim value
157 \arg 0x00-0x3F
158 \param[out] none
159 \retval none
160 */
ctc_irc48m_trim_value_config(uint8_t trim_value)161 void ctc_irc48m_trim_value_config(uint8_t trim_value)
162 {
163 /* clear TRIMVALUE bits */
164 CTC_CTL0 &= (~(uint32_t)CTC_CTL0_TRIMVALUE);
165 /* set TRIMVALUE bits */
166 CTC_CTL0 |= CTL0_TRIMVALUE(trim_value);
167 }
168
169 /*!
170 \brief generate software reference source sync pulse
171 \param[in] none
172 \param[out] none
173 \retval none
174 */
ctc_software_refsource_pulse_generate(void)175 void ctc_software_refsource_pulse_generate(void)
176 {
177 CTC_CTL0 |= (uint32_t)CTC_CTL0_SWREFPUL;
178 }
179
180 /*!
181 \brief configure hardware automatically trim mode
182 \param[in] hardmode:
183 only one parameter can be selected which is shown as below:
184 \arg CTC_HARDWARE_TRIM_MODE_ENABLE: hardware automatically trim mode enable
185 \arg CTC_HARDWARE_TRIM_MODE_DISABLE: hardware automatically trim mode disable
186 \param[out] none
187 \retval none
188 */
ctc_hardware_trim_mode_config(uint32_t hardmode)189 void ctc_hardware_trim_mode_config(uint32_t hardmode)
190 {
191 CTC_CTL0 &= (uint32_t)(~CTC_CTL0_AUTOTRIM);
192 CTC_CTL0 |= (uint32_t)hardmode;
193 }
194
195 /*!
196 \brief read CTC counter capture value when reference sync pulse occurred
197 \param[in] none
198 \param[out] none
199 \retval the 16-bit CTC counter capture value
200 */
ctc_counter_capture_value_read(void)201 uint16_t ctc_counter_capture_value_read(void)
202 {
203 uint16_t capture_value = 0U;
204 capture_value = (uint16_t)GET_STAT_REFCAP(CTC_STAT);
205 return (capture_value);
206 }
207
208 /*!
209 \brief read CTC trim counter direction when reference sync pulse occurred
210 \param[in] none
211 \param[out] none
212 \retval FlagStatus: SET or RESET
213 \arg SET: CTC trim counter direction is down-counting
214 \arg RESET: CTC trim counter direction is up-counting
215 */
ctc_counter_direction_read(void)216 FlagStatus ctc_counter_direction_read(void)
217 {
218 FlagStatus ret_status = RESET;
219 if(RESET != (CTC_STAT & CTC_STAT_REFDIR)){
220 ret_status = SET;
221 }
222 return ret_status;
223 }
224
225 /*!
226 \brief read CTC counter reload value
227 \param[in] none
228 \param[out] none
229 \retval the 16-bit CTC counter reload value
230 */
ctc_counter_reload_value_read(void)231 uint16_t ctc_counter_reload_value_read(void)
232 {
233 uint16_t reload_value = 0U;
234 reload_value = (uint16_t)(CTC_CTL1 & CTC_CTL1_RLVALUE);
235 return (reload_value);
236 }
237
238 /*!
239 \brief read the IRC48M trim value
240 \param[in] none
241 \param[out] none
242 \retval the 8-bit IRC48M trim value
243 */
ctc_irc48m_trim_value_read(void)244 uint8_t ctc_irc48m_trim_value_read(void)
245 {
246 uint8_t trim_value = 0U;
247 trim_value = (uint8_t)GET_CTL0_TRIMVALUE(CTC_CTL0);
248 return (trim_value);
249 }
250
251 /*!
252 \brief enable the CTC interrupt
253 \param[in] interrupt: CTC interrupt enable
254 one or more parameters can be selected which are shown as below:
255 \arg CTC_INT_CKOK: clock trim OK interrupt enable
256 \arg CTC_INT_CKWARN: clock trim warning interrupt enable
257 \arg CTC_INT_ERR: error interrupt enable
258 \arg CTC_INT_EREF: expect reference interrupt enable
259 \param[out] none
260 \retval none
261 */
ctc_interrupt_enable(uint32_t interrupt)262 void ctc_interrupt_enable(uint32_t interrupt)
263 {
264 CTC_CTL0 |= (uint32_t)interrupt;
265 }
266
267 /*!
268 \brief disable the CTC interrupt
269 \param[in] interrupt: CTC interrupt enable source
270 one or more parameters can be selected which are shown as below:
271 \arg CTC_INT_CKOK: clock trim OK interrupt enable
272 \arg CTC_INT_CKWARN: clock trim warning interrupt enable
273 \arg CTC_INT_ERR: error interrupt enable
274 \arg CTC_INT_EREF: expect reference interrupt enable
275 \param[out] none
276 \retval none
277 */
ctc_interrupt_disable(uint32_t interrupt)278 void ctc_interrupt_disable(uint32_t interrupt)
279 {
280 CTC_CTL0 &= (uint32_t)(~(interrupt));
281 }
282
283 /*!
284 \brief get CTC flag
285 \param[in] flag: the CTC flag
286 only one parameter can be selected which is shown as below:
287 \arg CTC_FLAG_CKOK: clock trim OK flag
288 \arg CTC_FLAG_CKWARN: clock trim warning flag
289 \arg CTC_FLAG_ERR: error flag
290 \arg CTC_FLAG_EREF: expect reference flag
291 \arg CTC_FLAG_CKERR: clock trim error bit
292 \arg CTC_FLAG_REFMISS: reference sync pulse miss
293 \arg CTC_FLAG_TRIMERR: trim value error bit
294 \param[out] none
295 \retval FlagStatus: SET or RESET
296 */
ctc_flag_get(uint32_t flag)297 FlagStatus ctc_flag_get(uint32_t flag)
298 {
299 FlagStatus ret_status = RESET;
300
301 if(RESET != (CTC_STAT & flag)){
302 ret_status = SET;
303 }
304 return ret_status;
305 }
306
307 /*!
308 \brief clear CTC flag
309 \param[in] flag: the CTC flag
310 only one parameter can be selected which is shown as below:
311 \arg CTC_FLAG_CKOK: clock trim OK flag
312 \arg CTC_FLAG_CKWARN: clock trim warning flag
313 \arg CTC_FLAG_ERR: error flag
314 \arg CTC_FLAG_EREF: expect reference flag
315 \arg CTC_FLAG_CKERR: clock trim error bit
316 \arg CTC_FLAG_REFMISS: reference sync pulse miss
317 \arg CTC_FLAG_TRIMERR: trim value error bit
318 \param[out] none
319 \retval none
320 */
ctc_flag_clear(uint32_t flag)321 void ctc_flag_clear(uint32_t flag)
322 {
323 if(flag & CTC_FLAG_MASK){
324 CTC_INTC |= CTC_INTC_ERRIC;
325 }else{
326 CTC_INTC |= flag;
327 }
328 }
329
330 /*!
331 \brief get CTC interrupt flag
332 \param[in] interrupt: the CTC interrupt flag
333 only one parameter can be selected which is shown as below:
334 \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt
335 \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt
336 \arg CTC_INT_FLAG_ERR: error interrupt
337 \arg CTC_INT_FLAG_EREF: expect reference interrupt
338 \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt
339 \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt
340 \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt
341 \param[out] none
342 \retval FlagStatus: SET or RESET
343 */
ctc_interrupt_flag_get(uint32_t interrupt)344 FlagStatus ctc_interrupt_flag_get(uint32_t interrupt)
345 {
346 uint32_t ctc_int = 0U, intenable = 0U;
347 FlagStatus ret_status = RESET;
348
349 if(interrupt & CTC_FLAG_MASK){
350 intenable = CTC_CTL0 & CTC_INT_ERR;
351 }else{
352 intenable = CTC_CTL0 & interrupt;
353 }
354 ctc_int = CTC_STAT & interrupt;
355
356 if(ctc_int && intenable){
357 ret_status = SET;
358 }
359 return ret_status;
360 }
361
362 /*!
363 \brief clear CTC interrupt flag
364 \param[in] interrupt: the CTC interrupt flag
365 only one parameter can be selected which is shown as below:
366 \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt
367 \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt
368 \arg CTC_INT_FLAG_ERR: error interrupt
369 \arg CTC_INT_FLAG_EREF: expect reference interrupt
370 \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt
371 \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt
372 \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt
373 \param[out] none
374 \retval none
375 */
ctc_interrupt_flag_clear(uint32_t interrupt)376 void ctc_interrupt_flag_clear(uint32_t interrupt)
377 {
378 if(interrupt & CTC_FLAG_MASK){
379 CTC_INTC |= CTC_INTC_ERRIC;
380 }else{
381 CTC_INTC |= interrupt;
382 }
383 }
384