1
0

gd32f10x_rcu.c 43 KB

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