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