1 /*!
2 \file gd32e50x_ctc.c
3 \brief CTC driver
4
5 \version 2020-03-10, V1.0.0, firmware for GD32E50x
6 \version 2020-08-26, V1.1.0, firmware for GD32E50x
7 \version 2021-03-23, V1.2.0, firmware for GD32E50x
8 */
9
10 /*
11 Copyright (c) 2021, 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 "gd32e50x_ctc.h"
38
39 #define CTC_FLAG_MASK ((uint32_t)0x00000700U)
40
41 /* CTC register bit offset */
42 #define CTC_TRIMVALUE_OFFSET ((uint32_t)8U)
43 #define CTC_TRIM_VALUE_OFFSET ((uint32_t)8U)
44 #define CTC_REFCAP_OFFSET ((uint32_t)16U)
45 #define CTC_LIMIT_VALUE_OFFSET ((uint32_t)16U)
46
47 /*!
48 \brief reset CTC clock trim controller
49 \param[in] none
50 \param[out] none
51 \retval none
52 */
ctc_deinit(void)53 void ctc_deinit(void)
54 {
55 /* reset CTC */
56 rcu_periph_reset_enable(RCU_CTCRST);
57 rcu_periph_reset_disable(RCU_CTCRST);
58 }
59
60
61
62 /*!
63 \brief enable CTC trim counter
64 \param[in] none
65 \param[out] none
66 \retval none
67 */
ctc_counter_enable(void)68 void ctc_counter_enable(void)
69 {
70 CTC_CTL0 |= (uint32_t)CTC_CTL0_CNTEN;
71 }
72
73 /*!
74 \brief disable CTC trim counter
75 \param[in] none
76 \param[out] none
77 \retval none
78 */
ctc_counter_disable(void)79 void ctc_counter_disable(void)
80 {
81 CTC_CTL0 &= (uint32_t)(~CTC_CTL0_CNTEN);
82 }
83
84 /*!
85 \brief configure the IRC48M trim value
86 \param[in] ctc_trim_value: 8-bit IRC48M trim value
87 \arg 0x00 - 0x3F
88 \param[out] none
89 \retval none
90 */
ctc_irc48m_trim_value_config(uint8_t trim_value)91 void ctc_irc48m_trim_value_config(uint8_t trim_value)
92 {
93 /* clear TRIMVALUE bits */
94 CTC_CTL0 &= (~(uint32_t)CTC_CTL0_TRIMVALUE);
95 /* set TRIMVALUE bits */
96 CTC_CTL0 |= ((uint32_t)trim_value << CTC_TRIM_VALUE_OFFSET);
97 }
98
99 /*!
100 \brief generate software reference source sync pulse
101 \param[in] none
102 \param[out] none
103 \retval none
104 */
ctc_software_refsource_pulse_generate(void)105 void ctc_software_refsource_pulse_generate(void)
106 {
107 CTC_CTL0 |= (uint32_t)CTC_CTL0_SWREFPUL;
108 }
109
110 /*!
111 \brief configure hardware automatically trim mode
112 \param[in] hardmode:
113 only one parameter can be selected which is shown as below:
114 \arg CTC_HARDWARE_TRIM_MODE_ENABLE: hardware automatically trim mode enable
115 \arg CTC_HARDWARE_TRIM_MODE_DISABLE: hardware automatically trim mode disable
116 \param[out] none
117 \retval none
118 */
ctc_hardware_trim_mode_config(uint32_t hardmode)119 void ctc_hardware_trim_mode_config(uint32_t hardmode)
120 {
121 CTC_CTL0 &= (uint32_t)(~CTC_CTL0_AUTOTRIM);
122 CTC_CTL0 |= (uint32_t)hardmode;
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 reference signal source
141 \param[in] refs:
142 only one parameter can be selected which is shown as below:
143 \arg CTC_REFSOURCE_GPIO: GPIO is selected
144 \arg CTC_REFSOURCE_LXTAL: LXTAL is selected
145 \arg CTC_REFSOURCE_USB_SOF: USBD_SOF or USBHS_SOF is selected
146 \param[out] none
147 \retval none
148 */
ctc_refsource_signal_select(uint32_t refs)149 void ctc_refsource_signal_select(uint32_t refs)
150 {
151 CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL);
152 CTC_CTL1 |= (uint32_t)refs;
153 }
154
155 /*!
156 \brief configure reference signal source prescaler
157 \param[in] prescaler:
158 only one parameter can be selected which is shown as below:
159 \arg CTC_REFSOURCE_PSC_OFF: reference signal not divided
160 \arg CTC_REFSOURCE_PSC_DIV2: reference signal divided by 2
161 \arg CTC_REFSOURCE_PSC_DIV4: reference signal divided by 4
162 \arg CTC_REFSOURCE_PSC_DIV8: reference signal divided by 8
163 \arg CTC_REFSOURCE_PSC_DIV16: reference signal divided by 16
164 \arg CTC_REFSOURCE_PSC_DIV32: reference signal divided by 32
165 \arg CTC_REFSOURCE_PSC_DIV64: reference signal divided by 64
166 \arg CTC_REFSOURCE_PSC_DIV128: reference signal divided by 128
167 \param[out] none
168 \retval none
169 */
ctc_refsource_prescaler_config(uint32_t prescaler)170 void ctc_refsource_prescaler_config(uint32_t prescaler)
171 {
172 CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPSC);
173 CTC_CTL1 |= (uint32_t)prescaler;
174 }
175
176 /*!
177 \brief configure clock trim base limit value
178 \param[in] limit_value: 8-bit clock trim base limit value
179 \arg 0x00 - 0xFF
180 \param[out] none
181 \retval none
182 */
ctc_clock_limit_value_config(uint8_t limit_value)183 void ctc_clock_limit_value_config(uint8_t limit_value)
184 {
185 CTC_CTL1 &= (uint32_t)(~CTC_CTL1_CKLIM);
186 CTC_CTL1 |= (uint32_t)((uint32_t)limit_value << CTC_LIMIT_VALUE_OFFSET);
187 }
188
189 /*!
190 \brief configure CTC counter reload value
191 \param[in] reload_value: 16-bit CTC counter reload value
192 \arg 0x0000 - 0xFFFF
193 \param[out] none
194 \retval none
195 */
ctc_counter_reload_value_config(uint16_t reload_value)196 void ctc_counter_reload_value_config(uint16_t reload_value)
197 {
198 CTC_CTL1 &= (uint32_t)(~CTC_CTL1_RLVALUE);
199 CTC_CTL1 |= (uint32_t)reload_value;
200 }
201
202 /*!
203 \brief read CTC counter capture value when reference sync pulse occurred
204 \param[in] none
205 \param[out] none
206 \retval the 16-bit CTC counter capture value
207 */
ctc_counter_capture_value_read(void)208 uint16_t ctc_counter_capture_value_read(void)
209 {
210 uint16_t capture_value = 0U;
211 capture_value = (uint16_t)((CTC_STAT & CTC_STAT_REFCAP)>> CTC_REFCAP_OFFSET);
212 return (capture_value);
213 }
214
215 /*!
216 \brief read CTC trim counter direction when reference sync pulse occurred
217 \param[in] none
218 \param[out] none
219 \retval FlagStatus: SET or RESET
220 \arg SET: CTC trim counter direction is down-counting
221 \arg RESET: CTC trim counter direction is up-counting
222 */
ctc_counter_direction_read(void)223 FlagStatus ctc_counter_direction_read(void)
224 {
225 if(RESET != (CTC_STAT & CTC_STAT_REFDIR)){
226 return SET;
227 }else{
228 return RESET;
229 }
230 }
231
232 /*!
233 \brief read CTC counter reload value
234 \param[in] none
235 \param[out] none
236 \retval the 16-bit CTC counter reload value
237 */
ctc_counter_reload_value_read(void)238 uint16_t ctc_counter_reload_value_read(void)
239 {
240 uint16_t reload_value = 0U;
241 reload_value = (uint16_t)(CTC_CTL1 & CTC_CTL1_RLVALUE);
242 return (reload_value);
243 }
244
245 /*!
246 \brief read the IRC48M trim value
247 \param[in] none
248 \param[out] none
249 \retval the 8-bit IRC48M trim value
250 */
ctc_irc48m_trim_value_read(void)251 uint8_t ctc_irc48m_trim_value_read(void)
252 {
253 uint8_t trim_value = 0U;
254 trim_value = (uint8_t)((CTC_CTL0 & CTC_CTL0_TRIMVALUE) >> CTC_TRIMVALUE_OFFSET);
255 return (trim_value);
256 }
257
258 /*!
259 \brief get CTC flag
260 \param[in] flag: the CTC flag
261 only one parameter can be selected which is shown as below:
262 \arg CTC_FLAG_CKOK: clock trim OK flag
263 \arg CTC_FLAG_CKWARN: clock trim warning flag
264 \arg CTC_FLAG_ERR: error flag
265 \arg CTC_FLAG_EREF: expect reference flag
266 \arg CTC_FLAG_CKERR: clock trim error bit
267 \arg CTC_FLAG_REFMISS: reference sync pulse miss
268 \arg CTC_FLAG_TRIMERR: trim value error bit
269 \param[out] none
270 \retval FlagStatus: SET or RESET
271 */
ctc_flag_get(uint32_t flag)272 FlagStatus ctc_flag_get(uint32_t flag)
273 {
274 if(RESET != (CTC_STAT & flag)){
275 return SET;
276 }else{
277 return RESET;
278 }
279 }
280
281 /*!
282 \brief clear CTC flag
283 \param[in] flag: the CTC flag
284 only one parameter can be selected which is shown as below:
285 \arg CTC_FLAG_CKOK: clock trim OK flag
286 \arg CTC_FLAG_CKWARN: clock trim warning flag
287 \arg CTC_FLAG_ERR: error flag
288 \arg CTC_FLAG_EREF: expect reference flag
289 \arg CTC_FLAG_CKERR: clock trim error bit
290 \arg CTC_FLAG_REFMISS: reference sync pulse miss
291 \arg CTC_FLAG_TRIMERR: trim value error bit
292 \param[out] none
293 \retval none
294 */
ctc_flag_clear(uint32_t flag)295 void ctc_flag_clear(uint32_t flag)
296 {
297 if(RESET != (flag & CTC_FLAG_MASK)){
298 CTC_INTC |= CTC_INTC_ERRIC;
299 }else{
300 CTC_INTC |= flag;
301 }
302 }
303
304 /*!
305 \brief enable the CTC interrupt
306 \param[in] interrupt: CTC interrupt enable
307 one or more parameters can be selected which are shown as below:
308 \arg CTC_INT_CKOK: clock trim OK interrupt enable
309 \arg CTC_INT_CKWARN: clock trim warning interrupt enable
310 \arg CTC_INT_ERR: error interrupt enable
311 \arg CTC_INT_EREF: expect reference interrupt enable
312 \param[out] none
313 \retval none
314 */
ctc_interrupt_enable(uint32_t interrupt)315 void ctc_interrupt_enable(uint32_t interrupt)
316 {
317 CTC_CTL0 |= (uint32_t)interrupt;
318 }
319
320 /*!
321 \brief disable the CTC interrupt
322 \param[in] interrupt: CTC interrupt enable source
323 one or more parameters can be selected which are shown as below:
324 \arg CTC_INT_CKOK: clock trim OK interrupt enable
325 \arg CTC_INT_CKWARN: clock trim warning interrupt enable
326 \arg CTC_INT_ERR: error interrupt enable
327 \arg CTC_INT_EREF: expect reference interrupt enable
328 \param[out] none
329 \retval none
330 */
ctc_interrupt_disable(uint32_t interrupt)331 void ctc_interrupt_disable(uint32_t interrupt)
332 {
333 CTC_CTL0 &= (uint32_t)(~interrupt);
334 }
335
336 /*!
337 \brief get CTC interrupt flag
338 \param[in] int_flag: the CTC interrupt flag
339 only one parameter can be selected which is shown as below:
340 \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt
341 \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt
342 \arg CTC_INT_FLAG_ERR: error interrupt
343 \arg CTC_INT_FLAG_EREF: expect reference interrupt
344 \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt
345 \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt
346 \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt
347 \param[out] none
348 \retval FlagStatus: SET or RESET
349 */
ctc_interrupt_flag_get(uint32_t int_flag)350 FlagStatus ctc_interrupt_flag_get(uint32_t int_flag)
351 {
352 uint32_t interrupt_flag = 0U, intenable = 0U;
353
354 /* check whether the interrupt is enabled */
355 if(RESET != (int_flag & CTC_FLAG_MASK)){
356 intenable = CTC_CTL0 & CTC_CTL0_ERRIE;
357 }else{
358 intenable = CTC_CTL0 & int_flag;
359 }
360
361 /* get interrupt flag status */
362 interrupt_flag = CTC_STAT & int_flag;
363
364 if(interrupt_flag && intenable){
365 return SET;
366 }else{
367 return RESET;
368 }
369 }
370
371 /*!
372 \brief clear CTC interrupt flag
373 \param[in] int_flag: the CTC interrupt flag
374 only one parameter can be selected which is shown as below:
375 \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt
376 \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt
377 \arg CTC_INT_FLAG_ERR: error interrupt
378 \arg CTC_INT_FLAG_EREF: expect reference interrupt
379 \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt
380 \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt
381 \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt
382 \param[out] none
383 \retval none
384 */
ctc_interrupt_flag_clear(uint32_t int_flag)385 void ctc_interrupt_flag_clear(uint32_t int_flag)
386 {
387 if(RESET != (int_flag & CTC_FLAG_MASK)){
388 CTC_INTC |= CTC_INTC_ERRIC;
389 }else{
390 CTC_INTC |= int_flag;
391 }
392 }
393
394