1 /*!
2 \file gd32e10x_ctc.c
3 \brief CTC driver
4
5 \version 2017-12-26, V1.0.0, firmware for GD32E10x
6 \version 2020-09-30, V1.1.0, firmware for GD32E10x
7 \version 2020-12-31, V1.2.0, firmware for GD32E10x
8 \version 2022-06-30, V1.3.0, firmware for GD32E10x
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 "gd32e10x_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 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 \param[out] none
146 \retval none
147 */
ctc_refsource_signal_select(uint32_t refs)148 void ctc_refsource_signal_select(uint32_t refs)
149 {
150 CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFSEL);
151 CTC_CTL1 |= (uint32_t)refs;
152 }
153
154 /*!
155 \brief configure reference signal source prescaler
156 \param[in] prescaler:
157 only one parameter can be selected which is shown as below:
158 \arg CTC_REFSOURCE_PSC_OFF: reference signal not divided
159 \arg CTC_REFSOURCE_PSC_DIV2: reference signal divided by 2
160 \arg CTC_REFSOURCE_PSC_DIV4: reference signal divided by 4
161 \arg CTC_REFSOURCE_PSC_DIV8: reference signal divided by 8
162 \arg CTC_REFSOURCE_PSC_DIV16: reference signal divided by 16
163 \arg CTC_REFSOURCE_PSC_DIV32: reference signal divided by 32
164 \arg CTC_REFSOURCE_PSC_DIV64: reference signal divided by 64
165 \arg CTC_REFSOURCE_PSC_DIV128: reference signal divided by 128
166 \param[out] none
167 \retval none
168 */
ctc_refsource_prescaler_config(uint32_t prescaler)169 void ctc_refsource_prescaler_config(uint32_t prescaler)
170 {
171 CTC_CTL1 &= (uint32_t)(~CTC_CTL1_REFPSC);
172 CTC_CTL1 |= (uint32_t)prescaler;
173 }
174
175 /*!
176 \brief configure clock trim base limit value
177 \param[in] limit_value: 8-bit clock trim base limit value
178 \arg 0x00 - 0xFF
179 \param[out] none
180 \retval none
181 */
ctc_clock_limit_value_config(uint8_t limit_value)182 void ctc_clock_limit_value_config(uint8_t limit_value)
183 {
184 CTC_CTL1 &= (uint32_t)(~CTC_CTL1_CKLIM);
185 CTC_CTL1 |= (uint32_t)((uint32_t)limit_value << CTC_LIMIT_VALUE_OFFSET);
186 }
187
188 /*!
189 \brief configure CTC counter reload value
190 \param[in] reload_value: 16-bit CTC counter reload value
191 \arg 0x0000 - 0xFFFF
192 \param[out] none
193 \retval none
194 */
ctc_counter_reload_value_config(uint16_t reload_value)195 void ctc_counter_reload_value_config(uint16_t reload_value)
196 {
197 CTC_CTL1 &= (uint32_t)(~CTC_CTL1_RLVALUE);
198 CTC_CTL1 |= (uint32_t)reload_value;
199 }
200
201 /*!
202 \brief read CTC counter capture value when reference sync pulse occurred
203 \param[in] none
204 \param[out] none
205 \retval the 16-bit CTC counter capture value
206 */
ctc_counter_capture_value_read(void)207 uint16_t ctc_counter_capture_value_read(void)
208 {
209 uint16_t capture_value = 0U;
210 capture_value = (uint16_t)((CTC_STAT & CTC_STAT_REFCAP)>> CTC_REFCAP_OFFSET);
211 return (capture_value);
212 }
213
214 /*!
215 \brief read CTC trim counter direction when reference sync pulse occurred
216 \param[in] none
217 \param[out] none
218 \retval FlagStatus: SET or RESET
219 \arg SET: CTC trim counter direction is down-counting
220 \arg RESET: CTC trim counter direction is up-counting
221 */
ctc_counter_direction_read(void)222 FlagStatus ctc_counter_direction_read(void)
223 {
224 if(RESET != (CTC_STAT & CTC_STAT_REFDIR)){
225 return SET;
226 }else{
227 return RESET;
228 }
229 }
230
231 /*!
232 \brief read CTC counter reload value
233 \param[in] none
234 \param[out] none
235 \retval the 16-bit CTC counter reload value
236 */
ctc_counter_reload_value_read(void)237 uint16_t ctc_counter_reload_value_read(void)
238 {
239 uint16_t reload_value = 0U;
240 reload_value = (uint16_t)(CTC_CTL1 & CTC_CTL1_RLVALUE);
241 return (reload_value);
242 }
243
244 /*!
245 \brief read the IRC48M trim value
246 \param[in] none
247 \param[out] none
248 \retval the 8-bit IRC48M trim value
249 */
ctc_irc48m_trim_value_read(void)250 uint8_t ctc_irc48m_trim_value_read(void)
251 {
252 uint8_t trim_value = 0U;
253 trim_value = (uint8_t)((CTC_CTL0 & CTC_CTL0_TRIMVALUE) >> CTC_TRIMVALUE_OFFSET);
254 return (trim_value);
255 }
256
257 /*!
258 \brief enable the CTC interrupt
259 \param[in] interrupt: CTC interrupt enable
260 one or more parameters can be selected which are shown as below:
261 \arg CTC_INT_CKOK: clock trim OK interrupt enable
262 \arg CTC_INT_CKWARN: clock trim warning interrupt enable
263 \arg CTC_INT_ERR: error interrupt enable
264 \arg CTC_INT_EREF: expect reference interrupt enable
265 \param[out] none
266 \retval none
267 */
ctc_interrupt_enable(uint32_t interrupt)268 void ctc_interrupt_enable(uint32_t interrupt)
269 {
270 CTC_CTL0 |= (uint32_t)interrupt;
271 }
272
273 /*!
274 \brief disable the CTC interrupt
275 \param[in] interrupt: CTC interrupt enable source
276 one or more parameters can be selected which are shown as below:
277 \arg CTC_INT_CKOK: clock trim OK interrupt enable
278 \arg CTC_INT_CKWARN: clock trim warning interrupt enable
279 \arg CTC_INT_ERR: error interrupt enable
280 \arg CTC_INT_EREF: expect reference interrupt enable
281 \param[out] none
282 \retval none
283 */
ctc_interrupt_disable(uint32_t interrupt)284 void ctc_interrupt_disable(uint32_t interrupt)
285 {
286 CTC_CTL0 &= (uint32_t)(~interrupt);
287 }
288
289 /*!
290 \brief get CTC interrupt flag
291 \param[in] interrupt: the CTC interrupt flag
292 only one parameter can be selected which is shown as below:
293 \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt
294 \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt
295 \arg CTC_INT_FLAG_ERR: error interrupt
296 \arg CTC_INT_FLAG_EREF: expect reference interrupt
297 \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt
298 \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt
299 \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt
300 \param[out] none
301 \retval FlagStatus: SET or RESET
302 */
ctc_interrupt_flag_get(uint32_t interrupt)303 FlagStatus ctc_interrupt_flag_get(uint32_t interrupt)
304 {
305 uint32_t intflag = 0U, intenable = 0U;
306
307 /* check whether the interrupt is enabled */
308 if(RESET != (interrupt & CTC_FLAG_MASK)){
309 intenable = CTC_CTL0 & CTC_CTL0_ERRIE;
310 }else{
311 intenable = CTC_CTL0 & interrupt;
312 }
313
314 /* get interrupt flag status */
315 intflag = CTC_STAT & interrupt;
316
317 if(intflag && intenable){
318 return SET;
319 }else{
320 return RESET;
321 }
322 }
323
324 /*!
325 \brief clear CTC interrupt flag
326 \param[in] interrupt: the CTC interrupt flag
327 only one parameter can be selected which is shown as below:
328 \arg CTC_INT_FLAG_CKOK: clock trim OK interrupt
329 \arg CTC_INT_FLAG_CKWARN: clock trim warning interrupt
330 \arg CTC_INT_FLAG_ERR: error interrupt
331 \arg CTC_INT_FLAG_EREF: expect reference interrupt
332 \arg CTC_INT_FLAG_CKERR: clock trim error bit interrupt
333 \arg CTC_INT_FLAG_REFMISS: reference sync pulse miss interrupt
334 \arg CTC_INT_FLAG_TRIMERR: trim value error interrupt
335 \param[out] none
336 \retval none
337 */
ctc_interrupt_flag_clear(uint32_t interrupt)338 void ctc_interrupt_flag_clear(uint32_t interrupt)
339 {
340 if(RESET != (interrupt & CTC_FLAG_MASK)){
341 CTC_INTC |= CTC_INTC_ERRIC;
342 }else{
343 CTC_INTC |= interrupt;
344 }
345 }
346
347 /*!
348 \brief get CTC flag
349 \param[in] flag: the CTC flag
350 only one parameter can be selected which is shown as below:
351 \arg CTC_FLAG_CKOK: clock trim OK flag
352 \arg CTC_FLAG_CKWARN: clock trim warning flag
353 \arg CTC_FLAG_ERR: error flag
354 \arg CTC_FLAG_EREF: expect reference flag
355 \arg CTC_FLAG_CKERR: clock trim error bit
356 \arg CTC_FLAG_REFMISS: reference sync pulse miss
357 \arg CTC_FLAG_TRIMERR: trim value error bit
358 \param[out] none
359 \retval FlagStatus: SET or RESET
360 */
ctc_flag_get(uint32_t flag)361 FlagStatus ctc_flag_get(uint32_t flag)
362 {
363 if(RESET != (CTC_STAT & flag)){
364 return SET;
365 }else{
366 return RESET;
367 }
368 }
369
370 /*!
371 \brief clear CTC flag
372 \param[in] flag: the CTC flag
373 only one parameter can be selected which is shown as below:
374 \arg CTC_FLAG_CKOK: clock trim OK flag
375 \arg CTC_FLAG_CKWARN: clock trim warning flag
376 \arg CTC_FLAG_ERR: error flag
377 \arg CTC_FLAG_EREF: expect reference flag
378 \arg CTC_FLAG_CKERR: clock trim error bit
379 \arg CTC_FLAG_REFMISS: reference sync pulse miss
380 \arg CTC_FLAG_TRIMERR: trim value error bit
381 \param[out] none
382 \retval none
383 */
ctc_flag_clear(uint32_t flag)384 void ctc_flag_clear(uint32_t flag)
385 {
386 if(RESET != (flag & CTC_FLAG_MASK)){
387 CTC_INTC |= CTC_INTC_ERRIC;
388 }else{
389 CTC_INTC |= flag;
390 }
391 }
392