1 /*!
2 \file gd32l23x_rcu.c
3 \brief RCU driver
4
5 \version 2021-08-04, V1.0.0, firmware for GD32L23x
6 */
7
8 /*
9 Copyright (c) 2021, GigaDevice Semiconductor Inc.
10
11 Redistribution and use in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
13
14 1. Redistributions of source code must retain the above copyright notice, this
15 list of conditions and the following disclaimer.
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 3. Neither the name of the copyright holder nor the names of its contributors
20 may be used to endorse or promote products derived from this software without
21 specific prior written permission.
22
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 OF SUCH DAMAGE.
33 */
34
35 #include "gd32l23x_rcu.h"
36
37 /* define clock source */
38 #define SEL_IRC16M 0x00U
39 #define SEL_HXTAL 0x01U
40 #define SEL_PLL 0x02U
41
42 /* define startup timeout count */
43 #define OSC_STARTUP_TIMEOUT ((uint32_t)0x000FFFFFU)
44 #define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x03FFFFFFU)
45
46 /*!
47 \brief deinitialize the RCU
48 \param[in] none
49 \param[out] none
50 \retval none
51 */
rcu_deinit(void)52 void rcu_deinit(void)
53 {
54 /* enable IRC16M */
55 RCU_CTL |= RCU_CTL_IRC16MEN;
56 while(0U == (RCU_CTL & RCU_CTL_IRC16MSTB)) {
57 }
58 RCU_CFG0 &= ~RCU_CFG0_SCS;
59 RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN | RCU_CTL_HXTALBPS);
60 /* reset RCU */
61 RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | \
62 RCU_CFG0_ADCPSC | RCU_CFG0_CKOUTSEL | RCU_CFG0_CKOUTDIV | RCU_CFG0_PLLDV);
63 RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLDV);
64 RCU_CFG1 &= ~(RCU_CFG1_PREDV);
65 RCU_CFG2 &= ~(RCU_CFG2_USART0SEL | RCU_CFG2_ADCSEL);
66 RCU_CFG2 &= ~RCU_CFG2_ADCPSC2;
67
68 RCU_INT = 0x00000000U;
69 }
70
71 /*!
72 \brief enable the peripherals clock
73 \param[in] periph: RCU peripherals, refer to rcu_periph_enum
74 only one parameter can be selected which is shown as below:
75 \arg RCU_GPIOx (x=A,B,C,D,F): GPIO ports clock
76 \arg RCU_DMA: DMA clock
77 \arg RCU_CAU: CAU clock
78 \arg RCU_TRNG: TRNG clock
79 \arg RCU_CRC: CRC clock
80 \arg RCU_CMP: CMP clock
81 \arg RCU_SYSCFG: SYSCFG clock
82 \arg RCU_ADC: ADC clock
83 \arg RCU_TIMERx (x=1,2,5,6,8,11): TIMER clock
84 \arg RCU_LPTIMER: LPTIMER clock
85 \arg RCU_SPIx (x=0,1): SPI clock
86 \arg RCU_USARTx (x=0,1): USART clock
87 \arg RCU_UARTx (x=3,4): UART clock
88 \arg RCU_LPUART: LPUART clock
89 \arg RCU_WWDGT: WWDGT clock
90 \arg RCU_I2Cx (x=0,1,2): I2C clock
91 \arg RCU_PMU: PMU clock
92 \arg RCU_RTC: RTC clock
93 \arg RCU_DBGMCU: DBGMCU clock
94 \arg RCU_CAU: CAU clock
95 \arg RCU_DAC: DAC clock
96 \arg RCU_CTC: CTC clock
97 \arg RCU_BKP: BKP clock
98 \arg RCU_USBD: USBD clock
99 \arg RCU_SLCD: SLCD clock
100 \param[out] none
101 \retval none
102 */
rcu_periph_clock_enable(rcu_periph_enum periph)103 void rcu_periph_clock_enable(rcu_periph_enum periph)
104 {
105 RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
106 }
107
108 /*!
109 \brief disable the peripherals clock
110 \param[in] periph: RCU peripherals, refer to rcu_periph_enum
111 only one parameter can be selected which is shown as below:
112 \arg RCU_GPIOx (x=A,B,C,D,F): GPIO ports clock
113 \arg RCU_DMA: DMA clock
114 \arg RCU_CAU: CAU clock
115 \arg RCU_TRNG: TRNG clock
116 \arg RCU_CRC: CRC clock
117 \arg RCU_CMP: CMP clock
118 \arg RCU_SYSCFG: SYSCFG clock
119 \arg RCU_ADC: ADC clock
120 \arg RCU_TIMERx (x=1,2,5,6,8,11): TIMER clock
121 \arg RCU_LPTIMER: LPTIMER clock
122 \arg RCU_SPIx (x=0,1): SPI clock
123 \arg RCU_USARTx (x=0,1): USART clock
124 \arg RCU_UARTx (x=3,4): UART clock
125 \arg RCU_LPUART: LPUART clock
126 \arg RCU_WWDGT: WWDGT clock
127 \arg RCU_I2Cx (x=0,1,2): I2C clock
128 \arg RCU_PMU: PMU clock
129 \arg RCU_RTC: RTC clock
130 \arg RCU_DBGMCU: DBGMCU clock
131 \arg RCU_CAU: CAU clock
132 \arg RCU_DAC: DAC clock
133 \arg RCU_CTC: CTC clock
134 \arg RCU_BKP: BKP clock
135 \arg RCU_USBD: USBD clock
136 \arg RCU_SLCD: SLCD clock
137 \param[out] none
138 \retval none
139 */
rcu_periph_clock_disable(rcu_periph_enum periph)140 void rcu_periph_clock_disable(rcu_periph_enum periph)
141 {
142 RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
143 }
144
145 /*!
146 \brief enable the peripherals clock when sleep mode
147 \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum
148 only one parameter can be selected which is shown as below:
149 \arg RCU_FMC_SLP: FMC clock
150 \arg RCU_SRAM0_SLP: SRAM0 clock
151 \arg RCU_SRAM1_SLP: SRAM1 clock
152 \param[out] none
153 \retval none
154 */
rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)155 void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)
156 {
157 RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
158 }
159
160 /*!
161 \brief disable the peripherals clock when sleep mode
162 \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum
163 only one parameter can be selected which is shown as below:
164 \arg RCU_FMC_SLP: FMC clock
165 \arg RCU_SRAM0_SLP: SRAM clock
166 \arg RCU_SRAM1_SLP: SRAM clock
167 \param[out] none
168 \retval none
169 */
rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)170 void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)
171 {
172 RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
173 }
174 /*!
175 \brief reset the peripherals
176 \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
177 only one parameter can be selected which is shown as below:
178 \arg RCU_GPIOxRST (x=A,B,C,D,F): reset GPIO ports
179 \arg RCU_CAU: reset CAU
180 \arg RCU_CRC: reset CRC
181 \arg RCU_TRNG: reset TRNG
182 \arg RCU_CMPRST: reset CMP
183 \arg RCU_SYSCFGRST: reset SYSCFG
184 \arg RCU_ADCRST: reset ADC
185 \arg RCU_TIMERxRST (x=1,2,5,6,8,11): reset TIMER
186 \arg RCU_SPIxRST (x=0,1): reset SPI
187 \arg RCU_USARTxRST (x=0,1): reset USART
188 \arg RCU_LPTIMERRST: reset LPTIMER
189 \arg RCU_SLCDRRST: reset SLCD
190 \arg RCU_WWDGTRST: reset WWDGT
191 \arg RCU_LPUARTRST: reset LPUART
192 \arg RCU_UARTxRST (x=3,4): reset UART
193 \arg RCU_I2CxRST (x=0,1,2): reset I2C
194 \arg RCU_USBDRST: reset USBD
195 \arg RCU_PMURST: reset PMU
196 \arg RCU_DACRST : reset DAC
197 \arg RCU_CTCRST : reset CTC
198 \param[out] none
199 \retval none
200 */
rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)201 void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)
202 {
203 RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset));
204 }
205
206 /*!
207 \brief disable reset the peripheral
208 \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
209 only one parameter can be selected which is shown as below:
210 \arg RCU_GPIOxRST (x=A,B,C,D,F): reset GPIO ports
211 \arg RCU_CAU: reset CAU
212 \arg RCU_CRC: reset CRC
213 \arg RCU_TRNG: reset TRNG
214 \arg RCU_CMPRST: reset CMP
215 \arg RCU_SYSCFGRST: reset SYSCFG
216 \arg RCU_ADCRST: reset ADC
217 \arg RCU_TIMERxRST (x=1,2,5,6,8,11): reset TIMER
218 \arg RCU_SPIxRST (x=0,1): reset SPI
219 \arg RCU_USARTxRST (x=0,1): reset USART
220 \arg RCU_LPTIMERRST: reset LPTIMER
221 \arg RCU_SLCDRRST: reset LPTIMER
222 \arg RCU_WWDGTRST: reset WWDGT
223 \arg RCU_LPUARTRST: reset LPUART
224 \arg RCU_UARTxRST (x=3,4): reset UART
225 \arg RCU_I2CxRST (x=0,1,2): reset I2C
226 \arg RCU_USBDRST: reset USBD
227 \arg RCU_PMURST: reset PMU
228 \arg RCU_DACRST : reset DAC
229 \arg RCU_CTCRST : reset CTC
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
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 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_IRC16M: select CK_IRC16M 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 \arg RCU_CKSYSSRC_IRC48M: select CK_IRC48M as the CK_SYS source
268 \param[out] none
269 \retval none
270 */
rcu_system_clock_source_config(uint32_t ck_sys)271 void rcu_system_clock_source_config(uint32_t ck_sys)
272 {
273 uint32_t cksys_source = 0U;
274 cksys_source = RCU_CFG0;
275 /* reset the SCS bits and set according to ck_sys */
276 cksys_source &= ~RCU_CFG0_SCS;
277 RCU_CFG0 = (ck_sys | cksys_source);
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_IRC16M: select CK_IRC16M as the CK_SYS source
286 \arg RCU_SCSS_HXTAL: select CK_HXTAL as the CK_SYS source
287 \arg RCU_SCSS_PLL: select CK_PLL as the CK_SYS source
288 \arg RCU_SCSS_IRC48M: select CK_IRC48M as the CK_SYS source
289 */
rcu_system_clock_source_get(void)290 uint32_t rcu_system_clock_source_get(void)
291 {
292 return (RCU_CFG0 & RCU_CFG0_SCSS);
293 }
294
295 /*!
296 \brief configure the AHB clock prescaler selection
297 \param[in] ck_ahb: AHB clock prescaler selection
298 only one parameter can be selected which is shown as below:
299 \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512
300 \param[out] none
301 \retval none
302 */
rcu_ahb_clock_config(uint32_t ck_ahb)303 void rcu_ahb_clock_config(uint32_t ck_ahb)
304 {
305 uint32_t ahbpsc = 0U;
306 ahbpsc = RCU_CFG0;
307 /* reset the AHBPSC bits and set according to ck_ahb */
308 ahbpsc &= ~RCU_CFG0_AHBPSC;
309 RCU_CFG0 = (ck_ahb | ahbpsc);
310 }
311
312 /*!
313 \brief configure the APB1 clock prescaler selection
314 \param[in] ck_apb1: APB1 clock prescaler selection
315 only one parameter can be selected which is shown as below:
316 \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1
317 \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1
318 \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1
319 \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1
320 \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1
321 \param[out] none
322 \retval none
323 */
rcu_apb1_clock_config(uint32_t ck_apb1)324 void rcu_apb1_clock_config(uint32_t ck_apb1)
325 {
326 uint32_t apb1psc = 0U;
327 apb1psc = RCU_CFG0;
328 /* reset the APB1PSC and set according to ck_apb1 */
329 apb1psc &= ~RCU_CFG0_APB1PSC;
330 RCU_CFG0 = (ck_apb1 | apb1psc);
331 }
332
333 /*!
334 \brief configure the APB2 clock prescaler selection
335 \param[in] ck_apb2: APB2 clock prescaler selection
336 only one parameter can be selected which is shown as below:
337 \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2
338 \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2
339 \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2
340 \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2
341 \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2
342 \param[out] none
343 \retval none
344 */
rcu_apb2_clock_config(uint32_t ck_apb2)345 void rcu_apb2_clock_config(uint32_t ck_apb2)
346 {
347 uint32_t apb2psc = 0U;
348 apb2psc = RCU_CFG0;
349 /* reset the APB2PSC and set according to ck_apb2 */
350 apb2psc &= ~RCU_CFG0_APB2PSC;
351 RCU_CFG0 = (ck_apb2 | apb2psc);
352 }
353
354 /*!
355 \brief configure the ADC clock prescaler selection
356 \param[in] ck_adc: ADC clock prescaler selection, refer to rcu_adc_clock_enum
357 only one parameter can be selected which is shown as below:
358 \arg RCU_ADCCK_IRC16M: select CK_IRC16M as CK_ADC
359 \arg RCU_ADCCK_APB2_DIV2: select CK_APB2/2 as CK_ADC
360 \arg RCU_ADCCK_APB2_DIV4: select CK_APB2/4 as CK_ADC
361 \arg RCU_ADCCK_APB2_DIV6: select CK_APB2/6 as CK_ADC
362 \arg RCU_ADCCK_APB2_DIV8: select CK_APB2/8 as CK_ADC
363 \arg RCU_ADCCK_APB2_DIV10: select CK_APB2/10 as CK_ADC
364 \arg RCU_ADCCK_APB2_DIV12: select CK_APB2/12 as CK_ADC
365 \arg RCU_ADCCK_APB2_DIV14: select CK_APB2/14 as CK_ADC
366 \arg RCU_ADCCK_APB2_DIV16: select CK_APB2/16 as CK_ADC
367 \arg RCU_ADCCK_AHB_DIV3: select CK_AHB/3 as CK_ADC
368 \arg RCU_ADCCK_AHB_DIV5: select CK_AHB/5 as CK_ADC
369 \arg RCU_ADCCK_AHB_DIV7: select CK_AHB/7 as CK_ADC
370 \arg RCU_ADCCK_AHB_DIV9: select CK_AHB/9 as CK_ADC
371 \arg RCU_ADCCK_AHB_DIV11: select CK_AHB/11 as CK_ADC
372 \arg RCU_ADCCK_AHB_DIV13: select CK_AHB/13 as CK_ADC
373 \arg RCU_ADCCK_AHB_DIV15: select CK_AHB/15 as CK_ADC
374 \param[out] none
375 \retval none
376 */
rcu_adc_clock_config(uint32_t ck_adc)377 void rcu_adc_clock_config(uint32_t ck_adc)
378 {
379 /* reset the ADCPSC, ADCSEL bits */
380 RCU_CFG0 &= ~RCU_CFG0_ADCPSC;
381 RCU_CFG2 &= ~(RCU_CFG2_ADCSEL | RCU_CFG2_ADCPSC2);
382
383 /* set the ADC clock according to ck_adc */
384 if(ck_adc <= 15U) {
385 RCU_CFG0 |= ((ck_adc & 0x3U) << 14U);
386 RCU_CFG2 |= (((ck_adc & 0xCU) >> 2U) << 30U);
387 RCU_CFG2 |= RCU_CFG2_ADCSEL;
388 }
389 if(ck_adc == 16U) {
390 RCU_CFG2 &= ~RCU_CFG2_ADCSEL;
391 }
392 }
393
394 /*!
395 \brief configure the CK_OUT clock source and divider
396 \param[in] ckout_src: CK_OUT clock source selection
397 only one parameter can be selected which is shown as below:
398 \arg RCU_CKOUTSRC_NONE: no clock selected
399 \arg RCU_CKOUTSRC_IRC48M: IRC48M selected
400 \arg RCU_CKOUTSRC_IRC32K: IRC32K selected
401 \arg RCU_CKOUTSRC_LXTAL: LXTAL selected
402 \arg RCU_CKOUTSRC_CKSYS: CKSYS selected
403 \arg RCU_CKOUTSRC_IRC16M: IRC16M selected
404 \arg RCU_CKOUTSRC_HXTAL: HXTAL selected
405 \arg RCU_CKOUTSRC_CKPLL_DIV1: CK_PLL selected
406 \arg RCU_CKOUTSRC_CKPLL_DIV2: CK_PLL/2 selected
407 \param[in] ckout_div: CK_OUT divider
408 \arg RCU_CKOUT_DIVx(x=1,2,4,8,16,32,64,128): CK_OUT is divided by x
409 \param[out] none
410 \retval none
411 */
rcu_ckout_config(uint32_t ckout_src,uint32_t ckout_div)412 void rcu_ckout_config(uint32_t ckout_src, uint32_t ckout_div)
413 {
414 uint32_t ckout = 0U;
415 ckout = RCU_CFG0;
416 /* reset the CKOUTSEL, CKOUTDIV and PLLDV bits and set according to ckout_src and ckout_div */
417 ckout &= ~(RCU_CFG0_CKOUTSEL | RCU_CFG0_CKOUTDIV | RCU_CFG0_PLLDV);
418 RCU_CFG0 = (ckout | ckout_src | ckout_div);
419 }
420
421 /*!
422 \brief configure the PLL clock source selection and PLL multiply factor
423 \param[in] pll_src: PLL clock source selection
424 only one parameter can be selected which is shown as below:
425 \arg RCU_PLLSRC_IRC16M: select CK_IRC16M as PLL source clock
426 \arg RCU_PLLSRC_HXTAL: select HXTAL as PLL source clock
427 \arg RCU_PLLSRC_IRC48M: select CK_IRC48M as PLL source clock
428 \param[in] pll_mul: PLL multiply factor
429 only one parameter can be selected which is shown as below:
430 \arg RCU_PLL_MULx(x=4..127): PLL source clock * x
431 \param[out] none
432 \retval none
433 */
rcu_pll_config(uint32_t pll_src,uint32_t pll_mul)434 void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul)
435 {
436 RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF);
437 RCU_CFG0 |= (pll_src | pll_mul);
438 }
439
440 /*!
441 \brief configure the USARTx(x=0,1) clock source selection
442 \param[in] usart_idx: IDX_USARTx(x=0,1)
443 \param[in] ck_usart: USART clock source selection
444 only one parameter can be selected which is shown as below:
445 \arg RCU_USARTSRC_CKAPB: CK_USART select CK_APB1/CK_APB2
446 \arg RCU_USARTSRC_CKSYS: CK_USART select CK_SYS
447 \arg RCU_USARTSRC_LXTAL: CK_USART select CK_LXTAL
448 \arg RCU_USARTSRC_IRC16MDIV: CK_USART select CK_IRC16MDIV
449 \param[out] none
450 \retval none
451 */
rcu_usart_clock_config(usart_idx_enum usart_idx,uint32_t ck_usart)452 void rcu_usart_clock_config(usart_idx_enum usart_idx, uint32_t ck_usart)
453 {
454 switch(usart_idx) {
455 case IDX_USART0:
456 /* reset the USART0SEL bits and set according to ck_usart */
457 RCU_CFG2 &= ~RCU_CFG2_USART0SEL;
458 RCU_CFG2 |= ck_usart;
459 break;
460 case IDX_USART1:
461 /* reset the USART1SEL bits and set according to ck_usart */
462 RCU_CFG2 &= ~RCU_CFG2_USART1SEL;
463 RCU_CFG2 |= (uint32_t)ck_usart << 16U;
464 break;
465 default:
466 break;
467 }
468 }
469
470 /*!
471 \brief configure the I2Cx(x=0,1,2) clock source selection
472 \param[in] i2c_idx: IDX_I2Cx(x=0,1,2)
473 \param[in] ck_i2c: I2C clock source selection
474 only one parameter can be selected which is shown as below:
475 \arg RCU_I2CSRC_CKAPB1: CK_I2C select CK_APB1
476 \arg RCU_I2CSRC_CKSYS: CK_I2C select CK_SYS
477 \arg RCU_I2CSRC_IRC16MDIV: CK_I2C select IRC16MDIV
478 \param[out] none
479 \retval none
480 */
rcu_i2c_clock_config(i2c_idx_enum i2c_idx,uint32_t ck_i2c)481 void rcu_i2c_clock_config(i2c_idx_enum i2c_idx, uint32_t ck_i2c)
482 {
483 switch(i2c_idx) {
484 case IDX_I2C0:
485 /* reset the I2C0SEL bits and set according to ck_i2c */
486 RCU_CFG2 &= ~RCU_CFG2_I2C0SEL;
487 RCU_CFG2 |= ck_i2c;
488 break;
489 case IDX_I2C1:
490 /* reset the I2C1SEL bits and set according to ck_i2c */
491 RCU_CFG2 &= ~RCU_CFG2_I2C1SEL;
492 RCU_CFG2 |= (uint32_t)ck_i2c << 2U;
493 break;
494 case IDX_I2C2:
495 /* reset the I2C2SEL bits and set according to ck_i2c */
496 RCU_CFG2 &= ~RCU_CFG2_I2C2SEL;
497 RCU_CFG2 |= (uint32_t)ck_i2c << 4U;
498 break;
499 default:
500 break;
501 }
502 }
503 /*!
504 \brief configure the LPTIMER clock source selection
505 \param[in] ck_lptimer: LPTIMER clock source selection
506 only one parameter can be selected which is shown as below:
507 \arg RCU_LPTIMERSRC_CKAPB1: CK_LPTIMER select CK_APB1
508 \arg RCU_LPTIMERSRC_IRC32K: CK_LPTIMER select CK_IRC32K
509 \arg RCU_LPTIMERSRC_LXTAL: CK_LPTIMER select CK_LXTAL
510 \arg RCU_LPTIMERSRC_IRC16MDIV: CK_LPTIMER select CK_IRC16MDIV
511 \param[out] none
512 \retval none
513 */
rcu_lptimer_clock_config(uint32_t ck_lptimer)514 void rcu_lptimer_clock_config(uint32_t ck_lptimer)
515 {
516 /* reset the LPTIMERSEL bits and set according to ck_lptimer */
517 RCU_CFG2 &= ~RCU_CFG2_LPTIMERSEL;
518 RCU_CFG2 |= ck_lptimer;
519 }
520
521 /*!
522 \brief configure the LPUART clock source selection
523 \param[in] ck_lpusart: LPUART clock source selection
524 only one parameter can be selected which is shown as below:
525 \arg RCU_LPUARTSRC_CKAPB1: LPUART select CK_APB1
526 \arg RCU_LPUARTSRC_CKSYS: LPUART select CK_SYS
527 \arg RCU_LPUARTSRC_LXTAL: LPUART select CK_LXTAL
528 \arg RCU_LPUARTSRC_IRC16MDIV: LPUART select CK_IRC16MDIV
529 \param[out] none
530 \retval none
531 */
rcu_lpuart_clock_config(uint32_t ck_lpuart)532 void rcu_lpuart_clock_config(uint32_t ck_lpuart)
533 {
534 /* reset the LPUARTSEL bits and set according to ck_lpuart */
535 RCU_CFG2 &= ~RCU_CFG2_LPUARTSEL;
536 RCU_CFG2 |= ck_lpuart;
537 }
538
539 /*!
540 \brief configure the IRC16MDIV clock selection
541 \param[in] ck_irc16mdiv: IRC16MDIV clock selection
542 only one parameter can be selected which is shown as below:
543 \arg RCU_IRC16MDIV_NONE: CK_IRC16MDIV select CK_IRC16M
544 \arg RCU_IRC16MDIV_2: CK_IRC16MDIV select CK_IRC16M divided by 2
545 \arg RCU_IRC16MDIV_4: CK_IRC16MDIV select CK_IRC16M divided by 4
546 \arg RCU_IRC16MDIV_8: CK_IRC16MDIV select CK_IRC16M divided by 8
547 \arg RCU_IRC16MDIV_16: CK_IRC16MDIV select CK_IRC16M divided by 16
548 \param[out] none
549 \retval none
550 */
rcu_irc16mdiv_clock_config(uint32_t ck_irc16mdiv)551 void rcu_irc16mdiv_clock_config(uint32_t ck_irc16mdiv)
552 {
553 /* reset the LPUARTSEL bits and set according to ck_lpuart */
554 RCU_CFG2 &= ~RCU_CFG2_IRC16MDIVSEL;
555 RCU_CFG2 |= ck_irc16mdiv;
556 }
557
558 /*!
559 \brief configure the USBD clock source selection
560 \param[in] ck_usart: USBD clock source selection
561 only one parameter can be selected which is shown as below:
562 \arg RCU_USBDSRC_IRC48M: USBD select CK_IRC48M
563 \arg RCU_USBDSRC_PLL: USBD select CK_PLL
564 \param[out] none
565 \retval none
566 */
rcu_usbd_clock_config(uint32_t ck_usbd)567 void rcu_usbd_clock_config(uint32_t ck_usbd)
568 {
569 /* reset the USBDSEL bits and set according to ck_usbd */
570 RCU_CFG2 &= ~RCU_CFG2_USBDSEL;
571 RCU_CFG2 |= ck_usbd;
572 }
573
574 /*!
575 \brief configure the RTC clock source selection
576 \param[in] rtc_clock_source: RTC clock source selection
577 only one parameter can be selected which is shown as below:
578 \arg RCU_RTCSRC_NONE: no clock selected
579 \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock
580 \arg RCU_RTCSRC_IRC32K: CK_IRC32K selected as RTC source clock
581 \arg RCU_RTCSRC_HXTAL_DIV32: CK_HXTAL/32 selected as RTC source clock
582 \param[out] none
583 \retval none
584 */
rcu_rtc_clock_config(uint32_t rtc_clock_source)585 void rcu_rtc_clock_config(uint32_t rtc_clock_source)
586 {
587 /* reset the RTCSRC bits and set according to rtc_clock_source */
588 RCU_BDCTL &= ~RCU_BDCTL_RTCSRC;
589 RCU_BDCTL |= rtc_clock_source;
590 }
591
592 /*!
593 \brief configure PLL source clocks pre-divider
594 \param[in] pllsource_ck_prediv: PLL source clocks divider used as input of PLL
595 only one parameter can be selected which is shown as below:
596 \arg RCU_PLL_PREDVx(x=1..16): PLL source clocks divided x used as input of PLL
597 \param[out] none
598 \retval none
599 */
rcu_pll_source_ck_prediv_config(uint32_t pllsource_ck_prediv)600 void rcu_pll_source_ck_prediv_config(uint32_t pllsource_ck_prediv)
601 {
602 uint32_t prediv = 0U;
603 prediv = RCU_CFG1;
604 /* reset the PREDV bits and set according to pllsource_ck_prediv */
605 prediv &= ~RCU_CFG1_PREDV;
606 RCU_CFG1 = (prediv | pllsource_ck_prediv);
607 }
608
609 /*!
610 \brief configure the LXTAL drive capability
611 \param[in] lxtal_dricap: drive capability of LXTAL
612 only one parameter can be selected which is shown as below:
613 \arg RCU_LXTAL_LOWDRI: lower driving capability
614 \arg RCU_LXTAL_MED_LOWDRI: medium low driving capability
615 \arg RCU_LXTAL_MED_HIGHDRI: medium high driving capability
616 \arg RCU_LXTAL_HIGHDRI: higher driving capability
617 \param[out] none
618 \retval none
619 */
rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap)620 void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap)
621 {
622 /* reset the LXTALDRI bits and set according to lxtal_dricap */
623 RCU_BDCTL &= ~RCU_BDCTL_LXTALDRI;
624 RCU_BDCTL |= lxtal_dricap;
625 }
626
627 /*!
628 \brief configure the low power mode LDO voltage selection
629 \param[in] lp_ldo_voltage: low power mode LDO voltage
630 only one parameter can be selected which is shown as below:
631 \arg RCU_LP_LDO_V_0_8: LP_LDO output voltage 0.8V
632 \arg RCU_LP_LDO_V_0_9: LP_LDO output voltage 0.9V
633 \param[out] none
634 \retval none
635 */
rcu_lp_ldo_config(uint32_t lp_ldo_voltage)636 void rcu_lp_ldo_config(uint32_t lp_ldo_voltage)
637 {
638 /* reset the RCU_LPB_LPBMODE bits and set according to lp_ldo_voltage */
639 RCU_LPLDO &= ~RCU_LPB_LPBMSEL;
640 RCU_LPLDO |= lp_ldo_voltage;
641 }
642
643 /*!
644 \brief configure low power bandgap mode selection
645 \param[in] lp_bandgap_clock: low power bandgap clock
646 only one parameter can be selected which is shown as below:
647 \arg RCU_LPBM_32CLK: The length of holding phase is 3.2ms, 32 clock cycles
648 \arg RCU_LPBM_64CLK: The length of holding phase is 6.4ms, 64 clock cycles
649 \arg RCU_LPBM_128CLK: The length of holding phase is 12.8ms, 128 clock cycles
650 \arg RCU_LPBM_256CLK: The length of holding phase is 25.6ms, 256 clock cycles
651 \arg RCU_LPBM_512CLK: The length of holding phase is 51.2ms, 512 clock cycles
652 \arg RCU_LPBM_1024CLK: The length of holding phase is 102.4ms, 1024 clock cycles
653 \arg RCU_LPBM_2048CLK: The length of holding phase is 204.8ms, 2048 clock cycles
654 \param[out] none
655 \retval none
656 */
rcu_lp_bandgap_config(uint32_t lp_bandgap_clock)657 void rcu_lp_bandgap_config(uint32_t lp_bandgap_clock)
658 {
659 /* reset the RCU_LPB_LPBMODE bits and set according to lp_ldo_voltage */
660 RCU_LPB &= ~RCU_LPB_LPBMSEL;
661 RCU_LPB |= lp_bandgap_clock;
662 }
663
664 /*!
665 \brief get the clock stabilization and periphral reset flags
666 \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum
667 only one parameter can be selected which is shown as below:
668 \arg RCU_FLAG_IRC32KSTB: IRC32K stabilization flag
669 \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag
670 \arg RCU_FLAG_IRC16MSTB: IRC16M stabilization flag
671 \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag
672 \arg RCU_FLAG_PLLSTB: PLL stabilization flag
673 \arg RCU_FLAG_IRC48MSTB: IRC48M stabilization flag
674 \arg RCU_FLAG_V12RST: V12 domain power reset flag
675 \arg RCU_FLAG_EPRST: external pin reset flag
676 \arg RCU_FLAG_PORRST: power reset flag
677 \arg RCU_FLAG_SWRST: software reset flag
678 \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag
679 \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag
680 \arg RCU_FLAG_LPRST: low-power reset flag
681 \param[out] none
682 \retval FlagStatus: SET or RESET
683 */
rcu_flag_get(rcu_flag_enum flag)684 FlagStatus rcu_flag_get(rcu_flag_enum flag)
685 {
686 if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))) {
687 return SET;
688 } else {
689 return RESET;
690 }
691 }
692
693 /*!
694 \brief clear the reset flag
695 \param[in] none
696 \param[out] none
697 \retval none
698 */
rcu_all_reset_flag_clear(void)699 void rcu_all_reset_flag_clear(void)
700 {
701 RCU_RSTSCK |= RCU_RSTSCK_RSTFC;
702 }
703
704 /*!
705 \brief get the clock stabilization interrupt and ckm flags
706 \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum
707 only one parameter can be selected which is shown as below:
708 \arg RCU_INT_FLAG_IRC32KSTB: IRC32K stabilization interrupt flag
709 \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag
710 \arg RCU_INT_FLAG_IRC16MSTB: IRC16M stabilization interrupt flag
711 \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag
712 \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag
713 \arg RCU_INT_FLAG_IRC48MSTB: IRC48M stabilization interrupt flag
714 \arg RCU_INT_FLAG_LXTALCKM: LXTAL clock stuck interrupt flag
715 \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag
716 \param[out] none
717 \retval FlagStatus: SET or RESET
718 */
rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)719 FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)
720 {
721 if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))) {
722 return SET;
723 } else {
724 return RESET;
725 }
726 }
727
728 /*!
729 \brief clear the interrupt flags
730 \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum
731 only one parameter can be selected which is shown as below:
732 \arg RCU_INT_FLAG_IRC32KSTB_CLR: IRC32K stabilization interrupt flag clear
733 \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear
734 \arg RCU_INT_FLAG_IRC16MSTB_CLR: IRC16M stabilization interrupt flag clear
735 \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear
736 \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear
737 \arg RCU_INT_FLAG_IRC48MSTB_CLR: IRC48M stabilization interrupt flag clear
738 \arg RCU_INT_FLAG_LXTALCKM_CLR: LXTAL clock stuck interrupt flag clear
739 \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear
740 \param[out] none
741 \retval none
742 */
rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear)743 void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear)
744 {
745 RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear));
746 }
747
748 /*!
749 \brief enable the stabilization interrupt
750 \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum
751 only one parameter can be selected which is shown as below:
752 \arg RCU_INT_IRC32KSTB: IRC32K stabilization interrupt enable
753 \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
754 \arg RCU_INT_IRC16MSTB: IRC16M stabilization interrupt enable
755 \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
756 \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable
757 \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable
758 \arg RCU_INT_LXTALCKM: LXTAL clock stuck interrup enable
759 \param[out] none
760 \retval none
761 */
rcu_interrupt_enable(rcu_int_enum stab_int)762 void rcu_interrupt_enable(rcu_int_enum stab_int)
763 {
764 RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int));
765 }
766
767 /*!
768 \brief disable the stabilization interrupt
769 \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum
770 only one parameter can be selected which is shown as below:
771 \arg RCU_INT_IRC32KSTB: IRC32K stabilization interrupt disable
772 \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt disable
773 \arg RCU_INT_IRC16MSTB: IRC16M stabilization interrupt disable
774 \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt disable
775 \arg RCU_INT_PLLSTB: PLL stabilization interrupt disable
776 \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt disable
777 \arg RCU_INT_LXTALCKM: LXTAL clock stuck interrup disable
778 \param[out] none
779 \retval none
780 */
rcu_interrupt_disable(rcu_int_enum stab_int)781 void rcu_interrupt_disable(rcu_int_enum stab_int)
782 {
783 RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int));
784 }
785
786 /*!
787 \brief wait until oscillator stabilization flags is SET
788 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
789 only one parameter can be selected which is shown as below:
790 \arg RCU_HXTAL: HXTAL
791 \arg RCU_LXTAL: LXTAL
792 \arg RCU_IRC16M: IRC16M
793 \arg RCU_IRC48M: IRC48M
794 \arg RCU_IRC32K: IRC32K
795 \arg RCU_PLL_CK: PLL
796 \param[out] none
797 \retval ErrStatus: SUCCESS or ERROR
798 */
rcu_osci_stab_wait(rcu_osci_type_enum osci)799 ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci)
800 {
801 uint32_t stb_cnt = 0U;
802 ErrStatus reval = ERROR;
803 FlagStatus osci_stat = RESET;
804 switch(osci) {
805 case RCU_HXTAL:
806 /* wait until HXTAL is stabilization and osci_stat is not more than timeout */
807 while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)) {
808 osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB);
809 stb_cnt++;
810 }
811 /* check whether flag is set or not */
812 if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)) {
813 reval = SUCCESS;
814 }
815 break;
816
817 /* wait LXTAL stable */
818 case RCU_LXTAL:
819 while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)) {
820 osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB);
821 stb_cnt++;
822 }
823 /* check whether flag is set or not */
824 if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)) {
825 reval = SUCCESS;
826 }
827 break;
828
829 /* wait IRC16M stable */
830 case RCU_IRC16M:
831 while((RESET == osci_stat) && (IRC16M_STARTUP_TIMEOUT != stb_cnt)) {
832 osci_stat = rcu_flag_get(RCU_FLAG_IRC16MSTB);
833 stb_cnt++;
834 }
835 /* check whether flag is set or not */
836 if(RESET != rcu_flag_get(RCU_FLAG_IRC16MSTB)) {
837 reval = SUCCESS;
838 }
839 break;
840
841 /* wait IRC48M stable */
842 case RCU_IRC48M:
843 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) {
844 osci_stat = rcu_flag_get(RCU_FLAG_IRC48MSTB);
845 stb_cnt++;
846 }
847 /* check whether flag is set or not */
848 if(RESET != rcu_flag_get(RCU_FLAG_IRC48MSTB)) {
849 reval = SUCCESS;
850 }
851 break;
852
853 /* wait IRC32K stable */
854 case RCU_IRC32K:
855 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) {
856 osci_stat = rcu_flag_get(RCU_FLAG_IRC32KSTB);
857 stb_cnt++;
858 }
859 /* check whether flag is set or not */
860 if(RESET != rcu_flag_get(RCU_FLAG_IRC32KSTB)) {
861 reval = SUCCESS;
862 }
863 break;
864
865 /* wait PLL stable */
866 case RCU_PLL_CK:
867 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) {
868 osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB);
869 stb_cnt++;
870 }
871 /* check whether flag is set or not */
872 if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)) {
873 reval = SUCCESS;
874 }
875 break;
876
877 default:
878 break;
879 }
880 /* return value */
881 return reval;
882 }
883
884 /*!
885 \brief turn on the oscillator
886 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
887 only one parameter can be selected which is shown as below:
888 \arg RCU_HXTAL: HXTAL
889 \arg RCU_LXTAL: LXTAL
890 \arg RCU_IRC16M: IRC16M
891 \arg RCU_IRC48M: IRC48M
892 \arg RCU_IRC32K: IRC32K
893 \arg RCU_PLL_CK: PLL
894 \param[out] none
895 \retval none
896 */
rcu_osci_on(rcu_osci_type_enum osci)897 void rcu_osci_on(rcu_osci_type_enum osci)
898 {
899 RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci));
900 }
901
902 /*!
903 \brief turn off the oscillator
904 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
905 only one parameter can be selected which is shown as below:
906 \arg RCU_HXTAL: HXTAL
907 \arg RCU_LXTAL: LXTAL
908 \arg RCU_IRC16M: IRC16M
909 \arg RCU_IRC48M: IRC48M
910 \arg RCU_IRC32K: IRC32K
911 \arg RCU_PLL_CK: PLL
912 \param[out] none
913 \retval none
914 */
rcu_osci_off(rcu_osci_type_enum osci)915 void rcu_osci_off(rcu_osci_type_enum osci)
916 {
917 RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci));
918 }
919
920 /*!
921 \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
922 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
923 only one parameter can be selected which is shown as below:
924 \arg RCU_HXTAL: HXTAL
925 \arg RCU_LXTAL: LXTAL
926 \param[out] none
927 \retval none
928 */
rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)929 void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)
930 {
931 uint32_t reg;
932 switch(osci) {
933 case RCU_HXTAL:
934 /* HXTALEN must be reset before enable the oscillator bypass mode */
935 reg = RCU_CTL;
936 RCU_CTL &= ~RCU_CTL_HXTALEN;
937 RCU_CTL = (reg | RCU_CTL_HXTALBPS);
938 break;
939 case RCU_LXTAL:
940 /* LXTALEN must be reset before enable the oscillator bypass mode */
941 reg = RCU_BDCTL;
942 RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
943 RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS);
944 break;
945 case RCU_IRC16M:
946 case RCU_IRC48M:
947 case RCU_IRC32K:
948 case RCU_PLL_CK:
949 break;
950 default:
951 break;
952 }
953 }
954
955 /*!
956 \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
957 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
958 only one parameter can be selected which is shown as below:
959 \arg RCU_HXTAL: HXTAL
960 \arg RCU_LXTAL: LXTAL
961 \param[out] none
962 \retval none
963 */
rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)964 void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)
965 {
966 uint32_t reg;
967 switch(osci) {
968 case RCU_HXTAL:
969 /* HXTALEN must be reset before disable the oscillator bypass mode */
970 reg = RCU_CTL;
971 RCU_CTL &= ~RCU_CTL_HXTALEN;
972 RCU_CTL = (reg & (~RCU_CTL_HXTALBPS));
973 break;
974 case RCU_LXTAL:
975 /* LXTALEN must be reset before disable the oscillator bypass mode */
976 reg = RCU_BDCTL;
977 RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
978 RCU_BDCTL = (reg & (~RCU_BDCTL_LXTALBPS));
979 break;
980 case RCU_IRC16M:
981 case RCU_IRC48M:
982 case RCU_IRC32K:
983 case RCU_PLL_CK:
984 break;
985 default:
986 break;
987 }
988 }
989
990 /*!
991 \brief enable the HXTAL clock monitor
992 \param[in] none
993 \param[out] none
994 \retval none
995 */
rcu_hxtal_clock_monitor_enable(void)996 void rcu_hxtal_clock_monitor_enable(void)
997 {
998 RCU_CTL |= RCU_CTL_CKMEN;
999 }
1000
1001 /*!
1002 \brief disable the HXTAL clock monitor
1003 \param[in] none
1004 \param[out] none
1005 \retval none
1006 */
rcu_hxtal_clock_monitor_disable(void)1007 void rcu_hxtal_clock_monitor_disable(void)
1008 {
1009 RCU_CTL &= ~RCU_CTL_CKMEN;
1010 }
1011
1012 /*!
1013 \brief enable the LXTAL clock monitor
1014 \param[in] none
1015 \param[out] none
1016 \retval none
1017 */
rcu_lxtal_clock_monitor_enable(void)1018 void rcu_lxtal_clock_monitor_enable(void)
1019 {
1020 RCU_CTL |= RCU_CTL_LXTALCKMEN;
1021 }
1022
1023 /*!
1024 \brief disable the LXTAL clock monitor
1025 \param[in] none
1026 \param[out] none
1027 \retval none
1028 */
rcu_lxtal_clock_monitor_disable(void)1029 void rcu_lxtal_clock_monitor_disable(void)
1030 {
1031 RCU_CTL &= ~RCU_CTL_LXTALCKMEN;
1032 }
1033
1034 /*!
1035 \brief set the IRC16M adjust value
1036 \param[in] irc16m_adjval: IRC16M adjust value, must be between 0 and 0x1F
1037 \param[out] none
1038 \retval none
1039 */
rcu_irc16m_adjust_value_set(uint8_t irc16m_adjval)1040 void rcu_irc16m_adjust_value_set(uint8_t irc16m_adjval)
1041 {
1042 uint32_t adjust = 0U;
1043 adjust = RCU_CTL;
1044 /* reset the IRC16MADJ bits and set according to irc16m_adjval */
1045 adjust &= ~RCU_CTL_IRC16MADJ;
1046 RCU_CTL = (adjust | (((uint32_t)irc16m_adjval) << 3));
1047 }
1048
1049
1050 /*!
1051 \brief unlock the voltage key
1052 \param[in] none
1053 \param[out] none
1054 \retval none
1055 */
rcu_voltage_key_unlock(void)1056 void rcu_voltage_key_unlock(void)
1057 {
1058 /* reset the KEY bits and set 0x1A2B3C4D */
1059 RCU_VKEY &= ~RCU_VKEY_KEY;
1060 RCU_VKEY |= RCU_VKEY_UNLOCK;
1061 }
1062
1063 /*!
1064 \brief get the system clock, bus and peripheral clock frequency
1065 \param[in] clock: the clock frequency which to get
1066 only one parameter can be selected which is shown as below:
1067 \arg CK_SYS: system clock frequency
1068 \arg CK_AHB: AHB clock frequency
1069 \arg CK_APB1: APB1 clock frequency
1070 \arg CK_APB2: APB2 clock frequency
1071 \arg CK_ADC: ADC clock frequency
1072 \arg CK_USART0: USART0 clock frequency
1073 \arg CK_USART1: USART1 clock frequency
1074 \arg CK_LPTIMER: LPTIMER clock frequency
1075 \arg CK_LPUART: LPUART clock frequency
1076 \param[out] none
1077 \retval clock frequency of system, AHB, APB1, APB2, ADC or USRAT0/1, LPUART, LPTIMER
1078 */
rcu_clock_freq_get(rcu_clock_freq_enum clock)1079 uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock)
1080 {
1081 uint32_t sws = 0U, adcps = 0U, adcps2 = 0U, ck_freq = 0U;
1082 uint32_t cksys_freq = 0U, ahb_freq = 0U, apb1_freq = 0U, apb2_freq = 0U;
1083 uint32_t adc_freq = 0U, usart_freq = 0U, lptimer_freq = 0U;
1084 uint32_t pllmf = 0U, pllmf6 = 0U, pllsel = 0U, prediv = 0U, idx = 0U, clk_exp = 0U;
1085 /* exponent of AHB, APB1 and APB2 clock divider */
1086 const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
1087 const uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1088 const uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1089 const uint8_t IRC16M_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1090
1091 sws = GET_BITS(RCU_CFG0, 2, 3);
1092 switch(sws) {
1093 /* IRC16M is selected as CK_SYS */
1094 case SEL_IRC16M:
1095 cksys_freq = IRC16M_VALUE;
1096 break;
1097 /* HXTAL is selected as CK_SYS */
1098 case SEL_HXTAL:
1099 cksys_freq = HXTAL_VALUE;
1100 break;
1101 /* PLL is selected as CK_SYS */
1102 case SEL_PLL:
1103 /* get the value of PLLMF[5:0] */
1104 pllmf = GET_BITS(RCU_CFG0, 18, 23);
1105 pllmf6 = GET_BITS(RCU_CFG0, 27, 27);
1106 pllmf = ((pllmf6 << 6) + pllmf);
1107 /* high 16 bits */
1108 if(14U <= pllmf) {
1109 pllmf += 1U;
1110 } else if(15U == pllmf) {
1111 pllmf = 16U;
1112 } else {
1113 pllmf += 2U;
1114 }
1115
1116 /* PLL clock source selection, HXTAL or IRC16M_VALUE or IRC48M_VALUE */
1117 pllsel = GET_BITS(RCU_CFG0, 16, 17);
1118 if(0U == pllsel) {
1119 prediv = (GET_BITS(RCU_CFG1, 0, 3) + 1U);
1120 cksys_freq = (IRC16M_VALUE / prediv) * pllmf;
1121 } else if(1U == pllsel) {
1122 prediv = (GET_BITS(RCU_CFG1, 0, 3) + 1U);
1123 cksys_freq = (HXTAL_VALUE / prediv) * pllmf;
1124 } else {
1125 prediv = (GET_BITS(RCU_CFG1, 0, 3) + 1U);
1126 cksys_freq = (IRC48M_VALUE / prediv) * pllmf;
1127 }
1128 break;
1129 /* IRC16M is selected as CK_SYS */
1130 default:
1131 cksys_freq = IRC16M_VALUE;
1132 break;
1133 }
1134 /* calculate AHB clock frequency */
1135 idx = GET_BITS(RCU_CFG0, 4, 7);
1136 clk_exp = ahb_exp[idx];
1137 ahb_freq = cksys_freq >> clk_exp;
1138
1139 /* calculate APB1 clock frequency */
1140 idx = GET_BITS(RCU_CFG0, 8, 10);
1141 clk_exp = apb1_exp[idx];
1142 apb1_freq = ahb_freq >> clk_exp;
1143
1144 /* calculate APB2 clock frequency */
1145 idx = GET_BITS(RCU_CFG0, 11, 13);
1146 clk_exp = apb2_exp[idx];
1147 apb2_freq = ahb_freq >> clk_exp;
1148
1149 /* return the clocks frequency */
1150 switch(clock) {
1151 case CK_SYS:
1152 ck_freq = cksys_freq;
1153 break;
1154 case CK_AHB:
1155 ck_freq = ahb_freq;
1156 break;
1157 case CK_APB1:
1158 ck_freq = apb1_freq;
1159 break;
1160 case CK_APB2:
1161 ck_freq = apb2_freq;
1162 break;
1163 case CK_ADC:
1164 /* calculate ADC clock frequency */
1165 if(RCU_ADCSRC_AHB_APB2DIV != (RCU_CFG2 & RCU_CFG2_ADCSEL)) {
1166 adc_freq = IRC48M_VALUE;
1167 } else {
1168 /* ADC clock select CK_APB2 divided by 2/4/6/8 or CK_AHB divided by 3/5/7/9 */
1169 adcps = GET_BITS(RCU_CFG0, 14, 15);
1170 adcps2 = GET_BITS(RCU_CFG2, 30, 31);
1171 switch(adcps) {
1172 case 0:
1173 if(0U == adcps2) {
1174 adc_freq = apb2_freq / 2U;
1175 } else if(1U == adcps2) {
1176 adc_freq = apb2_freq / 10U;
1177 } else if(2U == adcps2) {
1178 adc_freq = ahb_freq / 3U;
1179 } else if(3U == adcps2) {
1180 adc_freq = ahb_freq / 11U;
1181 } else {
1182 }
1183 break;
1184 case 1:
1185 if(0U == adcps2) {
1186 adc_freq = apb2_freq / 4U;
1187 } else if(1U == adcps2) {
1188 adc_freq = apb2_freq / 12U;
1189 } else if(2U == adcps2) {
1190 adc_freq = ahb_freq / 5U;
1191 } else if(3U == adcps2) {
1192 adc_freq = ahb_freq / 13U;
1193 } else {
1194 }
1195 break;
1196 case 2:
1197 if(0U == adcps2) {
1198 adc_freq = apb2_freq / 6U;
1199 } else if(1U == adcps2) {
1200 adc_freq = apb2_freq / 14U;
1201 } else if(2U == adcps2) {
1202 adc_freq = ahb_freq / 7U;
1203 } else if(3U == adcps2) {
1204 adc_freq = ahb_freq / 15U;
1205 } else {
1206 }
1207 break;
1208 case 3:
1209 if(0U == adcps2) {
1210 adc_freq = apb2_freq / 8U;
1211 } else if(1U == adcps2) {
1212 adc_freq = apb2_freq / 16U;
1213 } else if(2U == adcps2) {
1214 adc_freq = ahb_freq / 9U;
1215 } else if(3U == adcps2) {
1216 adc_freq = ahb_freq / 17U;
1217 } else {
1218 }
1219 break;
1220 default:
1221 break;
1222 }
1223 }
1224 ck_freq = adc_freq;
1225 break;
1226 case CK_USART0:
1227 /* calculate USART0 clock frequency */
1228 if(RCU_USART0SRC_CKAPB2 == (RCU_CFG2 & RCU_CFG2_USART0SEL)) {
1229 usart_freq = apb2_freq;
1230 } else if(RCU_USART0SRC_CKSYS == (RCU_CFG2 & RCU_CFG2_USART0SEL)) {
1231 usart_freq = cksys_freq;
1232 } else if(RCU_USART0SRC_LXTAL == (RCU_CFG2 & RCU_CFG2_USART0SEL)) {
1233 usart_freq = LXTAL_VALUE;
1234 } else if(RCU_USART0SRC_IRC16MDIV == (RCU_CFG2 & RCU_CFG2_USART0SEL)) {
1235 /* calculate IRC16MDIV clock frequency */
1236 idx = GET_BITS(RCU_CFG2, 18, 20);
1237 clk_exp = IRC16M_exp[idx];
1238 usart_freq = IRC16M_VALUE >> clk_exp;
1239 } else {
1240 }
1241 ck_freq = usart_freq;
1242 break;
1243 case CK_USART1:
1244 /* calculate USART1 clock frequency */
1245 if(RCU_USART1SRC_CKAPB1 == (RCU_CFG2 & RCU_CFG2_USART1SEL)) {
1246 usart_freq = apb1_freq;
1247 } else if(RCU_USART1SRC_CKSYS == (RCU_CFG2 & RCU_CFG2_USART1SEL)) {
1248 usart_freq = cksys_freq;
1249 } else if(RCU_USART1SRC_LXTAL == (RCU_CFG2 & RCU_CFG2_USART1SEL)) {
1250 usart_freq = LXTAL_VALUE;
1251 } else if(RCU_USART1SRC_IRC16MDIV == (RCU_CFG2 & RCU_CFG2_USART1SEL)) {
1252 /* calculate IRC16MDIV clock frequency */
1253 idx = GET_BITS(RCU_CFG2, 18, 20);
1254 clk_exp = IRC16M_exp[idx];
1255 usart_freq = IRC16M_VALUE >> clk_exp;
1256 } else {
1257 }
1258 ck_freq = usart_freq;
1259 break;
1260 case CK_LPUART:
1261 /* calculate LPUART clock frequency */
1262 if(RCU_LPUARTSRC_CKAPB1 == (RCU_CFG2 & RCU_CFG2_LPUARTSEL)) {
1263 usart_freq = apb1_freq;
1264 } else if(RCU_LPUARTSRC_CKSYS == (RCU_CFG2 & RCU_CFG2_LPUARTSEL)) {
1265 usart_freq = cksys_freq;
1266 } else if(RCU_LPUARTSRC_LXTAL == (RCU_CFG2 & RCU_CFG2_LPUARTSEL)) {
1267 usart_freq = LXTAL_VALUE;
1268 } else if(RCU_LPUARTSRC_IRC16MDIV == (RCU_CFG2 & RCU_CFG2_LPUARTSEL)) {
1269 /* calculate IRC16MDIV clock frequency */
1270 idx = GET_BITS(RCU_CFG2, 18, 20);
1271 clk_exp = IRC16M_exp[idx];
1272 usart_freq = IRC16M_VALUE >> clk_exp;
1273 } else {
1274 }
1275 ck_freq = usart_freq;
1276 break;
1277 case CK_LPTIMER:
1278 /* calculate LPTIMER clock frequency */
1279 if(RCU_LPTIMERSRC_CKAPB1 == (RCU_CFG2 & RCU_CFG2_LPTIMERSEL)) {
1280 lptimer_freq = apb1_freq;
1281 } else if(RCU_LPTIMERSRC_IRC32K == (RCU_CFG2 & RCU_CFG2_LPTIMERSEL)) {
1282 lptimer_freq = IRC32K_VALUE;
1283 } else if(RCU_LPTIMERSRC_LXTAL == (RCU_CFG2 & RCU_CFG2_LPTIMERSEL)) {
1284 lptimer_freq = LXTAL_VALUE;
1285 } else if(RCU_LPTIMERSRC_IRC16MDIV == (RCU_CFG2 & RCU_CFG2_LPTIMERSEL)) {
1286 /* calculate IRC16MDIV clock frequency */
1287 idx = GET_BITS(RCU_CFG2, 18, 20);
1288 clk_exp = IRC16M_exp[idx];
1289 usart_freq = IRC16M_VALUE >> clk_exp;
1290 } else {
1291 }
1292 ck_freq = lptimer_freq;
1293 break;
1294 default:
1295 break;
1296 }
1297 return ck_freq;
1298 }
1299