1 /*!
2 \file gd32e50x_rcu.c
3 \brief RCU driver
4
5 \version 2020-03-10, V1.0.0, firmware for GD32E50X
6 \version 2020-08-26, V1.1.0, firmware for GD32E50x
7 \version 2020-09-20, V1.1.1, firmware for GD32E50x
8 \version 2021-03-23, V1.2.0, firmware for GD32E50x
9 */
10
11 /*
12 Copyright (c) 2021, GigaDevice Semiconductor Inc.
13
14 All rights reserved.
15
16 Redistribution and use in source and binary forms, with or without modification,
17 are permitted provided that the following conditions are met:
18
19 1. Redistributions of source code must retain the above copyright notice, this
20 list of conditions and the following disclaimer.
21 2. Redistributions in binary form must reproduce the above copyright notice,
22 this list of conditions and the following disclaimer in the documentation
23 and/or other materials provided with the distribution.
24 3. Neither the name of the copyright holder nor the names of its contributors
25 may be used to endorse or promote products derived from this software without
26 specific prior written permission.
27
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
31 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
32 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
33 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
37 OF SUCH DAMAGE.
38 */
39
40 #include "gd32e50x_rcu.h"
41
42 /* define clock source */
43 #define SEL_IRC8M ((uint16_t)0U) /* IRC8M is selected as CK_SYS */
44 #define SEL_HXTAL ((uint16_t)1U) /* HXTAL is selected as CK_SYS */
45 #define SEL_PLL ((uint16_t)2U) /* PLL is selected as CK_SYS */
46
47 /* define startup timeout count */
48 #define OSC_STARTUP_TIMEOUT ((uint32_t)0x000FFFFFU)
49 #define LXTAL_STARTUP_TIMEOUT ((uint32_t)0x03FFFFFFU)
50
51 /* ADC clock prescaler offset */
52 #define RCU_ADC_PSC_OFFSET ((uint32_t)14U)
53
54 /* RCU IRC8M adjust value mask and offset*/
55 #define RCU_IRC8M_ADJUST_MASK ((uint8_t)0x1FU)
56 #define RCU_IRC8M_ADJUST_OFFSET ((uint32_t)3U)
57
58 /* RCU PLL1 clock multiplication factor offset */
59 #define RCU_CFG1_PLL1MF_OFFSET ((uint32_t)8U)
60 /* RCU PREDV1 division factor offset*/
61 #define RCU_CFG1_PREDV1_OFFSET ((uint32_t)4U)
62
63 /*!
64 \brief deinitialize the RCU
65 \param[in] none
66 \param[out] none
67 \retval none
68 */
rcu_deinit(void)69 void rcu_deinit(void)
70 {
71 /* enable IRC8M */
72 RCU_CTL |= RCU_CTL_IRC8MEN;
73 while(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
74 }
75 RCU_CFG0 &= ~RCU_CFG0_SCS;
76 /* reset CTL register */
77 RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN);
78 RCU_CTL &= ~RCU_CTL_HXTALBPS;
79 #if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)
80 RCU_CTL &= ~(RCU_CTL_PLL1EN | RCU_CTL_PLL2EN);
81 #endif /* GD32E50X_CL and GD32EPRT and GD32E508 */
82 /* reset CFG0 register */
83 #if defined(GD32E50X_HD) || defined(GD32E50X_XD)
84 RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |
85 RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0 | RCU_CFG0_PLLMF |
86 RCU_CFG0_USBDPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_PLLMF_4 | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBDPSC_2);
87 #elif defined(GD32E50X_CL) || defined(GD32E508)
88 RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |
89 RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF |
90 RCU_CFG0_USBHSPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBHSPSC_2);
91 #elif defined(GD32EPRT)
92 RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |
93 RCU_CFG0_ADCPSC | RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF |
94 RCU_CFG0_USBDPSC | RCU_CFG0_CKOUT0SEL | RCU_CFG0_ADCPSC_2 | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5 | RCU_CFG0_USBDPSC_2);
95 #endif /* GD32E50X_HD and GD32E50X_XD */
96
97 /* reset INT and CFG1 register */
98 #if defined(GD32E50X_HD) || defined(GD32E50X_XD)
99 RCU_INT = 0x009f0000U;
100 RCU_CFG1 &= ~(RCU_CFG1_ADCPSC_3 | RCU_CFG1_PLLPRESEL);
101 RCU_CFG2 &= ~(RCU_CFG2_USART5SEL | RCU_CFG2_I2C2SEL);
102 #elif defined(GD32E50X_CL) || defined(GD32E508)
103 RCU_INT = 0x00ff0000U;
104 RCU_ADDINT = 0x00C00000U;
105 RCU_ADDCTL &= ~(RCU_ADDCTL_CK48MSEL | RCU_ADDCTL_USBHSSEL | RCU_ADDCTL_USBHSDV | RCU_ADDCTL_USBSWEN | RCU_ADDCTL_PLLUSBEN | RCU_ADDCTL_IRC48MEN);
106 RCU_ADDCFG &= ~(RCU_ADDCFG_PLLUSBPREDV | RCU_ADDCFG_PLLUSBPRESEL | RCU_ADDCFG_PLLUSBPREDVSEL | RCU_ADDCFG_PLLUSBMF);
107
108 RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF |
109 RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL | RCU_CFG1_SHRTIMERSEL | RCU_CFG1_PLL2MF_5 | RCU_CFG1_ADCPSC_3 |
110 RCU_CFG1_PLLPRESEL | RCU_CFG1_PLL2MF_4);
111 RCU_CFG2 &= ~(RCU_CFG2_USART5SEL | RCU_CFG2_I2C2SEL);
112 #elif defined(GD32EPRT)
113 RCU_INT = 0x00ff0000U;
114 RCU_ADDINT &= ~ (RCU_ADDINT_IRC48MSTBIC);
115 RCU_ADDCTL &= ~(RCU_ADDCTL_CK48MSEL | RCU_ADDCTL_IRC48MEN);
116
117 RCU_CFG1 &= ~(RCU_CFG1_PREDV0 | RCU_CFG1_PREDV1 | RCU_CFG1_PLL1MF | RCU_CFG1_PLL2MF |
118 RCU_CFG1_PREDV0SEL | RCU_CFG1_I2S1SEL | RCU_CFG1_I2S2SEL | RCU_CFG1_PLL2MF_5 | RCU_CFG1_ADCPSC_3 |
119 RCU_CFG1_PLLPRESEL | RCU_CFG1_PLL2MF_4);
120 RCU_CFG2 &= ~(RCU_CFG2_USART5SEL | RCU_CFG2_I2C2SEL);
121
122 #endif /* GD32E50X_HD and GD32E50X_XD */
123 }
124
125 /*!
126 \brief enable the peripherals clock
127 \param[in] periph: RCU peripherals, refer to rcu_periph_enum
128 only one parameter can be selected which is shown as below:
129 \arg RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock
130 \arg RCU_AF : alternate function clock
131 \arg RCU_CRC: CRC clock
132 \arg RCU_DMAx (x=0,1): DMA clock
133 \arg RCU_ENET: ENET clock(EPRT and CL series available)
134 \arg RCU_ENETTX: ENETTX clock(EPRT and CL series available)
135 \arg RCU_ENETRX: ENETRX clock(EPRT and CL series available)
136 \arg RCU_USBD: USBD clock(HD,XD and EPRT series available)
137 \arg RCU_USBHS: USBHS clock(CL series available)
138 \arg RCU_TMU: TMU clock
139 \arg RCU_SQPI: SQPI clock
140 \arg RCU_EXMC: EXMC clock
141 \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for EPRT series): TIMER clock
142 \arg RCU_WWDGT: WWDGT clock
143 \arg RCU_SPIx (x=0,1,2): SPI clock
144 \arg RCU_USARTx (x=0,1,2,5): USART clock
145 \arg RCU_UARTx (x=3,4): UART clock
146 \arg RCU_I2Cx (x=0,1,2): I2C clock
147 \arg RCU_CANx (x=0,1,2,CAN2 is only available for CL series,CANx is not avaliable for GD32EPRT): CAN clock
148 \arg RCU_PMU: PMU clock
149 \arg RCU_DAC: DAC clock
150 \arg RCU_RTC: RTC clock
151 \arg RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock
152 \arg RCU_SDIO: SDIO clock(not available for CL and EPRT series)
153 \arg RCU_CTC: CTC clock
154 \arg RCU_BKPI: BKP interface clock
155 \arg RCU_SHRTIMER: (not available for EPRT series):SHRTIMER clock
156 \arg RCU_CMP(CMP is only available for CL series):CMP clock
157 \param[out] none
158 \retval none
159 */
rcu_periph_clock_enable(rcu_periph_enum periph)160 void rcu_periph_clock_enable(rcu_periph_enum periph)
161 {
162 RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
163 }
164
165 /*!
166 \brief disable the peripherals clock
167 \param[in] periph: RCU peripherals, refer to rcu_periph_enum
168 only one parameter can be selected which is shown as below:
169 \arg RCU_GPIOx (x=A,B,C,D,E,F,G): GPIO ports clock
170 \arg RCU_AF : alternate function clock
171 \arg RCU_CRC: CRC clock
172 \arg RCU_DMAx (x=0,1): DMA clock
173 \arg RCU_ENET: ENET clock(EPRT and CL series available)
174 \arg RCU_ENETTX: ENETTX clock(EPRT and CL series available)
175 \arg RCU_ENETRX: ENETRX clock(EPRT and CL series available)
176 \arg RCU_USBD: USBD clock(HD,XD and EPRT series available)
177 \arg RCU_USBHS: USBHS clock(CL series available)
178 \arg RCU_TMU: TMU clock
179 \arg RCU_SQPI: SQPI clock
180 \arg RCU_EXMC: EXMC clock
181 \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for EPRT series): TIMER clock
182 \arg RCU_WWDGT: WWDGT clock
183 \arg RCU_SPIx (x=0,1,2): SPI clock
184 \arg RCU_USARTx (x=0,1,2,5): USART clock
185 \arg RCU_UARTx (x=3,4): UART clock
186 \arg RCU_I2Cx (x=0,1,2): I2C clock
187 \arg RCU_CANx (x=0,1,2,CAN2 is only available for CL series,CANx is not avaliable for GD32EPRT): CAN clock
188 \arg RCU_PMU: PMU clock
189 \arg RCU_DAC: DAC clock
190 \arg RCU_RTC: RTC clock
191 \arg RCU_ADCx (x=0,1,2,ADC2 is not available for CL series): ADC clock
192 \arg RCU_SDIO: SDIO clock(not available for CL and EPRT series)
193 \arg RCU_CTC: CTC clock
194 \arg RCU_BKPI: BKP interface clock
195 \arg RCU_SHRTIMER: (not available for EPRT series): SHRTIMER clock
196 \arg RCU_CMP(CMP is only available for CL series):CMP clock
197 \param[out] none
198 \retval none
199 */
rcu_periph_clock_disable(rcu_periph_enum periph)200 void rcu_periph_clock_disable(rcu_periph_enum periph)
201 {
202 RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
203 }
204
205 /*!
206 \brief enable the peripherals clock when sleep mode
207 \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum
208 only one parameter can be selected which is shown as below:
209 \arg RCU_FMC_SLP: FMC clock
210 \arg RCU_SRAM_SLP: SRAM clock
211 \param[out] none
212 \retval none
213 */
rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)214 void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)
215 {
216 RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
217 }
218
219 /*!
220 \brief disable the peripherals clock when sleep mode
221 \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum
222 only one parameter can be selected which is shown as below:
223 \arg RCU_FMC_SLP: FMC clock
224 \arg RCU_SRAM_SLP: SRAM clock
225 \param[out] none
226 \retval none
227 */
rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)228 void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)
229 {
230 RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
231 }
232
233 /*!
234 \brief reset the peripherals
235 \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
236 only one parameter can be selected which is shown as below:
237 \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports
238 \arg RCU_AFRST : reset alternate function clock
239 \arg RCU_ENETRST: reset ENET(EPRT and CL series available)
240 \arg RCU_USBDRST: reset USBD(HD,XD and EPRT series available)
241 \arg RCU_USBHSRST: reset USBHS(CL series available)
242 \arg RCU_TMURST: reset TMU
243 \arg RCU_SQPIRST: reset SQPI
244 \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for EPRT series): reset TIMER
245 \arg RCU_WWDGTRST: reset WWDGT
246 \arg RCU_SPIxRST (x=0,1,2): reset SPI
247 \arg RCU_USARTxRST (x=0,1,2,5): reset USART
248 \arg RCU_UARTxRST (x=3,4): reset UART
249 \arg RCU_I2CxRST (x=0,1): reset I2C
250 \arg RCU_PMURST: reset PMU
251 \arg RCU_DACRST: reset DAC
252 \arg RCU_ADCRST (x=0,1,2,ADC2 is not available for CL series): reset ADC
253 \arg RCU_CTCRST: reset CTC
254 \arg RCU_BKPIRST: reset BKPI
255 \arg RCU_SHRTIMERRST: (not available for EPRT series):reset SHRTIMERRST
256 \arg RCU_CMPRST(CMP is only available for CL series): reset CMP
257 \param[out] none
258 \retval none
259 */
rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)260 void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)
261 {
262 RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset));
263 }
264
265 /*!
266 \brief disable reset the peripheral
267 \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
268 only one parameter can be selected which is shown as below:
269 \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G): reset GPIO ports
270 \arg RCU_AFRST : reset alternate function clock
271 \arg RCU_ENETRST: reset ENET(CL series available)
272 \arg RCU_USBDRST: reset USBD(HD,XD and EPRT series available)
273 \arg RCU_USBHSRST: reset USBHS(CL series available)
274 \arg RCU_TMURST: reset TMU
275 \arg RCU_SQPIRST: reset SQPI
276 \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13,TIMER8..13 are not available for EPRT series): reset TIMER
277 \arg RCU_WWDGTRST: reset WWDGT
278 \arg RCU_SPIxRST (x=0,1,2): reset SPI
279 \arg RCU_USARTxRST (x=0,1,2,5): reset USART
280 \arg RCU_UARTxRST (x=3,4): reset UART
281 \arg RCU_I2CxRST (x=0,1): reset I2C
282 \arg RCU_PMURST: reset PMU
283 \arg RCU_DACRST: reset DAC
284 \arg RCU_ADCRST (x=0,1,2,ADC2 is not available for CL series): reset ADC
285 \arg RCU_CTCRST: reset CTC
286 \arg RCU_BKPIRST: reset BKPI
287 \arg RCU_SHRTIMERRST: (not available for EPRT series):reset SHRTIMERRST
288 \arg RCU_CMPRST(CMP is only available for CL series): reset CMP
289 \param[out] none
290 \retval none
291 */
rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset)292 void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset)
293 {
294 RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset));
295 }
296
297 /*!
298 \brief reset the BKP domain
299 \param[in] none
300 \param[out] none
301 \retval none
302 */
rcu_bkp_reset_enable(void)303 void rcu_bkp_reset_enable(void)
304 {
305 RCU_BDCTL |= RCU_BDCTL_BKPRST;
306 }
307
308 /*!
309 \brief disable the BKP domain reset
310 \param[in] none
311 \param[out] none
312 \retval none
313 */
rcu_bkp_reset_disable(void)314 void rcu_bkp_reset_disable(void)
315 {
316 RCU_BDCTL &= ~RCU_BDCTL_BKPRST;
317 }
318
319 /*!
320 \brief configure the system clock source
321 \param[in] ck_sys: system clock source select
322 only one parameter can be selected which is shown as below:
323 \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source
324 \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source
325 \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source
326 \param[out] none
327 \retval none
328 */
rcu_system_clock_source_config(uint32_t ck_sys)329 void rcu_system_clock_source_config(uint32_t ck_sys)
330 {
331 uint32_t reg;
332
333 reg = RCU_CFG0;
334 /* reset the SCS bits and set according to ck_sys */
335 reg &= ~RCU_CFG0_SCS;
336 RCU_CFG0 = (reg | ck_sys);
337 }
338
339 /*!
340 \brief get the system clock source
341 \param[in] none
342 \param[out] none
343 \retval which clock is selected as CK_SYS source
344 \arg RCU_SCSS_IRC8M: CK_IRC8M is selected as the CK_SYS source
345 \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source
346 \arg RCU_SCSS_PLL: CK_PLL is selected as the CK_SYS source
347 */
rcu_system_clock_source_get(void)348 uint32_t rcu_system_clock_source_get(void)
349 {
350 return (RCU_CFG0 & RCU_CFG0_SCSS);
351 }
352
353 /*!
354 \brief configure the AHB clock prescaler selection
355 \param[in] ck_ahb: AHB clock prescaler selection
356 only one parameter can be selected which is shown as below:
357 \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512
358 \param[out] none
359 \retval none
360 */
rcu_ahb_clock_config(uint32_t ck_ahb)361 void rcu_ahb_clock_config(uint32_t ck_ahb)
362 {
363 uint32_t reg;
364
365 reg = RCU_CFG0;
366
367 /* reset the AHBPSC bits and set according to ck_ahb */
368 reg &= ~RCU_CFG0_AHBPSC;
369 RCU_CFG0 = (reg | ck_ahb);
370 }
371
372 /*!
373 \brief configure the APB1 clock prescaler selection
374 \param[in] ck_apb1: APB1 clock prescaler selection
375 only one parameter can be selected which is shown as below:
376 \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1
377 \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1
378 \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1
379 \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1
380 \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1
381 \param[out] none
382 \retval none
383 */
rcu_apb1_clock_config(uint32_t ck_apb1)384 void rcu_apb1_clock_config(uint32_t ck_apb1)
385 {
386 uint32_t reg;
387
388 reg = RCU_CFG0;
389
390 /* reset the APB1PSC and set according to ck_apb1 */
391 reg &= ~RCU_CFG0_APB1PSC;
392 RCU_CFG0 = (reg | ck_apb1);
393 }
394
395 /*!
396 \brief configure the APB2 clock prescaler selection
397 \param[in] ck_apb2: APB2 clock prescaler selection
398 only one parameter can be selected which is shown as below:
399 \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2
400 \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2
401 \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2
402 \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2
403 \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2
404 \param[out] none
405 \retval none
406 */
rcu_apb2_clock_config(uint32_t ck_apb2)407 void rcu_apb2_clock_config(uint32_t ck_apb2)
408 {
409 uint32_t reg;
410
411 reg = RCU_CFG0;
412
413 /* reset the APB2PSC and set according to ck_apb2 */
414 reg &= ~RCU_CFG0_APB2PSC;
415 RCU_CFG0 = (reg | ck_apb2);
416 }
417
418 /*!
419 \brief configure the CK_OUT0 clock source
420 \param[in] ckout0_src: CK_OUT0 clock source selection
421 only one parameter can be selected which is shown as below:
422 \arg RCU_CKOUT0SRC_NONE: no clock selected
423 \arg RCU_CKOUT0SRC_CKSYS: system clock selected
424 \arg RCU_CKOUT0SRC_IRC8M: high speed 8M internal oscillator clock selected
425 \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected
426 \arg RCU_CKOUT0SRC_CKPLL_DIV2: CK_PLL/2 selected
427 \arg RCU_CKOUT0SRC_CKPLL1: CK_PLL1 selected (only available for CL and EPRT series)
428 \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected (only available for CL and EPRT series)
429 \arg RCU_CKOUT0SRC_EXT1: EXT1 selected (only available for CL and EPRT series)
430 \arg RCU_CKOUT0SRC_CKPLL2: CK_PLL2 clock selected (only available for CL and EPRT series)
431 \arg RCU_CKOUT0SRC_CKIRC48M: CK_IRC48M clock selected (only available for CL and EPRT series)
432 \arg RCU_CKOUT0SRC_CKIRC48M_DIV8: CK_IRC48M/8 clock selected (only available for CL and EPRT series)
433 \arg RCU_CKOUT0SRC_CKPLLUSB_DIV32: CK_PLLUSB/32 clock selected (only available for CL series)
434 \param[out] none
435 \retval none
436 */
rcu_ckout0_config(uint32_t ckout0_src)437 void rcu_ckout0_config(uint32_t ckout0_src)
438 {
439 uint32_t reg;
440
441 reg = RCU_CFG0;
442
443 /* reset the CKOUT0SRC, set according to ckout0_src */
444 reg &= ~RCU_CFG0_CKOUT0SEL;
445 RCU_CFG0 = (reg | ckout0_src);
446 }
447
448 /*!
449 \brief configure the main PLL clock
450 \param[in] pll_src: PLL clock source selection
451 only one parameter can be selected which is shown as below:
452 \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL
453 \arg RCU_PLLSRC_HXTAL_IRC48M: HXTAL or IRC48M selected as source clock of PLL
454 \param[in] pll_mul: PLL clock multiplication factor
455 only one parameter can be selected which is shown as below:
456 \arg RCU_PLL_MULx (XD series x = 2..63, CL series x = 2..14, 16..64, 6.5)
457 \param[out] none
458 \retval none
459 */
rcu_pll_config(uint32_t pll_src,uint32_t pll_mul)460 void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul)
461 {
462 uint32_t reg = 0U;
463
464 reg = RCU_CFG0;
465
466 /* PLL clock source and multiplication factor configuration */
467 reg &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
468 reg |= (pll_src | pll_mul);
469
470 RCU_CFG0 = reg;
471 }
472
473 /*!
474 \brief configure the PLL clock source preselection
475 \param[in] pll_presel: PLL clock source preselection
476 only one parameter can be selected which is shown as below:
477 \arg RCU_PLLPRESRC_HXTAL: HXTAL selected as PLL source clock
478 \arg RCU_PLLPRESRC_IRC48M: CK_PLL selected as PREDV0 input source clock
479 \param[out] none
480 \retval none
481 */
rcu_pllpresel_config(uint32_t pll_presel)482 void rcu_pllpresel_config(uint32_t pll_presel)
483 {
484 uint32_t reg = 0U;
485
486 reg = RCU_CFG1;
487
488 /* PLL clock source preselection */
489 reg &= ~RCU_CFG1_PLLPRESEL;
490 reg |= pll_presel;
491
492 RCU_CFG1 = reg;
493 }
494
495 #if defined(GD32E50X_HD) || defined(GD32E50X_XD)
496 /*!
497 \brief configure the PREDV0 division factor
498 \param[in] predv0_div: PREDV0 division factor
499 \arg RCU_PREDV0_DIVx, x = 1,2
500 \param[out] none
501 \retval none
502 */
rcu_predv0_config(uint32_t predv0_div)503 void rcu_predv0_config(uint32_t predv0_div)
504 {
505 uint32_t reg = 0U;
506
507 reg = RCU_CFG0;
508 /* reset PREDV0 bit */
509 reg &= ~RCU_CFG0_PREDV0;
510 if(RCU_PREDV0_DIV2 == predv0_div){
511 /* set the PREDV0 bit */
512 reg |= RCU_CFG0_PREDV0;
513 }
514
515 RCU_CFG0 = reg;
516 }
517 #elif defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)
518 /*!
519 \brief configure the PREDV0 division factor and clock source
520 \param[in] predv0_source: PREDV0 input clock source selection
521 only one parameter can be selected which is shown as below:
522 \arg RCU_PREDV0SRC_HXTAL_IRC48M: HXTAL or IRC48M selected as PREDV0 input source clock
523 \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock
524 \param[in] predv0_div: PREDV0 division factor
525 only one parameter can be selected which is shown as below:
526 \arg RCU_PREDV0_DIVx, x = 1..16
527 \param[out] none
528 \retval none
529 */
rcu_predv0_config(uint32_t predv0_source,uint32_t predv0_div)530 void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div)
531 {
532 uint32_t reg = 0U;
533
534 reg = RCU_CFG1;
535 /* reset PREDV0SEL and PREDV0 bits */
536 reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0);
537 /* set the PREDV0SEL and PREDV0 division factor */
538 reg |= (predv0_source | predv0_div);
539
540 RCU_CFG1 = reg;
541 }
542
543 /*!
544 \brief configure the PREDV1 division factor
545 \param[in] predv1_div: PREDV1 division factor
546 only one parameter can be selected which is shown as below:
547 \arg RCU_PREDV1_DIVx, x = 1..16
548 \param[out] none
549 \retval none
550 */
rcu_predv1_config(uint32_t predv1_div)551 void rcu_predv1_config(uint32_t predv1_div)
552 {
553 uint32_t reg = 0U;
554
555 reg = RCU_CFG1;
556 /* reset the PREDV1 bits */
557 reg &= ~RCU_CFG1_PREDV1;
558 /* set the PREDV1 division factor */
559 reg |= predv1_div;
560
561 RCU_CFG1 = reg;
562 }
563
564 /*!
565 \brief configure the PLL1 clock
566 \param[in] pll_mul: PLL clock multiplication factor
567 only one parameter can be selected which is shown as below:
568 \arg RCU_PLL1_MULx (x = 8..14,16,20)
569 \param[out] none
570 \retval none
571 */
rcu_pll1_config(uint32_t pll_mul)572 void rcu_pll1_config(uint32_t pll_mul)
573 {
574 RCU_CFG1 &= ~RCU_CFG1_PLL1MF;
575 RCU_CFG1 |= pll_mul;
576 }
577
578 /*!
579 \brief configure the PLL2 clock
580 \param[in] pll_mul: PLL clock multiplication factor
581 only one parameter can be selected which is shown as below:
582 \arg RCU_PLL2_MULx (x = 8..14,16,20,18..32,40,34..64,80)
583 \param[out] none
584 \retval none
585 */
rcu_pll2_config(uint32_t pll_mul)586 void rcu_pll2_config(uint32_t pll_mul)
587 {
588 RCU_CFG1 &= ~RCU_CFG1_PLL2MF;
589 RCU_CFG1 |= pll_mul;
590 }
591 #endif /* GD32E50X_HD and GD32E50X_XD */
592
593 #if defined(GD32E50X_CL) || defined(GD32E508)
594 /*!
595 \brief configure the PLLUSB clock source preselection
596 \param[in] pllusb_presel: PLLUSB clock source preselection
597 only one parameter can be selected which is shown as below:
598 \arg RCU_PLLUSBPRESRC_HXTAL: HXTAL selected as PLLUSB source clock
599 \arg RCU_PLLUSBPRESRC_IRC48M: IRC48M clock selected as PLLUSB source clock
600 \param[out] none
601 \retval none
602 */
rcu_pllusbpresel_config(uint32_t pllusb_presel)603 void rcu_pllusbpresel_config(uint32_t pllusb_presel)
604 {
605 uint32_t reg = 0U;
606
607 reg = RCU_ADDCFG;
608
609 /* PLLUSB clock source preselection */
610 reg &= ~RCU_ADDCFG_PLLUSBPRESEL;
611 reg |= pllusb_presel;
612
613 RCU_ADDCFG = reg;
614 }
615
616 /*!
617 \brief configure the PLLUSBPREDV division factor and clock source
618 \param[in] pllusbpredv_source: PLLUSBPREDV input clock source selection
619 only one parameter can be selected which is shown as below:
620 \arg RCU_PLLUSBPREDVSRC_HXTAL_IRC48M: HXTAL or IRC48M selected as PLLUSBPREDV input source clock
621 \arg RCU_PLLUSBPREDVSRC_CKPLL1: CK_PLL1 selected as PLLUSBPREDV input source clock
622 \param[in] pllusbpredv_div: PLLUSBPREDV division factor
623 only one parameter can be selected which is shown as below:
624 \arg RCU_PLLUSBPREDV_DIVx, x = 1..15
625 \param[out] none
626 \retval none
627 */
rcu_pllusbpredv_config(uint32_t pllusbpredv_source,uint32_t pllusbpredv_div)628 void rcu_pllusbpredv_config(uint32_t pllusbpredv_source, uint32_t pllusbpredv_div)
629 {
630 uint32_t reg = 0U;
631
632 reg = RCU_ADDCFG;
633 /* reset PLLUSBPRESEL and PLLUSBPREDV bits */
634 reg &= ~(RCU_ADDCFG_PLLUSBPREDVSEL | RCU_ADDCFG_PLLUSBPREDV);
635 /* set the PLLUSBPRESEL and PLLUSBPREDV division factor */
636 reg |= (pllusbpredv_source | pllusbpredv_div);
637
638 RCU_ADDCFG = reg;
639 }
640
641 /*!
642 \brief configure the PLLUSB clock
643 \param[in] pllusb_mul: PLLUSB clock multiplication factor
644 only one parameter can be selected which is shown as below:
645 \arg RCU_PLLUSB_MULx (x = 16,17..127)
646 \param[out] none
647 \retval none
648 */
rcu_pllusb_config(uint32_t pllusb_mul)649 void rcu_pllusb_config(uint32_t pllusb_mul)
650 {
651 RCU_ADDCFG &= ~RCU_ADDCFG_PLLUSBMF;
652 RCU_ADDCFG |= pllusb_mul;
653 }
654
655 #endif /* GD32E50X_CL and GD32E508 */
656
657 /*!
658 \brief configure the ADC prescaler factor
659 \param[in] adc_psc: ADC prescaler factor
660 only one parameter can be selected which is shown as below:
661 \arg RCU_CKADC_CKAPB2_DIV2: ADC prescaler select CK_APB2/2
662 \arg RCU_CKADC_CKAPB2_DIV4: ADC prescaler select CK_APB2/4
663 \arg RCU_CKADC_CKAPB2_DIV6: ADC prescaler select CK_APB2/6
664 \arg RCU_CKADC_CKAPB2_DIV8: ADC prescaler select CK_APB2/8
665 \arg RCU_CKADC_CKAPB2_DIV12: ADC prescaler select CK_APB2/12
666 \arg RCU_CKADC_CKAPB2_DIV16: ADC prescaler select CK_APB2/16
667 \arg RCU_CKADC_CKAHB_DIV5: ADC prescaler select CK_AHB/5
668 \arg RCU_CKADC_CKAHB_DIV6: ADC prescaler select CK_AHB/6
669 \arg RCU_CKADC_CKAHB_DIV10: ADC prescaler select CK_AHB/10
670 \arg RCU_CKADC_CKAHB_DIV20: ADC prescaler select CK_AHB/20
671 \param[out] none
672 \retval none
673 */
rcu_adc_clock_config(uint32_t adc_psc)674 void rcu_adc_clock_config(uint32_t adc_psc)
675 {
676 uint32_t reg0,reg1;
677
678 /* reset the ADCPSC bits */
679 reg0 = RCU_CFG0;
680 reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC);
681 reg1 = RCU_CFG1;
682 reg1 &= ~RCU_CFG1_ADCPSC_3;
683
684 /* set the ADC prescaler factor */
685 switch(adc_psc){
686 case RCU_CKADC_CKAPB2_DIV2:
687 case RCU_CKADC_CKAPB2_DIV4:
688 case RCU_CKADC_CKAPB2_DIV6:
689 case RCU_CKADC_CKAPB2_DIV8:
690 reg0 |= (adc_psc << RCU_ADC_PSC_OFFSET);
691 break;
692
693 case RCU_CKADC_CKAPB2_DIV12:
694 case RCU_CKADC_CKAPB2_DIV16:
695 adc_psc &= ~BIT(2);
696 reg0 |= ((adc_psc << RCU_ADC_PSC_OFFSET) | RCU_CFG0_ADCPSC_2);
697 break;
698
699 case RCU_CKADC_CKAHB_DIV5:
700 case RCU_CKADC_CKAHB_DIV6:
701 case RCU_CKADC_CKAHB_DIV10:
702 case RCU_CKADC_CKAHB_DIV20:
703 adc_psc &= ~BITS(2,3);
704 reg0 |= (adc_psc << RCU_ADC_PSC_OFFSET);
705 reg1 |= RCU_CFG1_ADCPSC_3;
706 break;
707
708 default:
709 break;
710 }
711
712 /* set the register */
713 RCU_CFG0 = reg0;
714 RCU_CFG1 = reg1;
715 }
716
717 /*!
718 \brief configure the USBD/USBHS prescaler factor
719 \param[in] usb_psc: USB prescaler factor
720 only one parameter can be selected which is shown as below:
721 \arg RCU_CKUSB_CKPLL_DIV1_5: USBD/USBHS prescaler select CK_PLL/1.5
722 \arg RCU_CKUSB_CKPLL_DIV1: USBD/USBHS prescaler select CK_PLL/1
723 \arg RCU_CKUSB_CKPLL_DIV2_5: USBD/USBHS prescaler select CK_PLL/2.5
724 \arg RCU_CKUSB_CKPLL_DIV2: USBD/USBHS prescaler select CK_PLL/2
725 \arg RCU_CKUSB_CKPLL_DIV3: USBD/USBHS prescaler select CK_PLL/3
726 \arg RCU_CKUSB_CKPLL_DIV3_5: USBD/USBHS prescaler select CK_PLL/3.5
727 \arg RCU_CKUSB_CKPLL_DIV4: USBD/USBHS prescaler select CK_PLL/4
728 \param[out] none
729 \retval none
730 */
rcu_usb_clock_config(uint32_t usb_psc)731 void rcu_usb_clock_config(uint32_t usb_psc)
732 {
733 uint32_t reg;
734
735 reg = RCU_CFG0;
736
737 /* configure the USBD/USBHS prescaler factor */
738 #if (defined(GD32E50X_HD) || defined(GD32E50X_XD)||defined(GD32EPRT))
739 reg &= ~RCU_CFG0_USBDPSC;
740 #elif defined(GD32E50X_CL) || defined(GD32E508)
741 reg &= ~RCU_CFG0_USBHSPSC;
742 #endif /* GD32E50X_HD and GD32E50X_XD and GD32EPRT */
743
744 RCU_CFG0 = (reg | usb_psc);
745 }
746
747 /*!
748 \brief configure the RTC clock source selection
749 \param[in] rtc_clock_source: RTC clock source selection
750 only one parameter can be selected which is shown as below:
751 \arg RCU_RTCSRC_NONE: no clock selected
752 \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock
753 \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock
754 \arg RCU_RTCSRC_HXTAL_DIV_128: CK_HXTAL/128 selected as RTC source clock
755 \param[out] none
756 \retval none
757 */
rcu_rtc_clock_config(uint32_t rtc_clock_source)758 void rcu_rtc_clock_config(uint32_t rtc_clock_source)
759 {
760 uint32_t reg;
761
762 reg = RCU_BDCTL;
763 /* reset the RTCSRC bits and set according to rtc_clock_source */
764 reg &= ~RCU_BDCTL_RTCSRC;
765 RCU_BDCTL = (reg | rtc_clock_source);
766 }
767
768 #ifndef GD32EPRT
769 /*!
770 \brief configure the SHRTIMER clock source selection
771 \param[in] shrtimer_clock_source: SHRTIMER clock source selection
772 only one parameter can be selected which is shown as below:
773 \arg RCU_SHRTIMERSRC_CKAPB2: APB2 clock selected as SHRTIMER source clock
774 \arg RCU_SHRTIMERSRC_CKSYS: system clock selected as SHRTIMER source clock
775 \param[out] none
776 \retval none
777 */
rcu_shrtimer_clock_config(uint32_t shrtimer_clock_source)778 void rcu_shrtimer_clock_config(uint32_t shrtimer_clock_source)
779 {
780 uint32_t reg;
781
782 reg = RCU_CFG1;
783 /* reset the I2S1SEL bit and set according to shrtimer_clock_source */
784 reg &= ~RCU_CFG1_SHRTIMERSEL;
785 RCU_CFG1 = (reg | shrtimer_clock_source);
786 }
787 #endif /* GD32EPRT */
788
789 /*!
790 \brief configure the USART5 clock source selection
791 \param[in] usart5_clock_source: USART5 clock source selection
792 only one parameter can be selected which is shown as below:
793 \arg RCU_USART5SRC_CKAPB2: APB2 clock selected as USART5 source clock
794 \arg RCU_USART5SRC_CKSYS: system clock selected as USART5 source clock
795 \arg RCU_USART5SRC_LXTAL: LXTAL clock selected as USART5 source clock
796 \arg RCU_USART5SRC_IRC8M: IRC8M clock selected as USART5 source clock
797 \param[out] none
798 \retval none
799 */
rcu_usart5_clock_config(uint32_t usart5_clock_source)800 void rcu_usart5_clock_config(uint32_t usart5_clock_source)
801 {
802 uint32_t reg;
803 reg = RCU_CFG2;
804 /* reset the I2S1SEL bit and set according to usart5_clock_source */
805 reg &= ~RCU_CFG2_USART5SEL;
806 RCU_CFG2 = (reg | usart5_clock_source);
807 }
808
809 /*!
810 \brief configure the I2C2 clock source selection
811 \param[in] i2c2_clock_source: I2C2 clock source selection
812 only one parameter can be selected which is shown as below:
813 \arg RCU_I2C2SRC_CKAPB1: APB1 clock selected as I2C2 source clock
814 \arg RCU_I2C2SRC_CKSYS: System clock selected as I2C2 source clock
815 \arg RCU_I2C2SRCSRC_CKIRC8M: CK_IRC8M clock selected as I2C2 source clock
816 \param[out] none
817 \retval none
818 */
rcu_i2c2_clock_config(uint32_t i2c2_clock_source)819 void rcu_i2c2_clock_config(uint32_t i2c2_clock_source)
820 {
821 uint32_t reg;
822
823 reg = RCU_CFG2;
824 /* reset the I2S1SEL bit and set according to i2c2_clock_source */
825 reg &= ~RCU_CFG2_I2C2SEL;
826 RCU_CFG2 = (reg | i2c2_clock_source);
827 }
828
829 /*!
830 \brief configure the CK48M clock source selection
831 \param[in] ck48m_clock_source: CK48M clock source selection
832 only one parameter can be selected which is shown as below:
833 \arg RCU_CK48MSRC_CKPLL: CK_PLL selected as CK48M source clock
834 \arg RCU_CK48MSRC_IRC48M: CK_IRC48M selected as CK48M source clock
835 \arg RCU_CK48MSRC_CKPLLUSB: (not available for EPRT series): CKPLLUSB selected as CK48M source clock
836 \arg RCU_CK48MSRC_CKPLL2: CKPLL2 selected as CK48M source clock
837 \param[out] none
838 \retval none
839 */
rcu_ck48m_clock_config(uint32_t ck48m_clock_source)840 void rcu_ck48m_clock_config(uint32_t ck48m_clock_source)
841 {
842 uint32_t reg;
843
844 reg = RCU_ADDCTL;
845 /* reset the CK48MSEL bit and set according to ck48m_clock_source */
846 reg &= ~RCU_ADDCTL_CK48MSEL;
847 RCU_ADDCTL = (reg | ck48m_clock_source);
848 }
849
850 #if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)
851 /*!
852 \brief configure the I2S1 clock source selection
853 \param[in] i2s_clock_source: I2S1 clock source selection
854 only one parameter can be selected which is shown as below:
855 \arg RCU_I2S1SRC_CKSYS: System clock selected as I2S1 source clock
856 \arg RCU_I2S1SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S1 source clock
857 \param[out] none
858 \retval none
859 */
rcu_i2s1_clock_config(uint32_t i2s_clock_source)860 void rcu_i2s1_clock_config(uint32_t i2s_clock_source)
861 {
862 uint32_t reg;
863
864 reg = RCU_CFG1;
865 /* reset the I2S1SEL bit and set according to i2s_clock_source */
866 reg &= ~RCU_CFG1_I2S1SEL;
867 RCU_CFG1 = (reg | i2s_clock_source);
868 }
869
870 /*!
871 \brief configure the I2S2 clock source selection
872 \param[in] i2s_clock_source: I2S2 clock source selection
873 only one parameter can be selected which is shown as below:
874 \arg RCU_I2S2SRC_CKSYS: system clock selected as I2S2 source clock
875 \arg RCU_I2S2SRC_CKPLL2_MUL2: CK_PLL2x2 selected as I2S2 source clock
876 \param[out] none
877 \retval none
878 */
rcu_i2s2_clock_config(uint32_t i2s_clock_source)879 void rcu_i2s2_clock_config(uint32_t i2s_clock_source)
880 {
881 uint32_t reg;
882
883 reg = RCU_CFG1;
884 /* reset the I2S2SEL bit and set according to i2s_clock_source */
885 reg &= ~RCU_CFG1_I2S2SEL;
886 RCU_CFG1 = (reg | i2s_clock_source);
887 }
888 #endif /* GD32E50X_CL and GD32E50X_EPRT and GD32E508 */
889
890 #if defined(GD32E50X_CL) || defined(GD32E508)
891 /*!
892 \brief configure the USBHSSEL source clock selection
893 \param[in] usbhssel_clock_source: USBHSSEL clock source selection
894 only one parameter can be selected which is shown as below:
895 \arg RCU_USBHSSRC_48M: 48M clock selected as USBHS source clock
896 \arg RCU_CK48MSRC_60M: 60M clock selected as USBHS source clock
897 \param[out] none
898 \retval none
899 */
rcu_usbhssel_config(uint32_t usbhssel_clock_source)900 void rcu_usbhssel_config(uint32_t usbhssel_clock_source)
901 {
902 uint32_t reg = 0U;
903
904 reg = RCU_ADDCTL;
905
906 /* USBHS clock source selection */
907 reg &= ~RCU_ADDCTL_USBHSSEL;
908 reg |= usbhssel_clock_source;
909
910 RCU_ADDCTL = reg;
911 }
912
913 /*!
914 \brief configure the USBHSDV division factor
915 \param[in] usbhs_dv: USBHSDV division factor
916 only one parameter can be selected which is shown as below:
917 \arg RCU_USBHSDV_DIV2: USBHSDV input source clock divided by 2
918 \arg RCU_USBHSDV_DIV4: USBHSDV input source clock divided by 4
919 \arg RCU_USBHSDV_DIV6: USBHSDV input source clock divided by 6
920 \arg RCU_USBHSDV_DIV8: USBHSDV input source clock divided by 8
921 \arg RCU_USBHSDV_DIV10: USBHSDV input source clock divided by 10
922 \arg RCU_USBHSDV_DIV12: USBHSDV input source clock divided by 12
923 \arg RCU_USBHSDV_DIV14: USBHSDV input source clock divided by 14
924 \arg RCU_USBHSDV_DIV16: USBHSDV input source clock divided by 16
925 \param[out] none
926 \retval none
927 */
rcu_usbdv_config(uint32_t usbhs_dv)928 void rcu_usbdv_config(uint32_t usbhs_dv)
929 {
930 uint32_t reg = 0U;
931
932 reg = RCU_ADDCTL;
933
934 /* usbhs input clock source division factor */
935 reg &= ~RCU_ADDCTL_USBHSDV;
936 reg |= usbhs_dv;
937
938 RCU_ADDCTL = reg;
939 }
940 #endif /* GD32E50X_CL and GD32E508 */
941
942 /*!
943 \brief get the clock stabilization and periphral reset flags
944 \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum
945 only one parameter can be selected which is shown as below:
946 \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag
947 \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag
948 \arg RCU_FLAG_PLLSTB: PLL stabilization flag
949 \arg RCU_FLAG_PLLUSBSTB: PLLUSB stabilization flag(CL series only)
950 \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag(CL series only)
951 \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag(CL series only)
952 \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag
953 \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag
954 \arg RCU_FLAG_IRC48MSTB: IRC48M stabilization flag
955 \arg RCU_FLAG_BORRST: BOR reset flag
956 \arg RCU_FLAG_EPRST: external PIN reset flag
957 \arg RCU_FLAG_PORRST: power reset flag
958 \arg RCU_FLAG_SWRST: software reset flag
959 \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag
960 \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag
961 \arg RCU_FLAG_LPRST: low-power reset flag
962 \param[out] none
963 \retval none
964 */
rcu_flag_get(rcu_flag_enum flag)965 FlagStatus rcu_flag_get(rcu_flag_enum flag)
966 {
967 /* get the rcu flag */
968 if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){
969 return SET;
970 }else{
971 return RESET;
972 }
973 }
974
975 /*!
976 \brief clear all the reset flag
977 \param[in] none
978 \param[out] none
979 \retval none
980 */
rcu_all_reset_flag_clear(void)981 void rcu_all_reset_flag_clear(void)
982 {
983 RCU_RSTSCK |= RCU_RSTSCK_RSTFC;
984 }
985
986 /*!
987 \brief get the clock stabilization interrupt and ckm flags
988 \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum
989 only one parameter can be selected which is shown as below:
990 \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag
991 \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag
992 \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag
993 \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag
994 \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag
995 \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag(CL series only)
996 \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag(CL series only)
997 \arg RCU_INT_FLAG_PLLUSBSTB: PLLUSB stabilization interrupt flag(CL series only)
998 \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag
999 \arg RCU_INT_FLAG_IRC48MSTB: IRC48M stabilization interrupt flag
1000 \param[out] none
1001 \retval FlagStatus: SET or RESET
1002 */
rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)1003 FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)
1004 {
1005 /* get the rcu interrupt flag */
1006 if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){
1007 return SET;
1008 }else{
1009 return RESET;
1010 }
1011 }
1012
1013 /*!
1014 \brief clear the interrupt flags
1015 \param[in] int_flag: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum
1016 only one parameter can be selected which is shown as below:
1017 \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear
1018 \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear
1019 \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear
1020 \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear
1021 \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear
1022 \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear(CL series only)
1023 \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear(CL series only)
1024 \arg RCU_INT_FLAG_PLLUSBSTB_CLR: PLLUS stabilization interrupt flag clear(CL series only)
1025 \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear
1026 \arg RCU_INT_FLAG_IRC48MSTB_CLR: IRC48M stabilization interrupt flag clear
1027 \param[out] none
1028 \retval none
1029 */
rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag)1030 void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag)
1031 {
1032 RCU_REG_VAL(int_flag) |= BIT(RCU_BIT_POS(int_flag));
1033 }
1034
1035 /*!
1036 \brief enable the stabilization interrupt
1037 \param[in] interrupt clock stabilization interrupt, refer to rcu_int_enum
1038 only one parameter can be selected which is shown as below:
1039 \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable
1040 \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
1041 \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable
1042 \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
1043 \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable
1044 \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only)
1045 \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only)
1046 \arg RCU_INT_PLLUSBSTB: PLLUSB stabilization interrupt enable(CL series only)
1047 \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable
1048 \param[out] none
1049 \retval none
1050 */
rcu_interrupt_enable(rcu_int_enum interrupt)1051 void rcu_interrupt_enable(rcu_int_enum interrupt)
1052 {
1053 RCU_REG_VAL(interrupt) |= BIT(RCU_BIT_POS(interrupt));
1054 }
1055
1056 /*!
1057 \brief disable the stabilization interrupt
1058 \param[in] interrupt clock stabilization interrupt, refer to rcu_int_enum
1059 only one parameter can be selected which is shown as below:
1060 \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable
1061 \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
1062 \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable
1063 \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
1064 \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable
1065 \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable(CL series only)
1066 \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable(CL series only)
1067 \arg RCU_INT_PLLUSBSTB: PLLUSB stabilization interrupt enable(CL series only)
1068 \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable
1069 \param[out] none
1070 \retval none
1071 */
rcu_interrupt_disable(rcu_int_enum interrupt)1072 void rcu_interrupt_disable(rcu_int_enum interrupt)
1073 {
1074 RCU_REG_VAL(interrupt) &= ~BIT(RCU_BIT_POS(interrupt));
1075 }
1076
1077 /*!
1078 \brief configure the LXTAL drive capability
1079 \param[in] lxtal_dricap: drive capability of LXTAL
1080 only one parameter can be selected which is shown as below:
1081 \arg RCU_LXTAL_LOWDRI: lower driving capability
1082 \arg RCU_LXTAL_MED_LOWDRI: medium low driving capability
1083 \arg RCU_LXTAL_MED_HIGHDRI: medium high driving capability
1084 \arg RCU_LXTAL_HIGHDRI: higher driving capability
1085 \param[out] none
1086 \retval none
1087 */
rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap)1088 void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap)
1089 {
1090 uint32_t reg;
1091
1092 reg = RCU_BDCTL;
1093
1094 /* reset the LXTALDRI bits and set according to lxtal_dricap */
1095 reg &= ~RCU_BDCTL_LXTALDRI;
1096 RCU_BDCTL = (reg | lxtal_dricap);
1097 }
1098
1099 /*!
1100 \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout
1101 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
1102 only one parameter can be selected which is shown as below:
1103 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
1104 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
1105 \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M)
1106 \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M)
1107 \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K)
1108 \arg RCU_PLL_CK: phase locked loop(PLL)
1109 \arg RCU_PLL1_CK: phase locked loop 1(CL series only)
1110 \arg RCU_PLL2_CK: phase locked loop 2(CL series only)
1111 \arg RCU_PLLUSB_CK: phase locked loop USB(CL series only)
1112 \param[out] none
1113 \retval ErrStatus: SUCCESS or ERROR
1114 */
rcu_osci_stab_wait(rcu_osci_type_enum osci)1115 ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci)
1116 {
1117 uint32_t stb_cnt = 0U;
1118 ErrStatus reval = ERROR;
1119 FlagStatus osci_stat = RESET;
1120
1121 switch(osci){
1122 /* wait HXTAL stable */
1123 case RCU_HXTAL:
1124 while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){
1125 osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB);
1126 stb_cnt++;
1127 }
1128
1129 /* check whether flag is set or not */
1130 if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){
1131 reval = SUCCESS;
1132 }
1133 break;
1134
1135 /* wait LXTAL stable */
1136 case RCU_LXTAL:
1137 while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){
1138 osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB);
1139 stb_cnt++;
1140 }
1141
1142 /* check whether flag is set or not */
1143 if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){
1144 reval = SUCCESS;
1145 }
1146 break;
1147
1148 /* wait IRC8M stable */
1149 case RCU_IRC8M:
1150 while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){
1151 osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB);
1152 stb_cnt++;
1153 }
1154
1155 /* check whether flag is set or not */
1156 if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){
1157 reval = SUCCESS;
1158 }
1159 break;
1160
1161 /* wait IRC48M stable */
1162 case RCU_IRC48M:
1163 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
1164 osci_stat = rcu_flag_get(RCU_FLAG_IRC48MSTB);
1165 stb_cnt++;
1166 }
1167
1168 /* check whether flag is set or not */
1169 if (RESET != rcu_flag_get(RCU_FLAG_IRC48MSTB)){
1170 reval = SUCCESS;
1171 }
1172 break;
1173
1174 /* wait IRC40K stable */
1175 case RCU_IRC40K:
1176 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
1177 osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB);
1178 stb_cnt++;
1179 }
1180
1181 /* check whether flag is set or not */
1182 if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){
1183 reval = SUCCESS;
1184 }
1185 break;
1186
1187 /* wait PLL stable */
1188 case RCU_PLL_CK:
1189 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
1190 osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB);
1191 stb_cnt++;
1192 }
1193
1194 /* check whether flag is set or not */
1195 if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){
1196 reval = SUCCESS;
1197 }
1198 break;
1199
1200 #if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)
1201 /* wait PLL1 stable */
1202 case RCU_PLL1_CK:
1203 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
1204 osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB);
1205 stb_cnt++;
1206 }
1207
1208 /* check whether flag is set or not */
1209 if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){
1210 reval = SUCCESS;
1211 }
1212 break;
1213 /* wait PLL2 stable */
1214 case RCU_PLL2_CK:
1215 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
1216 osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB);
1217 stb_cnt++;
1218 }
1219
1220 /* check whether flag is set or not */
1221 if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){
1222 reval = SUCCESS;
1223 }
1224 break;
1225 #endif /* GD32E50X_CL and GD32E50X_EPRT and GD32E508 */
1226 #if defined(GD32E50X_CL) || defined(GD32E508)
1227 case RCU_PLLUSB_CK:
1228 while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
1229 osci_stat = rcu_flag_get(RCU_FLAG_PLLUSBSTB);
1230 stb_cnt++;
1231 }
1232
1233 /* check whether flag is set or not */
1234 if(RESET != rcu_flag_get(RCU_FLAG_PLLUSBSTB)){
1235 reval = SUCCESS;
1236 }
1237 break;
1238 #endif /* GD32E50X_CL and GD32E508 */
1239
1240 default:
1241 break;
1242 }
1243
1244 /* return value */
1245 return reval;
1246 }
1247
1248 /*!
1249 \brief turn on the oscillator
1250 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
1251 only one parameter can be selected which is shown as below:
1252 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
1253 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
1254 \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M)
1255 \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M)
1256 \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K)
1257 \arg RCU_PLL_CK: phase locked loop(PLL)
1258 \arg RCU_PLL1_CK: phase locked loop 1(CL and EPRT series only)
1259 \arg RCU_PLL2_CK: phase locked loop 2(CL and EPRT series only)
1260 \arg RCU_PLLUSB_CK: phase locked loop USB(CL series only)
1261 \param[out] none
1262 \retval none
1263 */
rcu_osci_on(rcu_osci_type_enum osci)1264 void rcu_osci_on(rcu_osci_type_enum osci)
1265 {
1266 RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci));
1267 }
1268
1269 /*!
1270 \brief turn off the oscillator
1271 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
1272 only one parameter can be selected which is shown as below:
1273 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
1274 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
1275 \arg RCU_IRC8M: internal 8M RC oscillators(IRC8M)
1276 \arg RCU_IRC48M: internal 48M RC oscillators(IRC48M)
1277 \arg RCU_IRC40K: internal 40K RC oscillator(IRC40K)
1278 \arg RCU_PLL_CK: phase locked loop(PLL)
1279 \arg RCU_PLL1_CK: phase locked loop 1(CL and EPRT series only)
1280 \arg RCU_PLL2_CK: phase locked loop 2(CL and EPRT series only)
1281 \arg RCU_PLLUSB_CK: phase locked loop USB(CL series only)
1282 \param[out] none
1283 \retval none
1284 */
rcu_osci_off(rcu_osci_type_enum osci)1285 void rcu_osci_off(rcu_osci_type_enum osci)
1286 {
1287 RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci));
1288 }
1289
1290 /*!
1291 \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
1292 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
1293 only one parameter can be selected which is shown as below:
1294 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
1295 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
1296 \param[out] none
1297 \retval none
1298 */
rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)1299 void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)
1300 {
1301 uint32_t reg;
1302
1303 switch(osci){
1304 /* enable HXTAL to bypass mode */
1305 case RCU_HXTAL:
1306 reg = RCU_CTL;
1307 RCU_CTL &= ~RCU_CTL_HXTALEN;
1308 RCU_CTL = (reg | RCU_CTL_HXTALBPS);
1309 break;
1310 /* enable LXTAL to bypass mode */
1311 case RCU_LXTAL:
1312 reg = RCU_BDCTL;
1313 RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
1314 RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS);
1315 break;
1316 case RCU_IRC8M:
1317 case RCU_IRC48M:
1318 case RCU_IRC40K:
1319 case RCU_PLL_CK:
1320 #if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)
1321 case RCU_PLL1_CK:
1322 case RCU_PLL2_CK:
1323 #endif /* GD32E50X_CL and GD32EPRT and GD32E508 */
1324 break;
1325 default:
1326 break;
1327 }
1328 }
1329
1330 /*!
1331 \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
1332 \param[in] osci: oscillator types, refer to rcu_osci_type_enum
1333 only one parameter can be selected which is shown as below:
1334 \arg RCU_HXTAL: high speed crystal oscillator(HXTAL)
1335 \arg RCU_LXTAL: low speed crystal oscillator(LXTAL)
1336 \param[out] none
1337 \retval none
1338 */
rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)1339 void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)
1340 {
1341 uint32_t reg;
1342
1343 switch(osci){
1344 /* disable HXTAL to bypass mode */
1345 case RCU_HXTAL:
1346 reg = RCU_CTL;
1347 RCU_CTL &= ~RCU_CTL_HXTALEN;
1348 RCU_CTL = (reg & ~RCU_CTL_HXTALBPS);
1349 break;
1350 /* disable LXTAL to bypass mode */
1351 case RCU_LXTAL:
1352 reg = RCU_BDCTL;
1353 RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
1354 RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS);
1355 break;
1356 case RCU_IRC8M:
1357 case RCU_IRC48M:
1358 case RCU_IRC40K:
1359 case RCU_PLL_CK:
1360 #if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)
1361 case RCU_PLL1_CK:
1362 case RCU_PLL2_CK:
1363 #endif /* GD32E50X_CL and GD32EPRT and GD32E508 */
1364 break;
1365 default:
1366 break;
1367 }
1368 }
1369
1370 /*!
1371 \brief enable the HXTAL clock monitor
1372 \param[in] none
1373 \param[out] none
1374 \retval none
1375 */
1376
rcu_hxtal_clock_monitor_enable(void)1377 void rcu_hxtal_clock_monitor_enable(void)
1378 {
1379 RCU_CTL |= RCU_CTL_CKMEN;
1380 }
1381
1382 /*!
1383 \brief disable the HXTAL clock monitor
1384 \param[in] none
1385 \param[out] none
1386 \retval none
1387 */
rcu_hxtal_clock_monitor_disable(void)1388 void rcu_hxtal_clock_monitor_disable(void)
1389 {
1390 RCU_CTL &= ~RCU_CTL_CKMEN;
1391 }
1392
1393 /*!
1394 \brief set the IRC8M adjust value
1395 \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F
1396 \arg 0x00 - 0x1F
1397 \param[out] none
1398 \retval none
1399 */
rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval)1400 void rcu_irc8m_adjust_value_set(uint32_t irc8m_adjval)
1401 {
1402 uint32_t reg;
1403
1404 reg = RCU_CTL;
1405 /* reset the IRC8MADJ bits and set according to irc8m_adjval */
1406 reg &= ~RCU_CTL_IRC8MADJ;
1407 RCU_CTL = (reg | ((irc8m_adjval & RCU_IRC8M_ADJUST_MASK) << RCU_IRC8M_ADJUST_OFFSET));
1408 }
1409
1410 /*!
1411 \brief deep-sleep mode voltage select
1412 \param[in] dsvol: deep sleep mode voltage
1413 only one parameter can be selected which is shown as below:
1414 \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V
1415 \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V
1416 \arg RCU_DEEPSLEEP_V_0_8: the core voltage is 0.8V
1417 \arg RCU_DEEPSLEEP_V_0_7: the core voltage is 0.7V
1418 \param[out] none
1419 \retval none
1420 */
rcu_deepsleep_voltage_set(uint32_t dsvol)1421 void rcu_deepsleep_voltage_set(uint32_t dsvol)
1422 {
1423 dsvol &= RCU_DSV_DSLPVS;
1424 RCU_DSV = dsvol;
1425 }
1426
1427 /*!
1428 \brief get the system clock, bus and peripheral clock frequency
1429 \param[in] clock: the clock frequency which to get
1430 only one parameter can be selected which is shown as below:
1431 \arg CK_SYS: system clock frequency
1432 \arg CK_AHB: AHB clock frequency
1433 \arg CK_APB1: APB1 clock frequency
1434 \arg CK_APB2: APB2 clock frequency
1435 \arg CK_USART: USART5 clock frequency
1436 \param[out] none
1437 \retval clock frequency of system, AHB, APB1, APB2
1438 */
rcu_clock_freq_get(rcu_clock_freq_enum clock)1439 uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock)
1440 {
1441 uint32_t sws, ck_freq = 0U;
1442 uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq;
1443 uint32_t usart_freq = 0U;
1444 uint32_t pllsel, pllpresel, predv0sel, pllmf,ck_src, idx, clk_exp;
1445 #if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)
1446 uint32_t predv0, predv1, pll1mf;
1447 #endif /* GD32E50X_CL and GD32EPRT and GD32E508*/
1448
1449 /* exponent of AHB, APB1 and APB2 clock divider */
1450 uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
1451 uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1452 uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
1453
1454 sws = GET_BITS(RCU_CFG0, 2, 3);
1455 switch(sws){
1456 /* IRC8M is selected as CK_SYS */
1457 case SEL_IRC8M:
1458 cksys_freq = IRC8M_VALUE;
1459 break;
1460 /* HXTAL is selected as CK_SYS */
1461 case SEL_HXTAL:
1462 cksys_freq = HXTAL_VALUE;
1463 break;
1464 /* PLL is selected as CK_SYS */
1465 case SEL_PLL:
1466 /* PLL clock source selection, HXTAL, IRC48M or IRC8M/2 */
1467 pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL);
1468
1469 if(RCU_PLLSRC_HXTAL_IRC48M == pllsel) {
1470 /* PLL clock source is HXTAL or IRC48M */
1471 pllpresel = (RCU_CFG1 & RCU_CFG1_PLLPRESEL);
1472
1473 if(RCU_PLLPRESRC_HXTAL == pllpresel){
1474 /* PLL clock source is HXTAL */
1475 ck_src = HXTAL_VALUE;
1476 }else{
1477 /* PLL clock source is IRC48 */
1478 ck_src = IRC48M_VALUE;
1479 }
1480
1481 #if defined(GD32E50X_HD) || defined(GD32E50X_XD)
1482 predv0sel = (RCU_CFG0 & RCU_CFG0_PREDV0);
1483 /* PREDV0 input source clock divided by 2 */
1484 if(RCU_CFG0_PREDV0 == predv0sel){
1485 ck_src = HXTAL_VALUE/2U;
1486 }
1487 #elif defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)
1488 predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL);
1489 /* source clock use PLL1 */
1490 if(RCU_PREDV0SRC_CKPLL1 == predv0sel){
1491 predv1 = ((RCU_CFG1 & RCU_CFG1_PREDV1) >> RCU_CFG1_PREDV1_OFFSET) + 1U;
1492 pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> RCU_CFG1_PLL1MF_OFFSET) + 2U;
1493 if(15U == pll1mf){
1494 pll1mf = 20U;
1495 }
1496 ck_src = (ck_src/predv1)*pll1mf;
1497 }
1498 predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U;
1499 ck_src /= predv0;
1500 #endif /* GD32E50X_HD and GD32E50X_XD */
1501 }else{
1502 /* PLL clock source is IRC8M/2 */
1503 ck_src = IRC8M_VALUE/2U;
1504 }
1505
1506 /* PLL multiplication factor */
1507 pllmf = GET_BITS(RCU_CFG0, 18, 21);
1508 if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){
1509 pllmf |= 0x10U;
1510 }
1511 if((RCU_CFG0 & RCU_CFG0_PLLMF_5)){
1512 pllmf |= 0x20U;
1513 }
1514 if(pllmf < 15U){
1515 pllmf += 2U;
1516 }else if((pllmf >= 15U) && (pllmf <= 64U)){
1517 pllmf += 1U;
1518 }
1519 cksys_freq = ck_src*pllmf;
1520 #if defined(GD32E50X_CL) || defined(GD32EPRT) || defined(GD32E508)
1521 if(15U == pllmf){
1522 cksys_freq = ck_src*6U + ck_src/2U;
1523 }
1524 #endif /* GD32E50X_CL and GD32EPRT and GD32E508 */
1525
1526 break;
1527 /* IRC8M is selected as CK_SYS */
1528 default:
1529 cksys_freq = IRC8M_VALUE;
1530 break;
1531 }
1532
1533 /* calculate AHB clock frequency */
1534 idx = GET_BITS(RCU_CFG0, 4, 7);
1535 clk_exp = ahb_exp[idx];
1536 ahb_freq = cksys_freq >> clk_exp;
1537
1538 /* calculate APB1 clock frequency */
1539 idx = GET_BITS(RCU_CFG0, 8, 10);
1540 clk_exp = apb1_exp[idx];
1541 apb1_freq = ahb_freq >> clk_exp;
1542
1543 /* calculate APB2 clock frequency */
1544 idx = GET_BITS(RCU_CFG0, 11, 13);
1545 clk_exp = apb2_exp[idx];
1546 apb2_freq = ahb_freq >> clk_exp;
1547
1548 /* return the clocks frequency */
1549 switch(clock){
1550 case CK_SYS:
1551 ck_freq = cksys_freq;
1552 break;
1553 case CK_AHB:
1554 ck_freq = ahb_freq;
1555 break;
1556 case CK_APB1:
1557 ck_freq = apb1_freq;
1558 break;
1559 case CK_APB2:
1560 ck_freq = apb2_freq;
1561 break;
1562 case CK_USART:
1563 /* calculate USART5 clock frequency */
1564 if(RCU_USART5SRC_CKAPB2 == (RCU_CFG2 & RCU_CFG2_USART5SEL)){
1565 usart_freq = apb2_freq;
1566 }else if(RCU_USART5SRC_CKSYS == (RCU_CFG2 & RCU_CFG2_USART5SEL)){
1567 usart_freq = cksys_freq;
1568 }else if(RCU_USART5SRC_LXTAL == (RCU_CFG2 & RCU_CFG2_USART5SEL)){
1569 usart_freq = LXTAL_VALUE;
1570 }else if(RCU_USART5SRC_IRC8M == (RCU_CFG2 & RCU_CFG2_USART5SEL)){
1571 usart_freq = IRC8M_VALUE;
1572 }else{
1573 }
1574 ck_freq = usart_freq;
1575 break;
1576 default:
1577 break;
1578 }
1579 return ck_freq;
1580 }
1581