gd32f30x_rcu.c 43 KB

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