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