1 /*!
2 \file gd32e10x_rcu.c
3 \brief RCU 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 2021-05-31, V1.2.1, firmware for GD32E10x
9 \version 2022-06-30, V1.3.0, firmware for GD32E10x
10 */
11
12 /*
13 Copyright (c) 2022, GigaDevice Semiconductor Inc.
14
15 Redistribution and use in source and binary forms, with or without modification,
16 are permitted provided that the following conditions are met:
17
18 1. Redistributions of source code must retain the above copyright notice, this
19 list of conditions and the following disclaimer.
20 2. Redistributions in binary form must reproduce the above copyright notice,
21 this list of conditions and the following disclaimer in the documentation
22 and/or other materials provided with the distribution.
23 3. Neither the name of the copyright holder nor the names of its contributors
24 may be used to endorse or promote products derived from this software without
25 specific prior written permission.
26
27 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
31 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
36 OF SUCH DAMAGE.
37 */
38
39 #include "gd32e10x_rcu.h"
40
41 /* define clock source */
42 #define SEL_IRC8M ((uint16_t)0U) /* IRC8M is selected as CK_SYS */
43 #define SEL_HXTAL ((uint16_t)1U) /* HXTAL is selected as CK_SYS */
44 #define SEL_PLL ((uint16_t)2U) /* PLL is selected as CK_SYS */
45
46 /* define startup timeout count */
47 #define OSC_STARTUP_TIMEOUT ((uint32_t)0x000FFFFFU)
48 #define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x03FFFFFFU)
49
50 /* ADC clock prescaler offset */
51 #define RCU_ADC_PSC_OFFSET ((uint32_t)14U)
52
53 /* RCU IRC8M adjust value mask and offset*/
54 #define RCU_IRC8M_ADJUST_MASK ((uint8_t)0x1FU)
55 #define RCU_IRC8M_ADJUST_OFFSET ((uint32_t)3U)
56
57 /* RCU PLL1 clock multiplication factor offset */
58 #define RCU_CFG1_PLL1MF_OFFSET ((uint32_t)8U)
59 /* RCU PREDV1 division factor offset*/
60 #define RCU_CFG1_PREDV1_OFFSET ((uint32_t)4U)
61
62 /*!
63 \brief deinitialize the RCU
64 \param[in] none
65 \param[out] none
66 \retval none
67 */
rcu_deinit(void)68 void rcu_deinit(void)
69 {
70 /* enable IRC8M */
71 RCU_CTL |= RCU_CTL_IRC8MEN;
72 rcu_osci_stab_wait(RCU_IRC8M);
73
74 RCU_CFG0 &= ~RCU_CFG0_SCS;
75
76 /* reset HXTALEN, CKMEN, PLLEN bits */
77 RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN);
78
79 /* reset CFG0 register */
80 RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |
81 RCU_CFG0_ADCPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2);
82
83 /* reset HXTALBPS bit */
84 RCU_CTL &= ~RCU_CTL_HXTALBPS;
85 /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */
86 RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF |
87 RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4 | RCU_CFG0_USBFSPSC_2);
88 /* reset PLL1EN and PLL2EN bits */
89 RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN);
90
91 /* reset INT and CFG1 register */
92 RCU_INT = 0x00ff0000U;
93 RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF |
94 RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL | RCU_CFG1_ADCPSC_3 |
95 RCU_CFG1_PLLPRESEL);
96 }
97
98 /*!
99 \brief enable the peripherals clock
100 \param[in] periph: RCU peripherals, refer to rcu_periph_enum
101 only one parameter can be selected which is shown as below:
102 \arg RCU_GPIOx (x=A,B,C,D,E): GPIO ports clock
103 \arg RCU_AF : alternate function clock
104 \arg RCU_CRC: CRC clock
105 \arg RCU_DMAx (x=0,1): DMA clock
106 \arg RCU_USBFS: USBFS clock
107 \arg RCU_EXMC: EXMC clock
108 \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): TIMER clock
109 \arg RCU_WWDGT: WWDGT clock
110 \arg RCU_SPIx (x=0,1,2): SPI clock
111 \arg RCU_USARTx (x=0,1,2): USART clock
112 \arg RCU_UARTx (x=3,4): UART clock
113 \arg RCU_I2Cx (x=0,1): I2C clock
114 \arg RCU_PMU: PMU clock
115 \arg RCU_DAC: DAC clock
116 \arg RCU_RTC: RTC clock
117 \arg RCU_ADCx (x=0,1): ADC clock
118 \arg RCU_CTC: CTC clock
119 \arg RCU_BKPI: BKP interface clock
120 \param[out] none
121 \retval none
122 */
rcu_periph_clock_enable(rcu_periph_enum periph)123 void rcu_periph_clock_enable(rcu_periph_enum periph)
124 {
125 RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
126 }
127
128 /*!
129 \brief disable the peripherals clock
130 \param[in] periph: RCU peripherals, refer to rcu_periph_enum
131 only one parameter can be selected which is shown as below:
132 \arg RCU_GPIOx (x=A,B,C,D,E): GPIO ports clock
133 \arg RCU_AF: alternate function clock
134 \arg RCU_CRC: CRC clock
135 \arg RCU_DMAx (x=0,1): DMA clock
136 \arg RCU_USBFS: USBFS clock
137 \arg RCU_EXMC: EXMC clock
138 \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): TIMER clock
139 \arg RCU_WWDGT: WWDGT clock
140 \arg RCU_SPIx (x=0,1,2): SPI clock
141 \arg RCU_USARTx (x=0,1,2): USART clock
142 \arg RCU_UARTx (x=3,4): UART clock
143 \arg RCU_I2Cx (x=0,1): I2C clock
144 \arg RCU_PMU: PMU clock
145 \arg RCU_DAC: DAC clock
146 \arg RCU_RTC: RTC clock
147 \arg RCU_ADCx (x=0,1): ADC clock
148 \arg RCU_CTC: CTC clock
149 \arg RCU_BKPI: BKP interface clock
150 \param[out] none
151 \retval none
152 */
rcu_periph_clock_disable(rcu_periph_enum periph)153 void rcu_periph_clock_disable(rcu_periph_enum periph)
154 {
155 RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
156 }
157
158 /*!
159 \brief enable the peripherals clock when sleep mode
160 \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum
161 only one parameter can be selected which is shown as below:
162 \arg RCU_FMC_SLP: FMC clock
163 \arg RCU_SRAM_SLP: SRAM clock
164 \param[out] none
165 \retval none
166 */
rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)167 void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)
168 {
169 RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
170 }
171
172 /*!
173 \brief disable the peripherals clock when sleep mode
174 \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum
175 only one parameter can be selected which is shown as below:
176 \arg RCU_FMC_SLP: FMC clock
177 \arg RCU_SRAM_SLP: SRAM clock
178 \param[out] none
179 \retval none
180 */
rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)181 void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)
182 {
183 RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
184 }
185
186 /*!
187 \brief reset the peripherals
188 \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
189 only one parameter can be selected which is shown as below:
190 \arg RCU_GPIOxRST (x=A,B,C,D,E): reset GPIO ports
191 \arg RCU_AFRST : reset alternate function clock
192 \arg RCU_USBFSRST: reset USBFS
193 \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): reset TIMER
194 \arg RCU_WWDGTRST: reset WWDGT
195 \arg RCU_SPIxRST (x=0,1,2): reset SPI
196 \arg RCU_USARTxRST (x=0,1,2): reset USART
197 \arg RCU_UARTxRST (x=3,4): reset UART
198 \arg RCU_I2CxRST (x=0,1): reset I2C
199 \arg RCU_PMURST: reset PMU
200 \arg RCU_DACRST: reset DAC
201 \arg RCU_ADCxRST (x=0,1): reset ADC
202 \arg RCU_CTCRST: reset CTC
203 \arg RCU_BKPIRST: reset BKPI
204 \param[out] none
205 \retval none
206 */
rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)207 void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)
208 {
209 RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset));
210 }
211
212 /*!
213 \brief disable reset the peripheral
214 \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
215 only one parameter can be selected which is shown as below:
216 \arg RCU_GPIOxRST (x=A,B,C,D,E): reset GPIO ports
217 \arg RCU_AFRST : reset alternate function clock
218 \arg RCU_USBFSRST: reset USBFS
219 \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): reset TIMER
220 \arg RCU_WWDGTRST: reset WWDGT
221 \arg RCU_SPIxRST (x=0,1,2): reset SPI
222 \arg RCU_USARTxRST (x=0,1,2): reset USART
223 \arg RCU_UARTxRST (x=3,4): reset UART
224 \arg RCU_I2CxRST (x=0,1): reset I2C
225 \arg RCU_PMURST: reset PMU
226 \arg RCU_DACRST: reset DAC
227 \arg RCU_ADCxRST (x=0,1): reset ADC
228 \arg RCU_CTCRST: reset CTC
229 \arg RCU_BKPIRST: reset BKPI
230 \param[out] none
231 \retval none
232 */
rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset)233 void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset)
234 {
235 RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset));
236 }
237
238 /*!
239 \brief reset the BKP domain
240 \param[in] none
241 \param[out] none
242 \retval none
243 */
rcu_bkp_reset_enable(void)244 void rcu_bkp_reset_enable(void)
245 {
246 RCU_BDCTL |= RCU_BDCTL_BKPRST;
247 }
248
249 /*!
250 \brief disable the BKP domain reset
251 \param[in] none
252 \param[out] none
253 \retval none
254 */
rcu_bkp_reset_disable(void)255 void rcu_bkp_reset_disable(void)
256 {
257 RCU_BDCTL &= ~RCU_BDCTL_BKPRST;
258 }
259
260 /*!
261 \brief configure the system clock source
262 \param[in] ck_sys: system clock source select
263 only one parameter can be selected which is shown as below:
264 \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source
265 \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source
266 \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source
267 \param[out] none
268 \retval none
269 */
rcu_system_clock_source_config(uint32_t ck_sys)270 void rcu_system_clock_source_config(uint32_t ck_sys)
271 {
272 uint32_t reg;
273
274 reg = RCU_CFG0;
275 /* reset the SCS bits and set according to ck_sys */
276 reg &= ~RCU_CFG0_SCS;
277 RCU_CFG0 = (reg | ck_sys);
278 }
279
280 /*!
281 \brief get the system clock source
282 \param[in] none
283 \param[out] none
284 \retval which clock is selected as CK_SYS source
285 \arg RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source
286 \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source
287 \arg RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source
288 */
rcu_system_clock_source_get(void)289 uint32_t rcu_system_clock_source_get(void)
290 {
291 return (RCU_CFG0 & RCU_CFG0_SCSS);
292 }
293
294 /*!
295 \brief configure the AHB clock prescaler selection
296 \param[in] ck_ahb: AHB clock prescaler selection
297 only one parameter can be selected which is shown as below:
298 \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512
299 \param[out] none
300 \retval none
301 */
rcu_ahb_clock_config(uint32_t ck_ahb)302 void rcu_ahb_clock_config(uint32_t ck_ahb)
303 {
304 uint32_t reg;
305
306 reg = RCU_CFG0;
307
308 /* reset the AHBPSC bits and set according to ck_ahb */
309 reg &= ~RCU_CFG0_AHBPSC;
310 RCU_CFG0 = (reg | ck_ahb);
311 }
312
313 /*!
314 \brief configure the APB1 clock prescaler selection
315 \param[in] ck_apb1: APB1 clock prescaler selection
316 only one parameter can be selected which is shown as below:
317 \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1
318 \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1
319 \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1
320 \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1
321 \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1
322 \param[out] none
323 \retval none
324 */
rcu_apb1_clock_config(uint32_t ck_apb1)325 void rcu_apb1_clock_config(uint32_t ck_apb1)
326 {
327 uint32_t reg;
328
329 reg = RCU_CFG0;
330
331 /* reset the APB1PSC and set according to ck_apb1 */
332 reg &= ~RCU_CFG0_APB1PSC;
333 RCU_CFG0 = (reg | ck_apb1);
334 }
335
336 /*!
337 \brief configure the APB2 clock prescaler selection
338 \param[in] ck_apb2: APB2 clock prescaler selection
339 only one parameter can be selected which is shown as below:
340 \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2
341 \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2
342 \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2
343 \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2
344 \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2
345 \param[out] none
346 \retval none
347 */
rcu_apb2_clock_config(uint32_t ck_apb2)348 void rcu_apb2_clock_config(uint32_t ck_apb2)
349 {
350 uint32_t reg;
351
352 reg = RCU_CFG0;
353
354 /* reset the APB2PSC and set according to ck_apb2 */
355 reg &= ~RCU_CFG0_APB2PSC;
356 RCU_CFG0 = (reg | ck_apb2);
357 }
358
359 /*!
360 \brief configure the CK_OUT0 clock source
361 \param[in] ckout0_src: CK_OUT0 clock source selection
362 only one parameter can be selected which is shown as below:
363 \arg RCU_CKOUT0SRC_NONE: no clock selected
364 \arg RCU_CKOUT0SRC_CKSYS: system clock selected
365 \arg RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected
366 \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected
367 \arg RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected
368 \arg RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected
369 \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected
370 \arg RCU_CKOUT0SRC_CKPLL2: PLL2 selected
371 \arg RCU_CKOUT0SRC_IRC48M: IRC48M selected
372 \arg RCU_CKOUT0SRC_IRC48M_DIV8: IRC48M/8 selected
373 \param[out] none
374 \retval none
375 */
rcu_ckout0_config(uint32_t ckout0_src)376 void rcu_ckout0_config(uint32_t ckout0_src)
377 {
378 uint32_t reg;
379
380 reg = RCU_CFG0;
381
382 /* reset the CKOUT0SRC, set according to ckout0_src */
383 reg &= ~RCU_CFG0_CKOUT0SEL;
384 RCU_CFG0 = (reg | ckout0_src);
385 }
386
387 /*!
388 \brief configure the main PLL clock
389 \param[in] pll_src: PLL clock source selection
390 only one parameter can be selected which is shown as below:
391 \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL
392 \arg RCU_PLLSRC_HXTAL_IRC48M: HXTAL or IRC48M selected as source clock of PLL
393 \param[in] pll_mul: PLL clock multiplication factor
394 only one parameter can be selected which is shown as below:
395 \arg RCU_PLL_MULx (x = 2..14, 16..31, 6.5)
396 \param[out] none
397 \retval none
398 */
rcu_pll_config(uint32_t pll_src,uint32_t pll_mul)399 void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul)
400 {
401 uint32_t reg = 0U;
402
403 reg = RCU_CFG0;
404
405 /* PLL clock source and multiplication factor configuration */
406 reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
407 reg |= (pll_src | pll_mul);
408
409 RCU_CFG0 = reg;
410 }
411
412 /*!
413 \brief configure the PLL clock source preselection
414 \param[in] pll_presel: PLL clock source preselection
415 only one parameter can be selected which is shown as below:
416 \arg RCU_PLLPRESRC_HXTAL: HXTAL selected as PLL source clock
417 \arg RCU_PLLPRESRC_IRC48M: CK_PLL selected as PREDV0 input source clock
418 \param[out] none
419 \retval none
420 */
rcu_pllpresel_config(uint32_t pll_presel)421 void rcu_pllpresel_config(uint32_t pll_presel)
422 {
423 uint32_t reg = 0U;
424
425 reg = RCU_CFG1;
426
427 /* PLL clock source preselection */
428 reg &= ~RCU_CFG1_PLLPRESEL;
429 reg |= pll_presel;
430
431 RCU_CFG1 = reg;
432 }
433
434 /*!
435 \brief configure the PREDV0 division factor and clock source
436 \param[in] predv0_source: PREDV0 input clock source selection
437 only one parameter can be selected which is shown as below:
438 \arg RCU_PREDV0SRC_HXTAL_IRC48M: HXTAL or IRC48M selected as PREDV0 input source clock
439 \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock
440 \param[in] predv0_div: PREDV0 division factor
441 only one parameter can be selected which is shown as below:
442 \arg RCU_PREDV0_DIVx, x = 1..16
443 \param[out] none
444 \retval none
445 */
rcu_predv0_config(uint32_t predv0_source,uint32_t predv0_div)446 void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div)
447 {
448 uint32_t reg = 0U;
449
450 reg = RCU_CFG1;
451 /* reset PREDV0SEL and PREDV0 bits */
452 reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0);
453 /* set the PREDV0SEL and PREDV0 division factor */
454 reg |= (predv0_source | predv0_div);
455
456 RCU_CFG1 = reg;
457 }
458
459 /*!
460 \brief configure the PREDV1 division factor
461 \param[in] predv1_div: PREDV1 division factor
462 only one parameter can be selected which is shown as below:
463 \arg RCU_PREDV1_DIVx, x = 1..16
464 \param[out] none
465 \retval none
466 */
rcu_predv1_config(uint32_t predv1_div)467 void rcu_predv1_config(uint32_t predv1_div)
468 {
469 uint32_t reg = 0U;
470
471 reg = RCU_CFG1;
472 /* reset the PREDV1 bits */
473 reg &= ~RCU_CFG1_PREDV1;
474 /* set the PREDV1 division factor */
475 reg |= predv1_div;
476
477 RCU_CFG1 = reg;
478 }
479
480 /*!
481 \brief configure the PLL1 clock
482 \param[in] pll_mul: PLL clock multiplication factor
483 only one parameter can be selected which is shown as below:
484 \arg RCU_PLL1_MULx (x = 8..16, 20)
485 \param[out] none
486 \retval none
487 */
rcu_pll1_config(uint32_t pll_mul)488 void rcu_pll1_config(uint32_t pll_mul)
489 {
490 RCU_CFG1 &= ~RCU_CFG1_PLL1MF;
491 RCU_CFG1 |= pll_mul;
492 }
493
494 /*!
495 \brief configure the PLL2 clock
496 \param[in] pll_mul: PLL clock multiplication factor
497 only one parameter can be selected which is shown as below:
498 \arg RCU_PLL2_MULx (x = 8..16, 20)
499 \param[out] none
500 \retval none
501 */
rcu_pll2_config(uint32_t pll_mul)502 void rcu_pll2_config(uint32_t pll_mul)
503 {
504 RCU_CFG1 &= ~RCU_CFG1_PLL2MF;
505 RCU_CFG1 |= pll_mul;
506 }
507
508 /*!
509 \brief configure the ADC prescaler factor
510 \param[in] adc_psc: ADC prescaler factor
511 only one parameter can be selected which is shown as below:
512 \arg RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2/2
513 \arg RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2/4
514 \arg RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2/6
515 \arg RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2/8
516 \arg RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2/12
517 \arg RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2/16
518 \arg RCU_CKADC_CKAHB_DIV3: ADC prescaler select CK_AHB/3
519 \arg RCU_CKADC_CKAHB_DIV5: ADC prescaler select CK_AHB/5
520 \arg RCU_CKADC_CKAHB_DIV7: ADC prescaler select CK_AHB/7
521 \arg RCU_CKADC_CKAHB_DIV9: ADC prescaler select CK_AHB/9
522 \param[out] none
523 \retval none
524 */
rcu_adc_clock_config(uint32_t adc_psc)525 void rcu_adc_clock_config(uint32_t adc_psc)
526 {
527 uint32_t reg0,reg1;
528
529 /* reset the ADCPSC bits */
530 reg0 = RCU_CFG0;
531 reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC);
532 reg1 = RCU_CFG1;
533 reg1 &= ~RCU_CFG1_ADCPSC_3;
534
535 /* set the ADC prescaler factor */
536 switch(adc_psc){
537 case RCU_CKADC_CKAPB2_DIV2:
538 case RCU_CKADC_CKAPB2_DIV4:
539 case RCU_CKADC_CKAPB2_DIV6:
540 case RCU_CKADC_CKAPB2_DIV8:
541 reg0 |= (adc_psc << RCU_ADC_PSC_OFFSET);
542 break;
543
544 case RCU_CKADC_CKAPB2_DIV12:
545 case RCU_CKADC_CKAPB2_DIV16:
546 adc_psc &= ~BIT(2);
547 reg0 |= ((adc_psc << RCU_ADC_PSC_OFFSET) | RCU_CFG0_ADCPSC_2);
548 break;
549
550 case RCU_CKADC_CKAHB_DIV3:
551 case RCU_CKADC_CKAHB_DIV5:
552 case RCU_CKADC_CKAHB_DIV7:
553 case RCU_CKADC_CKAHB_DIV9:
554 adc_psc &= ~BITS(2,3);
555 reg0 |= (adc_psc << RCU_ADC_PSC_OFFSET);
556 reg1 |= RCU_CFG1_ADCPSC_3;
557 break;
558
559 default:
560 break;
561 }
562
563 /* set the register */
564 RCU_CFG0 = reg0;
565 RCU_CFG1 = reg1;
566 }
567
568 /*!
569 \brief configure the USBFS prescaler factor
570 \param[in] adc_div: USB prescaler factor
571 only one parameter can be selected which is shown as below:
572 \arg RCU_CKUSB_CKPLL_DIV1_5: USBFS prescaler select CK_PLL/1.5
573 \arg RCU_CKUSB_CKPLL_DIV1: USBFS prescaler select CK_PLL/1
574 \arg RCU_CKUSB_CKPLL_DIV2_5: USBFS prescaler select CK_PLL/2.5
575 \arg RCU_CKUSB_CKPLL_DIV2: USBFS prescaler select CK_PLL/2
576 \arg RCU_CKUSB_CKPLL_DIV3: USBFS prescaler select CK_PLL/3
577 \arg RCU_CKUSB_CKPLL_DIV3_5: USBFS prescaler select CK_PLL/3.5
578 \arg RCU_CKUSB_CKPLL_DIV4: USBFS prescaler select CK_PLL/4
579 \param[out] none
580 \retval none
581 */
rcu_usb_clock_config(uint32_t usb_psc)582 void rcu_usb_clock_config(uint32_t usb_psc)
583 {
584 uint32_t reg;
585
586 reg = RCU_CFG0;
587
588 /* configure the USBFS prescaler factor */
589 reg &= ~RCU_CFG0_USBFSPSC;
590
591 RCU_CFG0 = (reg | usb_psc);
592 }
593
594 /*!
595 \brief configure the RTC clock source selection
596 \param[in] rtc_clock_source: RTC clock source selection
597 only one parameter can be selected which is shown as below:
598 \arg RCU_RTCSRC_NONE: no clock selected
599 \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock
600 \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock
601 \arg RCU_RTCSRC_HXTAL_DIV_128: CK_HXTAL/128 selected as RTC source clock
602 \param[out] none
603 \retval none
604 */
rcu_rtc_clock_config(uint32_t rtc_clock_source)605 void rcu_rtc_clock_config(uint32_t rtc_clock_source)
606 {
607 uint32_t reg;
608
609 reg = RCU_BDCTL;
610 /* reset the RTCSRC bits and set according to rtc_clock_source */
611 reg &= ~RCU_BDCTL_RTCSRC;
612 RCU_BDCTL = (reg | rtc_clock_source);
613 }
614
615 /*!
616 \brief configure the I2S1 clock source selection
617 \param[in] i2s_clock_source: I2S1 clock source selection
618 only one parameter can be selected which is shown as below:
619 \arg RCU_I2S1SRC_CKSYS: system clock selected as I2S1 source clock
620 \arg RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S1 source clock
621 \param[out] none
622 \retval none
623 */
rcu_i2s1_clock_config(uint32_t i2s_clock_source)624 void rcu_i2s1_clock_config(uint32_t i2s_clock_source)
625 {
626 uint32_t reg;
627
628 reg = RCU_CFG1;
629 /* reset the I2S1SEL bit and set according to i2s_clock_source */
630 reg &= ~RCU_CFG1_I2S1SEL;
631 RCU_CFG1 = (reg | i2s_clock_source);
632 }
633
634 /*!
635 \brief configure the I2S2 clock source selection
636 \param[in] i2s_clock_source: I2S2 clock source selection
637 only one parameter can be selected which is shown as below:
638 \arg RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock
639 \arg RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S2 source clock
640 \param[out] none
641 \retval none
642 */
rcu_i2s2_clock_config(uint32_t i2s_clock_source)643 void rcu_i2s2_clock_config(uint32_t i2s_clock_source)
644 {
645 uint32_t reg;
646
647 reg = RCU_CFG1;
648 /* reset the I2S2SEL bit and set according to i2s_clock_source */
649 reg &= ~RCU_CFG1_I2S2SEL;
650 RCU_CFG1 = (reg | i2s_clock_source);
651 }
652
653 /*!
654 \brief configure the CK48M clock source selection
655 \param[in] ck48m_clock_source: CK48M clock source selection
656 only one parameter can be selected which is shown as below:
657 \arg RCU_CK48MSRC_CKPLL: CK_PLL selected as CK48M source clock
658 \arg RCU_CK48MSRC_IRC48M: CK_IRC48M selected as CK48M source clock
659 \param[out] none
660 \retval none
661 */
rcu_ck48m_clock_config(uint32_t ck48m_clock_source)662 void rcu_ck48m_clock_config(uint32_t ck48m_clock_source)
663 {
664 uint32_t reg;
665
666 reg = RCU_ADDCTL;
667 /* reset the CK48MSEL bit and set according to ck48m_clock_source */
668 reg &= ~RCU_ADDCTL_CK48MSEL;
669 RCU_ADDCTL = (reg | ck48m_clock_source);
670 }
671
672 /*!
673 \brief get the clock stabilization and peripheral reset flags
674 \param[in] flag: the clock stabilization and peripheral reset flags, refer to rcu_flag_enum
675 only one parameter can be selected which is shown as below:
676 \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag
677 \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag
678 \arg RCU_FLAG_PLLSTB: PLL stabilization flag
679 \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag
680 \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag
681 \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag
682 \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag
683 \arg RCU_FLAG_IRC48MSTB: IRC48M stabilization flag
684 \arg RCU_FLAG_EPRST: external PIN reset flag
685 \arg RCU_FLAG_PORRST: power reset flag
686 \arg RCU_FLAG_SWRST: software reset flag
687 \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag
688 \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag
689 \arg RCU_FLAG_LPRST: low-power reset flag
690 \param[out] none
691 \retval none
692 */
rcu_flag_get(rcu_flag_enum flag)693 FlagStatus rcu_flag_get(rcu_flag_enum flag)
694 {
695 /* get the rcu flag */
696 if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){
697 return SET;
698 }else{
699 return RESET;
700 }
701 }
702
703 /*!
704 \brief clear all the reset flag
705 \param[in] none
706 \param[out] none
707 \retval none
708 */
rcu_all_reset_flag_clear(void)709 void rcu_all_reset_flag_clear(void)
710 {
711 RCU_RSTSCK |= RCU_RSTSCK_RSTFC;
712 }
713
714 /*!
715 \brief get the clock stabilization interrupt and ckm flags
716 \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum
717 only one parameter can be selected which is shown as below:
718 \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag
719 \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag
720 \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag
721 \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag
722 \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag
723 \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag
724 \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag
725 \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag
726 \arg RCU_INT_FLAG_IRC48MSTB: IRC48M stabilization interrupt flag
727 \param[out] none
728 \retval FlagStatus: SET or RESET
729 */
rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)730 FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)
731 {
732 /* get the rcu interrupt flag */
733 if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){
734 return SET;
735 }else{
736 return RESET;
737 }
738 }
739
740 /*!
741 \brief clear the interrupt flags
742 \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum
743 only one parameter can be selected which is shown as below:
744 \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear
745 \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear
746 \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear
747 \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear
748 \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear
749 \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear
750 \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear
751 \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear
752 \arg RCU_INT_FLAG_IRC48MSTB_CLR: IRC48M stabilization interrupt flag clear
753 \param[out] none
754 \retval none
755 */
rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear)756 void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear)
757 {
758 RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear));
759 }
760
761 /*!
762 \brief enable the stabilization interrupt
763 \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum
764 only one parameter can be selected which is shown as below:
765 \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable
766 \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
767 \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable
768 \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
769 \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable
770 \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable
771 \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable
772 \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable
773 \param[out] none
774 \retval none
775 */
rcu_interrupt_enable(rcu_int_enum stab_int)776 void rcu_interrupt_enable(rcu_int_enum stab_int)
777 {
778 RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int));
779 }
780
781 /*!
782 \brief disable the stabilization interrupt
783 \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum
784 only one parameter can be selected which is shown as below:
785 \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable
786 \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
787 \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable
788 \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
789 \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable
790 \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable
791 \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable
792 \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable
793 \param[out] none
794 \retval none
795 */
rcu_interrupt_disable(rcu_int_enum stab_int)796 void rcu_interrupt_disable(rcu_int_enum stab_int)
797 {
798 RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int));
799 }
800
801 /*!
802 \brief configure the LXTAL drive capability
803 \param[in] lxtal_dricap: drive capability of LXTAL
804 only one parameter can be selected which is shown as below:
805 \arg RCU_LXTAL_LOWDRI: lower driving capability
806 \arg RCU_LXTAL_MED_LOWDRI: medium low driving capability
807 \arg RCU_LXTAL_MED_HIGHDRI: medium high driving capability
808 \arg RCU_LXTAL_HIGHDRI: higher driving capability
809 \param[out] none
810 \retval none
811 */
rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap)812 void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap)
813 {
814 uint32_t reg;
815
816 reg = RCU_BDCTL;
817
818 /* reset the LXTALDRI bits and set according to lxtal_dricap */
819 reg &= ~RCU_BDCTL_LXTALDRI;
820 RCU_BDCTL = (reg | lxtal_dricap);
821 }
822
823 /*!
824 \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout
825 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
826 only one parameter can be selected which is shown as below:
827 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
828 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
829 \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M)
830 \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M)
831 \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K)
832 \arg RCU_PLL_CK: phase locked loop(PLL)
833 \arg RCU_PLL1_CK: phase locked loop 1
834 \arg RCU_PLL2_CK: phase locked loop 2
835 \param[out] none
836 \retval ErrStatus: SUCCESS or ERROR
837 */
rcu_osci_stab_wait(rcu_osci_type_enum osci)838 ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci)
839 {
840 uint32_t stb_cnt = 0U;
841 ErrStatus reval = ERROR;
842 FlagStatus osci_stat = RESET;
843
844 switch(osci){
845 /* wait HXTAL stable */
846 case RCU_HXTAL:
847 while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){
848 osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB);
849 stb_cnt++;
850 }
851
852 /* check whether flag is set or not */
853 if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){
854 reval = SUCCESS;
855 }
856 break;
857
858 /* wait LXTAL stable */
859 case RCU_LXTAL:
860 while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){
861 osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB);
862 stb_cnt++;
863 }
864
865 /* check whether flag is set or not */
866 if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){
867 reval = SUCCESS;
868 }
869 break;
870
871 /* wait IRC8M stable */
872 case RCU_IRC8M:
873 while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){
874 osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB);
875 stb_cnt++;
876 }
877
878 /* check whether flag is set or not */
879 if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){
880 reval = SUCCESS;
881 }
882 break;
883
884 /* wait IRC48M stable */
885 case RCU_IRC48M:
886 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
887 osci_stat = rcu_flag_get(RCU_FLAG_IRC48MSTB);
888 stb_cnt++;
889 }
890
891 /* check whether flag is set or not */
892 if (RESET != rcu_flag_get(RCU_FLAG_IRC48MSTB)){
893 reval = SUCCESS;
894 }
895 break;
896
897 /* wait IRC40K stable */
898 case RCU_IRC40K:
899 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
900 osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB);
901 stb_cnt++;
902 }
903
904 /* check whether flag is set or not */
905 if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){
906 reval = SUCCESS;
907 }
908 break;
909
910 /* wait PLL stable */
911 case RCU_PLL_CK:
912 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
913 osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB);
914 stb_cnt++;
915 }
916
917 /* check whether flag is set or not */
918 if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){
919 reval = SUCCESS;
920 }
921 break;
922
923 /* wait PLL1 stable */
924 case RCU_PLL1_CK:
925 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
926 osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB);
927 stb_cnt++;
928 }
929
930 /* check whether flag is set or not */
931 if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){
932 reval = SUCCESS;
933 }
934 break;
935 /* wait PLL2 stable */
936 case RCU_PLL2_CK:
937 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
938 osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB);
939 stb_cnt++;
940 }
941
942 /* check whether flag is set or not */
943 if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){
944 reval = SUCCESS;
945 }
946 break;
947
948 default:
949 break;
950 }
951
952 /* return value */
953 return reval;
954 }
955
956 /*!
957 \brief turn on the oscillator
958 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
959 only one parameter can be selected which is shown as below:
960 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
961 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
962 \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M)
963 \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M)
964 \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K)
965 \arg RCU_PLL_CK: phase locked loop(PLL)
966 \arg RCU_PLL1_CK: phase locked loop 1
967 \arg RCU_PLL2_CK: phase locked loop 2
968 \param[out] none
969 \retval none
970 */
rcu_osci_on(rcu_osci_type_enum osci)971 void rcu_osci_on(rcu_osci_type_enum osci)
972 {
973 RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci));
974 }
975
976 /*!
977 \brief turn off the oscillator
978 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
979 only one parameter can be selected which is shown as below:
980 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
981 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
982 \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M)
983 \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M)
984 \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K)
985 \arg RCU_PLL_CK: phase locked loop(PLL)
986 \arg RCU_PLL1_CK: phase locked loop 1
987 \arg RCU_PLL2_CK: phase locked loop 2
988 \param[out] none
989 \retval none
990 */
rcu_osci_off(rcu_osci_type_enum osci)991 void rcu_osci_off(rcu_osci_type_enum osci)
992 {
993 RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci));
994 }
995
996 /*!
997 \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
998 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
999 only one parameter can be selected which is shown as below:
1000 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
1001 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
1002 \param[out] none
1003 \retval none
1004 */
rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)1005 void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)
1006 {
1007 uint32_t reg;
1008
1009 switch(osci){
1010 /* enable HXTAL to bypass mode */
1011 case RCU_HXTAL:
1012 reg = RCU_CTL;
1013 RCU_CTL &= ~RCU_CTL_HXTALEN;
1014 RCU_CTL = (reg | RCU_CTL_HXTALBPS);
1015 break;
1016 /* enable LXTAL to bypass mode */
1017 case RCU_LXTAL:
1018 reg = RCU_BDCTL;
1019 RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
1020 RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS);
1021 break;
1022 case RCU_IRC8M:
1023 case RCU_IRC48M:
1024 case RCU_IRC40K:
1025 case RCU_PLL_CK:
1026 case RCU_PLL1_CK:
1027 case RCU_PLL2_CK:
1028 break;
1029 default:
1030 break;
1031 }
1032 }
1033
1034 /*!
1035 \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
1036 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
1037 only one parameter can be selected which is shown as below:
1038 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
1039 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
1040 \param[out] none
1041 \retval none
1042 */
rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)1043 void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)
1044 {
1045 uint32_t reg;
1046
1047 switch(osci){
1048 /* disable HXTAL to bypass mode */
1049 case RCU_HXTAL:
1050 reg = RCU_CTL;
1051 RCU_CTL &= ~RCU_CTL_HXTALEN;
1052 RCU_CTL = (reg & ~RCU_CTL_HXTALBPS);
1053 break;
1054 /* disable LXTAL to bypass mode */
1055 case RCU_LXTAL:
1056 reg = RCU_BDCTL;
1057 RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
1058 RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS);
1059 break;
1060 case RCU_IRC8M:
1061 case RCU_IRC48M:
1062 case RCU_IRC40K:
1063 case RCU_PLL_CK:
1064 case RCU_PLL1_CK:
1065 case RCU_PLL2_CK:
1066 break;
1067 default:
1068 break;
1069 }
1070 }
1071
1072 /*!
1073 \brief enable the HXTAL clock monitor
1074 \param[in] none
1075 \param[out] none
1076 \retval none
1077 */
1078
rcu_hxtal_clock_monitor_enable(void)1079 void rcu_hxtal_clock_monitor_enable(void)
1080 {
1081 RCU_CTL |= RCU_CTL_CKMEN;
1082 }
1083
1084 /*!
1085 \brief disable the HXTAL clock monitor
1086 \param[in] none
1087 \param[out] none
1088 \retval none
1089 */
rcu_hxtal_clock_monitor_disable(void)1090 void rcu_hxtal_clock_monitor_disable(void)
1091 {
1092 RCU_CTL &= ~RCU_CTL_CKMEN;
1093 }
1094
1095 /*!
1096 \brief set the IRC8M adjust value
1097 \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F
1098 \arg 0x00 - 0x1F
1099 \param[out] none
1100 \retval none
1101 */
rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval)1102 void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval)
1103 {
1104 uint32_t reg;
1105
1106 reg = RCU_CTL;
1107 /* reset the IRC8MADJ bits and set according to irc8m_adjval */
1108 reg &= ~RCU_CTL_IRC8MADJ;
1109 RCU_CTL = (reg | ((irc8m_adjval & RCU_IRC8M_ADJUST_MASK) << RCU_IRC8M_ADJUST_OFFSET));
1110 }
1111
1112 /*!
1113 \brief deep-sleep mode voltage select
1114 \param[in] dsvol: deep sleep mode voltage
1115 only one parameter can be selected which is shown as below:
1116 \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V
1117 \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V
1118 \arg RCU_DEEPSLEEP_V_0_8: the core voltage is 0.8V
1119 \arg RCU_DEEPSLEEP_V_1_2: the core voltage is 1.2V
1120 \param[out] none
1121 \retval none
1122 */
rcu_deepsleep_voltage_set(uint32_t dsvol)1123 void rcu_deepsleep_voltage_set(uint32_t dsvol)
1124 {
1125 dsvol &= RCU_DSV_DSLPVS;
1126 RCU_DSV = dsvol;
1127 }
1128
1129 /*!
1130 \brief get the system clock, bus and peripheral clock frequency
1131 \param[in] clock: the clock frequency which to get
1132 only one parameter can be selected which is shown as below:
1133 \arg CK_SYS: system clock frequency
1134 \arg CK_AHB: AHB clock frequency
1135 \arg CK_APB1: APB1 clock frequency
1136 \arg CK_APB2: APB2 clock frequency
1137 \param[out] none
1138 \retval clock frequency of system, AHB, APB1, APB2
1139 */
rcu_clock_freq_get(rcu_clock_freq_enum clock)1140 uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock)
1141 {
1142 uint32_t sws, ck_freq = 0U;
1143 uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq;
1144 uint32_t pllsel, pllpresel, predv0sel, pllmf,ck_src, idx, clk_exp;
1145 uint32_t predv0, predv1, pll1mf;
1146
1147 /* exponent of AHB, APB1 and APB2 clock divider */
1148 uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
1149 uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1150 uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1151
1152 sws = GET_BITS(RCU_CFG0, 2, 3);
1153 switch(sws){
1154 /* IRC8M is selected as CK_SYS */
1155 case SEL_IRC8M:
1156 cksys_freq = IRC8M_VALUE;
1157 break;
1158 /* HXTAL is selected as CK_SYS */
1159 case SEL_HXTAL:
1160 cksys_freq = HXTAL_VALUE;
1161 break;
1162 /* PLL is selected as CK_SYS */
1163 case SEL_PLL:
1164 /* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */
1165 pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
1166
1167 if(RCU_PLLSRC_HXTAL_IRC48M == pllsel) {
1168 /* PLL clock source is HXTAL or IRC48M */
1169 pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL);
1170
1171 if(RCU_PLLPRESRC_HXTAL == pllpresel){
1172 /* PLL clock source is HXTAL */
1173 ck_src = HXTAL_VALUE;
1174 }else{
1175 /* PLL clock source is IRC48 */
1176 ck_src = IRC48M_VALUE;
1177 }
1178
1179 predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL);
1180 /* source clock use PLL1 */
1181 if(RCU_PREDV0SRC_CKPLL1 == predv0sel){
1182 predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> RCU_CFG1_PREDV1_OFFSET) + 1U;
1183 pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> RCU_CFG1_PLL1MF_OFFSET) + 2U;
1184 if(17U == pll1mf){
1185 pll1mf = 20U;
1186 }
1187 ck_src = (ck_src/predv1)*pll1mf;
1188 }
1189 predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U;
1190 ck_src /= predv0;
1191 }else{
1192 /* PLL clock source is IRC8M/2 */
1193 ck_src = IRC8M_VALUE/2U;
1194 }
1195
1196 /* PLL multiplication factor */
1197 pllmf = GET_BITS(RCU_CFG0, 18, 21);
1198 if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){
1199 pllmf |= 0x10U;
1200 }
1201 if(pllmf < 15U){
1202 pllmf += 2U;
1203 }else{
1204 pllmf += 1U;
1205 }
1206 cksys_freq = ck_src*pllmf;
1207 if(15U == pllmf){
1208 cksys_freq = ck_src*6U + ck_src/2U;
1209 }
1210
1211 break;
1212 /* IRC8M is selected as CK_SYS */
1213 default:
1214 cksys_freq = IRC8M_VALUE;
1215 break;
1216 }
1217
1218 /* calculate AHB clock frequency */
1219 idx = GET_BITS(RCU_CFG0, 4, 7);
1220 clk_exp = ahb_exp[idx];
1221 ahb_freq = cksys_freq >> clk_exp;
1222
1223 /* calculate APB1 clock frequency */
1224 idx = GET_BITS(RCU_CFG0, 8, 10);
1225 clk_exp = apb1_exp[idx];
1226 apb1_freq = ahb_freq >> clk_exp;
1227
1228 /* calculate APB2 clock frequency */
1229 idx = GET_BITS(RCU_CFG0, 11, 13);
1230 clk_exp = apb2_exp[idx];
1231 apb2_freq = ahb_freq >> clk_exp;
1232
1233 /* return the clocks frequency */
1234 switch(clock){
1235 case CK_SYS:
1236 ck_freq = cksys_freq;
1237 break;
1238 case CK_AHB:
1239 ck_freq = ahb_freq;
1240 break;
1241 case CK_APB1:
1242 ck_freq = apb1_freq;
1243 break;
1244 case CK_APB2:
1245 ck_freq = apb2_freq;
1246 break;
1247 default:
1248 break;
1249 }
1250 return ck_freq;
1251 }
1252