gd32f3x0_rcu.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154
  1. /*!
  2. \file gd32f3x0_rcu.c
  3. \brief RCU driver
  4. */
  5. /*
  6. Copyright (C) 2017 GigaDevice
  7. 2017-06-06, V1.0.0, firmware for GD32F3x0
  8. */
  9. #include "gd32f3x0_rcu.h"
  10. /* define clock source */
  11. #define SEL_IRC8M 0x00U
  12. #define SEL_HXTAL 0x01U
  13. #define SEL_PLL 0x02U
  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_CTL0 |= RCU_CTL0_IRC8MEN;
  27. while(0U == (RCU_CTL0 & RCU_CTL0_IRC8MSTB)){
  28. }
  29. /* reset RCU */
  30. RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |\
  31. RCU_CFG0_ADCPSC | RCU_CFG0_CKOUTSEL | RCU_CFG0_CKOUTDIV | RCU_CFG0_PLLDV);
  32. RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF4 | RCU_CFG0_PLLDV);
  33. #if (defined(GD32F350))
  34. RCU_CFG0 &= ~(RCU_CFG0_USBFSPSC);
  35. RCU_CFG2 &= ~(RCU_CFG2_CECSEL | RCU_CFG2_USBFSPSC2);
  36. #endif /* GD32F350 */
  37. RCU_CTL0 &= ~(RCU_CTL0_HXTALEN | RCU_CTL0_CKMEN | RCU_CTL0_PLLEN | RCU_CTL0_HXTALBPS);
  38. RCU_CFG1 &= ~(RCU_CFG1_PREDV | RCU_CFG1_PLLMF5 | RCU_CFG1_PLLPRESEL);
  39. RCU_CFG2 &= ~(RCU_CFG2_USART0SEL | RCU_CFG2_ADCSEL);
  40. RCU_CFG2 &= ~RCU_CFG2_IRC28MDIV;
  41. RCU_CFG2 &= ~RCU_CFG2_ADCPSC2;
  42. RCU_CTL1 &= ~RCU_CTL1_IRC28MEN;
  43. RCU_ADDCTL &= ~RCU_ADDCTL_IRC48MEN;
  44. RCU_INT = 0x00000000U;
  45. RCU_ADDINT = 0x00000000U;
  46. }
  47. /*!
  48. \brief enable the peripherals clock
  49. \param[in] periph: RCU peripherals, refer to rcu_periph_enum
  50. only one parameter can be selected which is shown as below:
  51. \arg RCU_GPIOx (x=A,B,C,D,F): GPIO ports clock
  52. \arg RCU_DMA: DMA clock
  53. \arg RCU_CRC: CRC clock
  54. \arg RCU_TSI: TSI clock
  55. \arg RCU_CFGCMP: CFGCMP clock
  56. \arg RCU_ADC: ADC clock
  57. \arg RCU_TIMERx (x=0,1,2,5,13,14,15,16): TIMER clock (RCU_TIMER5 only for GD32F350)
  58. \arg RCU_SPIx (x=0,1,2): SPI clock
  59. \arg RCU_USARTx (x=0,1): USART clock
  60. \arg RCU_WWDGT: WWDGT clock
  61. \arg RCU_I2Cx (x=0,1,2): I2C clock
  62. \arg RCU_USBFS: USBFS clock (only for GD32F350)
  63. \arg RCU_PMU: PMU clock
  64. \arg RCU_DAC: DAC clock (only for GD32F350)
  65. \arg RCU_CEC: CEC clock (only for GD32F350)
  66. \arg RCU_CTC: CTC clock
  67. \arg RCU_RTC: RTC clock
  68. \param[out] none
  69. \retval none
  70. */
  71. void rcu_periph_clock_enable(rcu_periph_enum periph)
  72. {
  73. RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
  74. }
  75. /*!
  76. \brief disable the peripherals clock
  77. \param[in] periph: RCU peripherals, refer to rcu_periph_enum
  78. only one parameter can be selected which is shown as below:
  79. \arg RCU_GPIOx (x=A,B,C,D,F): GPIO ports clock
  80. \arg RCU_DMA: DMA clock
  81. \arg RCU_CRC: CRC clock
  82. \arg RCU_TSI: TSI clock
  83. \arg RCU_CFGCMP: CFGCMP clock
  84. \arg RCU_ADC: ADC clock
  85. \arg RCU_TIMERx (x=0,1,2,5,13,14,15,16): TIMER clock (RCU_TIMER5 only for GD32F350)
  86. \arg RCU_SPIx (x=0,1,2): SPI clock
  87. \arg RCU_USARTx (x=0,1): USART clock
  88. \arg RCU_WWDGT: WWDGT clock
  89. \arg RCU_I2Cx (x=0,1,2): I2C clock
  90. \arg RCU_USBFS: USBFS clock (only for GD32F350)
  91. \arg RCU_PMU: PMU clock
  92. \arg RCU_DAC: DAC clock (only for GD32F350)
  93. \arg RCU_CEC: CEC clock (only for GD32F350)
  94. \arg RCU_CTC: CTC clock
  95. \arg RCU_RTC: RTC clock
  96. \param[out] none
  97. \retval none
  98. */
  99. void rcu_periph_clock_disable(rcu_periph_enum periph)
  100. {
  101. RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
  102. }
  103. /*!
  104. \brief enable the peripherals clock when sleep mode
  105. \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum
  106. only one parameter can be selected which is shown as below:
  107. \arg RCU_FMC_SLP: FMC clock
  108. \arg RCU_SRAM_SLP: SRAM clock
  109. \param[out] none
  110. \retval none
  111. */
  112. void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)
  113. {
  114. RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
  115. }
  116. /*!
  117. \brief disable the peripherals clock when sleep mode
  118. \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum
  119. only one parameter can be selected which is shown as below:
  120. \arg RCU_FMC_SLP: FMC clock
  121. \arg RCU_SRAM_SLP: SRAM clock
  122. \param[out] none
  123. \retval none
  124. */
  125. void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)
  126. {
  127. RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
  128. }
  129. /*!
  130. \brief reset the peripherals
  131. \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
  132. only one parameter can be selected which is shown as below:
  133. \arg RCU_GPIOxRST (x=A,B,C,D,F): reset GPIO ports
  134. \arg RCU_TSIRST: reset TSI
  135. \arg RCU_CFGCMPRST: reset CFGCMP
  136. \arg RCU_ADCRST: reset ADC
  137. \arg RCU_TIMERxRST (x=0,1,2,5,13,14,15,16): reset TIMER (RCU_TIMER5 only for GD32F350)
  138. \arg RCU_SPIxRST (x=0,1,2): reset SPI
  139. \arg RCU_USARTxRST (x=0,1): reset USART
  140. \arg RCU_WWDGTRST: reset WWDGT
  141. \arg RCU_I2CxRST (x=0,1,2): reset I2C
  142. \arg RCU_USBFSRST: reset USBFS (only for GD32F350)
  143. \arg RCU_PMURST: reset PMU
  144. \arg RCU_DACRST: reset DAC (only for GD32F350)
  145. \arg RCU_CECRST: reset CEC (only for GD32F350)
  146. \arg RCU_CTCRST: reset CTC
  147. \param[out] none
  148. \retval none
  149. */
  150. void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)
  151. {
  152. RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset));
  153. }
  154. /*!
  155. \brief disable reset the peripheral
  156. \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
  157. only one parameter can be selected which is shown as below:
  158. \arg RCU_GPIOxRST (x=A,B,C,D,F): reset GPIO ports
  159. \arg RCU_TSIRST: reset TSI
  160. \arg RCU_CFGCMPRST: reset CFGCMP
  161. \arg RCU_ADCRST: reset ADC
  162. \arg RCU_TIMERxRST (x=0,1,2,5,13,14,15,16): reset TIMER (RCU_TIMER5 only for GD32F350)
  163. \arg RCU_SPIxRST (x=0,1,2): reset SPI
  164. \arg RCU_USARTxRST (x=0,1): reset USART
  165. \arg RCU_WWDGTRST: reset WWDGT
  166. \arg RCU_I2CxRST (x=0,1,2): reset I2C
  167. \arg RCU_USBFSRST: reset USBFS (only for GD32F350)
  168. \arg RCU_PMURST: reset PMU
  169. \arg RCU_DACRST: reset DAC (only for GD32F350)
  170. \arg RCU_CECRST: reset CEC (only for GD32F350)
  171. \arg RCU_CTCRST: reset CTC
  172. \param[out] none
  173. \retval none
  174. */
  175. void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset)
  176. {
  177. RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset));
  178. }
  179. /*!
  180. \brief reset the BKP
  181. \param[in] none
  182. \param[out] none
  183. \retval none
  184. */
  185. void rcu_bkp_reset_enable(void)
  186. {
  187. RCU_BDCTL |= RCU_BDCTL_BKPRST;
  188. }
  189. /*!
  190. \brief disable the BKP reset
  191. \param[in] none
  192. \param[out] none
  193. \retval none
  194. */
  195. void rcu_bkp_reset_disable(void)
  196. {
  197. RCU_BDCTL &= ~RCU_BDCTL_BKPRST;
  198. }
  199. /*!
  200. \brief configure the system clock source
  201. \param[in] ck_sys: system clock source select
  202. only one parameter can be selected which is shown as below:
  203. \arg RCU_CKSYSSRC_IRC8M: select CK_IRC8M as the CK_SYS source
  204. \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source
  205. \arg RCU_CKSYSSRC_PLL: select CK_PLL as the CK_SYS source
  206. \param[out] none
  207. \retval none
  208. */
  209. void rcu_system_clock_source_config(uint32_t ck_sys)
  210. {
  211. uint32_t cksys_source = 0U;
  212. cksys_source = RCU_CFG0;
  213. /* reset the SCS bits and set according to ck_sys */
  214. cksys_source &= ~RCU_CFG0_SCS;
  215. RCU_CFG0 = (ck_sys | cksys_source);
  216. }
  217. /*!
  218. \brief get the system clock source
  219. \param[in] none
  220. \param[out] none
  221. \retval which clock is selected as CK_SYS source
  222. \arg RCU_SCSS_IRC8M: select CK_IRC8M as the CK_SYS source
  223. \arg RCU_SCSS_HXTAL: select CK_HXTAL as the CK_SYS source
  224. \arg RCU_SCSS_PLL: select CK_PLL as the CK_SYS source
  225. */
  226. uint32_t rcu_system_clock_source_get(void)
  227. {
  228. return (RCU_CFG0 & RCU_CFG0_SCSS);
  229. }
  230. /*!
  231. \brief configure the AHB clock prescaler selection
  232. \param[in] ck_ahb: AHB clock prescaler selection
  233. \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512
  234. \param[out] none
  235. \retval none
  236. */
  237. void rcu_ahb_clock_config(uint32_t ck_ahb)
  238. {
  239. uint32_t ahbpsc = 0U;
  240. ahbpsc = RCU_CFG0;
  241. /* reset the AHBPSC bits and set according to ck_ahb */
  242. ahbpsc &= ~RCU_CFG0_AHBPSC;
  243. RCU_CFG0 = (ck_ahb | ahbpsc);
  244. }
  245. /*!
  246. \brief configure the APB1 clock prescaler selection
  247. \param[in] ck_apb1: APB1 clock prescaler selection
  248. \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1
  249. \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1
  250. \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1
  251. \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1
  252. \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1
  253. \param[out] none
  254. \retval none
  255. */
  256. void rcu_apb1_clock_config(uint32_t ck_apb1)
  257. {
  258. uint32_t apb1psc = 0U;
  259. apb1psc = RCU_CFG0;
  260. /* reset the APB1PSC and set according to ck_apb1 */
  261. apb1psc &= ~RCU_CFG0_APB1PSC;
  262. RCU_CFG0 = (ck_apb1 | apb1psc);
  263. }
  264. /*!
  265. \brief configure the APB2 clock prescaler selection
  266. \param[in] ck_apb2: APB2 clock prescaler selection
  267. \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2
  268. \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2
  269. \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2
  270. \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2
  271. \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2
  272. \param[out] none
  273. \retval none
  274. */
  275. void rcu_apb2_clock_config(uint32_t ck_apb2)
  276. {
  277. uint32_t apb2psc = 0U;
  278. apb2psc = RCU_CFG0;
  279. /* reset the APB2PSC and set according to ck_apb2 */
  280. apb2psc &= ~RCU_CFG0_APB2PSC;
  281. RCU_CFG0 = (ck_apb2 | apb2psc);
  282. }
  283. /*!
  284. \brief configure the ADC clock prescaler selection
  285. \param[in] ck_adc: ADC clock prescaler selection, refer to rcu_adc_clock_enum
  286. \arg RCU_ADCCK_IRC28M_DIV2: select CK_IRC28M/2 as CK_ADC
  287. \arg RCU_ADCCK_IRC28M: select CK_IRC28M as CK_ADC
  288. \arg RCU_ADCCK_APB2_DIV2: select CK_APB2/2 as CK_ADC
  289. \arg RCU_ADCCK_APB2_DIV3: select CK_APB2/3 as CK_ADC
  290. \arg RCU_ADCCK_APB2_DIV4: select CK_APB2/4 as CK_ADC
  291. \arg RCU_ADCCK_APB2_DIV5: select CK_APB2/5 as CK_ADC
  292. \arg RCU_ADCCK_APB2_DIV6: select CK_APB2/6 as CK_ADC
  293. \arg RCU_ADCCK_APB2_DIV7: select CK_APB2/7 as CK_ADC
  294. \arg RCU_ADCCK_APB2_DIV8: select CK_APB2/8 as CK_ADC
  295. \arg RCU_ADCCK_APB2_DIV9: select CK_APB2/9 as CK_ADC
  296. \param[out] none
  297. \retval none
  298. */
  299. void rcu_adc_clock_config(rcu_adc_clock_enum ck_adc)
  300. {
  301. /* reset the ADCPSC, ADCSEL, IRC28MDIV bits */
  302. RCU_CFG0 &= ~RCU_CFG0_ADCPSC;
  303. RCU_CFG2 &= ~(RCU_CFG2_ADCSEL | RCU_CFG2_IRC28MDIV | RCU_CFG2_ADCPSC2);
  304. /* set the ADC clock according to ck_adc */
  305. switch(ck_adc){
  306. case RCU_ADCCK_IRC28M_DIV2:
  307. RCU_CFG2 &= ~RCU_CFG2_IRC28MDIV;
  308. RCU_CFG2 &= ~RCU_CFG2_ADCSEL;
  309. break;
  310. case RCU_ADCCK_IRC28M:
  311. RCU_CFG2 |= RCU_CFG2_IRC28MDIV;
  312. RCU_CFG2 &= ~RCU_CFG2_ADCSEL;
  313. break;
  314. case RCU_ADCCK_APB2_DIV2:
  315. RCU_CFG0 |= RCU_ADC_CKAPB2_DIV2;
  316. RCU_CFG2 |= RCU_CFG2_ADCSEL;
  317. break;
  318. case RCU_ADCCK_APB2_DIV3:
  319. RCU_CFG0 |= RCU_ADC_CKAPB2_DIV2;
  320. RCU_CFG2 |= RCU_CFG2_ADCPSC2;
  321. RCU_CFG2 |= RCU_CFG2_ADCSEL;
  322. break;
  323. case RCU_ADCCK_APB2_DIV4:
  324. RCU_CFG0 |= RCU_ADC_CKAPB2_DIV4;
  325. RCU_CFG2 |= RCU_CFG2_ADCSEL;
  326. break;
  327. case RCU_ADCCK_APB2_DIV5:
  328. RCU_CFG0 |= RCU_ADC_CKAPB2_DIV4;
  329. RCU_CFG2 |= RCU_CFG2_ADCPSC2;
  330. RCU_CFG2 |= RCU_CFG2_ADCSEL;
  331. break;
  332. case RCU_ADCCK_APB2_DIV6:
  333. RCU_CFG0 |= RCU_ADC_CKAPB2_DIV6;
  334. RCU_CFG2 |= RCU_CFG2_ADCSEL;
  335. break;
  336. case RCU_ADCCK_APB2_DIV7:
  337. RCU_CFG0 |= RCU_ADC_CKAPB2_DIV6;
  338. RCU_CFG2 |= RCU_CFG2_ADCPSC2;
  339. RCU_CFG2 |= RCU_CFG2_ADCSEL;
  340. break;
  341. case RCU_ADCCK_APB2_DIV8:
  342. RCU_CFG0 |= RCU_ADC_CKAPB2_DIV8;
  343. RCU_CFG2 |= RCU_CFG2_ADCSEL;
  344. break;
  345. case RCU_ADCCK_APB2_DIV9:
  346. RCU_CFG0 |= RCU_ADC_CKAPB2_DIV8;
  347. RCU_CFG2 |= RCU_CFG2_ADCPSC2;
  348. RCU_CFG2 |= RCU_CFG2_ADCSEL;
  349. break;
  350. default:
  351. break;
  352. }
  353. }
  354. /*!
  355. \brief configure the USBFS clock prescaler selection
  356. \param[in] ck_usbfs: USBFS clock prescaler selection
  357. \arg RCU_USBFS_CKPLL_DIV1_5: select CK_PLL/1.5 as CK_USBFS
  358. \arg RCU_USBFS_CKPLL_DIV1: select CK_PLL as CK_USBFS
  359. \arg RCU_USBFS_CKPLL_DIV2_5: select CK_PLL/2.5 as CK_USBFS
  360. \arg RCU_USBFS_CKPLL_DIV2: select CK_PLL/2 as CK_USBFS
  361. \arg RCU_USBFS_CKPLL_DIV3: select CK_PLL/3 as CK_USBFS
  362. \arg RCU_USBFS_CKPLL_DIV3_5: select CK_PLL/3.5 as CK_USBFS
  363. \param[out] none
  364. \retval none
  365. */
  366. void rcu_usbfs_clock_config(uint32_t ck_usbfs)
  367. {
  368. /* reset the USBFSPSC bits and set according to ck_usbfs */
  369. RCU_CFG0 &= ~RCU_CFG0_USBFSPSC;
  370. RCU_CFG2 &= ~RCU_CFG2_USBFSPSC2;
  371. RCU_CFG0 |= (ck_usbfs & (~RCU_CFG2_USBFSPSC2));
  372. RCU_CFG2 |= (ck_usbfs & RCU_CFG2_USBFSPSC2);
  373. }
  374. /*!
  375. \brief configure the CK_OUT clock source and divider
  376. \param[in] ckout_src: CK_OUT clock source selection
  377. \arg RCU_CKOUTSRC_NONE: no clock selected
  378. \arg RCU_CKOUTSRC_IRC28M: IRC28M selected
  379. \arg RCU_CKOUTSRC_IRC40K: IRC40K selected
  380. \arg RCU_CKOUTSRC_LXTAL: LXTAL selected
  381. \arg RCU_CKOUTSRC_CKSYS: CKSYS selected
  382. \arg RCU_CKOUTSRC_IRC8M: IRC8M selected
  383. \arg RCU_CKOUTSRC_HXTAL: HXTAL selected
  384. \arg RCU_CKOUTSRC_CKPLL_DIV1: CK_PLL selected
  385. \arg RCU_CKOUTSRC_CKPLL_DIV2: CK_PLL/2 selected
  386. \param[in] ckout_div: CK_OUT divider
  387. \arg RCU_CKOUT_DIVx(x=1,2,4,8,16,32,64,128): CK_OUT is divided by x
  388. \param[out] none
  389. \retval none
  390. */
  391. void rcu_ckout_config(uint32_t ckout_src, uint32_t ckout_div)
  392. {
  393. uint32_t ckout = 0U;
  394. ckout = RCU_CFG0;
  395. /* reset the CKOUTSEL, CKOUTDIV and PLLDV bits and set according to ckout_src and ckout_div */
  396. ckout &= ~(RCU_CFG0_CKOUTSEL | RCU_CFG0_CKOUTDIV | RCU_CFG0_PLLDV);
  397. RCU_CFG0 = (ckout | ckout_src | ckout_div);
  398. }
  399. /*!
  400. \brief configure the PLL clock source preselection
  401. \param[in] pll_presel: PLL clock source preselection
  402. \arg RCU_PLLPRESEL_IRC48M: select IRC48M as PLL preselection clock
  403. \arg RCU_PLLPRESEL_HXTAL: select HXTAL as PLL preselection clock
  404. \param[out] none
  405. \retval none
  406. */
  407. void rcu_pll_preselection_config(uint32_t pll_presel)
  408. {
  409. RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL);
  410. RCU_CFG1 |= pll_presel;
  411. }
  412. /*!
  413. \brief configure the PLL clock source selection and PLL multiply factor
  414. \param[in] pll_src: PLL clock source selection
  415. \arg RCU_PLLSRC_IRC8M_DIV2: select CK_IRC8M/2 as PLL source clock
  416. \arg RCU_PLLSRC_HXTAL_IRC48M: select HXTAL or IRC48M as PLL source clock
  417. \param[in] pll_mul: PLL multiply factor
  418. \arg RCU_PLL_MULx(x=2..64): PLL source clock * x
  419. \param[out] none
  420. \retval none
  421. */
  422. void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul)
  423. {
  424. RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF);
  425. RCU_CFG1 &= ~(RCU_CFG1_PLLMF5);
  426. RCU_CFG0 |= (pll_src | (pll_mul & (~RCU_CFG1_PLLMF5)));
  427. RCU_CFG1 |= (pll_mul & RCU_CFG1_PLLMF5);
  428. }
  429. /*!
  430. \brief configure the USART clock source selection
  431. \param[in] ck_usart: USART clock source selection
  432. \arg RCU_USART0SRC_CKAPB2: CK_USART0 select CK_APB2
  433. \arg RCU_USART0SRC_CKSYS: CK_USART0 select CK_SYS
  434. \arg RCU_USART0SRC_LXTAL: CK_USART0 select CK_LXTAL
  435. \arg RCU_USART0SRC_IRC8M: CK_USART0 select CK_IRC8M
  436. \param[out] none
  437. \retval none
  438. */
  439. void rcu_usart_clock_config(uint32_t ck_usart)
  440. {
  441. /* reset the USART0SEL bits and set according to ck_usart */
  442. RCU_CFG2 &= ~RCU_CFG2_USART0SEL;
  443. RCU_CFG2 |= ck_usart;
  444. }
  445. /*!
  446. \brief configure the CEC clock source selection
  447. \param[in] ck_cec: CEC clock source selection
  448. \arg RCU_CECSRC_IRC8M_DIV244: CK_CEC select CK_IRC8M/244
  449. \arg RCU_CECSRC_LXTAL: CK_CEC select CK_LXTAL
  450. \param[out] none
  451. \retval none
  452. */
  453. void rcu_cec_clock_config(uint32_t ck_cec)
  454. {
  455. /* reset the CECSEL bit and set according to ck_cec */
  456. RCU_CFG2 &= ~RCU_CFG2_CECSEL;
  457. RCU_CFG2 |= ck_cec;
  458. }
  459. /*!
  460. \brief configure the RTC clock source selection
  461. \param[in] rtc_clock_source: RTC clock source selection
  462. \arg RCU_RTCSRC_NONE: no clock selected
  463. \arg RCU_RTCSRC_LXTAL: CK_LXTAL selected as RTC source clock
  464. \arg RCU_RTCSRC_IRC40K: CK_IRC40K selected as RTC source clock
  465. \arg RCU_RTCSRC_HXTAL_DIV32: CK_HXTAL/32 selected as RTC source clock
  466. \param[out] none
  467. \retval none
  468. */
  469. void rcu_rtc_clock_config(uint32_t rtc_clock_source)
  470. {
  471. /* reset the RTCSRC bits and set according to rtc_clock_source */
  472. RCU_BDCTL &= ~RCU_BDCTL_RTCSRC;
  473. RCU_BDCTL |= rtc_clock_source;
  474. }
  475. /*!
  476. \brief configure the CK48M clock source selection
  477. \param[in] ck48m_clock_source: CK48M clock source selection
  478. only one parameter can be selected which is shown as below:
  479. \arg RCU_CK48MSRC_PLL48M: CK_PLL48M selected as CK48M source clock
  480. \arg RCU_CK48MSRC_IRC48M: CK_IRC48M selected as CK48M source clock
  481. \param[out] none
  482. \retval none
  483. */
  484. void rcu_ck48m_clock_config(uint32_t ck48m_clock_source)
  485. {
  486. uint32_t reg;
  487. reg = RCU_ADDCTL;
  488. /* reset the CK48MSEL bit and set according to ck48m_clock_source */
  489. reg &= ~RCU_ADDCTL_CK48MSEL;
  490. RCU_ADDCTL = (reg | ck48m_clock_source);
  491. }
  492. /*!
  493. \brief configure the HXTAL divider used as input of PLL
  494. \param[in] hxtal_prediv: HXTAL divider used as input of PLL
  495. \arg RCU_PLL_PREDVx(x=1..16): HXTAL or IRC48M divided x used as input of PLL
  496. \param[out] none
  497. \retval none
  498. */
  499. void rcu_hxtal_prediv_config(uint32_t hxtal_prediv)
  500. {
  501. uint32_t prediv = 0U;
  502. prediv = RCU_CFG1;
  503. /* reset the HXTALPREDV bits and set according to hxtal_prediv */
  504. prediv &= ~RCU_CFG1_PREDV;
  505. RCU_CFG1 = (prediv | hxtal_prediv);
  506. }
  507. /*!
  508. \brief configure the LXTAL drive capability
  509. \param[in] lxtal_dricap: drive capability of LXTAL
  510. \arg RCU_LXTAL_LOWDRI: lower driving capability
  511. \arg RCU_LXTAL_MED_LOWDRI: medium low driving capability
  512. \arg RCU_LXTAL_MED_HIGHDRI: medium high driving capability
  513. \arg RCU_LXTAL_HIGHDRI: higher driving capability
  514. \param[out] none
  515. \retval none
  516. */
  517. void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap)
  518. {
  519. /* reset the LXTALDRI bits and set according to lxtal_dricap */
  520. RCU_BDCTL &= ~RCU_BDCTL_LXTALDRI;
  521. RCU_BDCTL |= lxtal_dricap;
  522. }
  523. /*!
  524. \brief get the clock stabilization and periphral reset flags
  525. \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum
  526. only one parameter can be selected which is shown as below:
  527. \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag
  528. \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag
  529. \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag
  530. \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag
  531. \arg RCU_FLAG_PLLSTB: PLL stabilization flag
  532. \arg RCU_FLAG_IRC28MSTB: IRC28M stabilization flag
  533. \arg RCU_FLAG_IRC48MSTB: IRC48M stabilization flag
  534. \arg RCU_FLAG_V12RST: V12 domain power reset flag
  535. \arg RCU_FLAG_OBLRST: option byte loader reset flag
  536. \arg RCU_FLAG_EPRST: external pin reset flag
  537. \arg RCU_FLAG_PORRST: power reset flag
  538. \arg RCU_FLAG_SWRST: software reset flag
  539. \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag
  540. \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag
  541. \arg RCU_FLAG_LPRST: low-power reset flag
  542. \param[out] none
  543. \retval FlagStatus: SET or RESET
  544. */
  545. FlagStatus rcu_flag_get(rcu_flag_enum flag)
  546. {
  547. if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){
  548. return SET;
  549. }else{
  550. return RESET;
  551. }
  552. }
  553. /*!
  554. \brief clear the reset flag
  555. \param[in] none
  556. \param[out] none
  557. \retval none
  558. */
  559. void rcu_all_reset_flag_clear(void)
  560. {
  561. RCU_RSTSCK |= RCU_RSTSCK_RSTFC;
  562. }
  563. /*!
  564. \brief get the clock stabilization interrupt and ckm flags
  565. \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum
  566. only one parameter can be selected which is shown as below:
  567. \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag
  568. \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag
  569. \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag
  570. \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag
  571. \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag
  572. \arg RCU_INT_FLAG_IRC28MSTB: IRC28M stabilization interrupt flag
  573. \arg RCU_INT_FLAG_IRC48MSTB: IRC48M stabilization interrupt flag
  574. \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag
  575. \param[out] none
  576. \retval FlagStatus: SET or RESET
  577. */
  578. FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)
  579. {
  580. if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){
  581. return SET;
  582. }else{
  583. return RESET;
  584. }
  585. }
  586. /*!
  587. \brief clear the interrupt flags
  588. \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum
  589. only one parameter can be selected which is shown as below:
  590. \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear
  591. \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear
  592. \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear
  593. \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear
  594. \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear
  595. \arg RCU_INT_FLAG_IRC28MSTB_CLR: IRC28M stabilization interrupt flag clear
  596. \arg RCU_INT_FLAG_IRC48MSTB_CLR: IRC48M stabilization interrupt flag clear
  597. \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear
  598. \param[out] none
  599. \retval none
  600. */
  601. void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear)
  602. {
  603. RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear));
  604. }
  605. /*!
  606. \brief enable the stabilization interrupt
  607. \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum
  608. only one parameter can be selected which is shown as below:
  609. \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable
  610. \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
  611. \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable
  612. \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
  613. \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable
  614. \arg RCU_INT_IRC28MSTB: IRC28M stabilization interrupt enable
  615. \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable
  616. \param[out] none
  617. \retval none
  618. */
  619. void rcu_interrupt_enable(rcu_int_enum stab_int)
  620. {
  621. RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int));
  622. }
  623. /*!
  624. \brief disable the stabilization interrupt
  625. \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum
  626. only one parameter can be selected which is shown as below:
  627. \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt disable
  628. \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt disable
  629. \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt disable
  630. \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt disable
  631. \arg RCU_INT_PLLSTB: PLL stabilization interrupt disable
  632. \arg RCU_INT_IRC28MSTB: IRC28M stabilization interrupt disable
  633. \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt disable
  634. \param[out] none
  635. \retval none
  636. */
  637. void rcu_interrupt_disable(rcu_int_enum stab_int)
  638. {
  639. RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int));
  640. }
  641. /*!
  642. \brief wait until oscillator stabilization flags is SET
  643. \param[in] osci: oscillator types, refer to rcu_osci_type_enum
  644. \arg RCU_HXTAL: HXTAL
  645. \arg RCU_LXTAL: LXTAL
  646. \arg RCU_IRC8M: IRC8M
  647. \arg RCU_IRC28M: IRC28M
  648. \arg RCU_IRC48M: IRC48M
  649. \arg RCU_IRC40K: IRC40K
  650. \arg RCU_PLL_CK: PLL
  651. \param[out] none
  652. \retval ErrStatus: SUCCESS or ERROR
  653. */
  654. ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci)
  655. {
  656. uint32_t stb_cnt = 0U;
  657. ErrStatus reval = ERROR;
  658. FlagStatus osci_stat = RESET;
  659. switch(osci){
  660. case RCU_HXTAL:
  661. /* wait until HXTAL is stabilization and osci_stat is not more than timeout */
  662. while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){
  663. osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB);
  664. stb_cnt++;
  665. }
  666. if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){
  667. reval = SUCCESS;
  668. }
  669. break;
  670. /* wait LXTAL stable */
  671. case RCU_LXTAL:
  672. while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){
  673. osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB);
  674. stb_cnt++;
  675. }
  676. /* check whether flag is set or not */
  677. if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){
  678. reval = SUCCESS;
  679. }
  680. break;
  681. /* wait IRC8M stable */
  682. case RCU_IRC8M:
  683. while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){
  684. osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB);
  685. stb_cnt++;
  686. }
  687. /* check whether flag is set or not */
  688. if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){
  689. reval = SUCCESS;
  690. }
  691. break;
  692. /* wait IRC28M stable */
  693. case RCU_IRC28M:
  694. while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
  695. osci_stat = rcu_flag_get(RCU_FLAG_IRC28MSTB);
  696. stb_cnt++;
  697. }
  698. /* check whether flag is set or not */
  699. if(RESET != rcu_flag_get(RCU_FLAG_IRC28MSTB)){
  700. reval = SUCCESS;
  701. }
  702. break;
  703. /* wait IRC48M stable */
  704. case RCU_IRC48M:
  705. while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
  706. osci_stat = rcu_flag_get(RCU_FLAG_IRC48MSTB);
  707. stb_cnt++;
  708. }
  709. /* check whether flag is set or not */
  710. if (RESET != rcu_flag_get(RCU_FLAG_IRC48MSTB)){
  711. reval = SUCCESS;
  712. }
  713. break;
  714. /* wait IRC40K stable */
  715. case RCU_IRC40K:
  716. while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
  717. osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB);
  718. stb_cnt++;
  719. }
  720. /* check whether flag is set or not */
  721. if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){
  722. reval = SUCCESS;
  723. }
  724. break;
  725. /* wait PLL stable */
  726. case RCU_PLL_CK:
  727. while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
  728. osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB);
  729. stb_cnt++;
  730. }
  731. /* check whether flag is set or not */
  732. if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){
  733. reval = SUCCESS;
  734. }
  735. break;
  736. default:
  737. break;
  738. }
  739. /* return value */
  740. return reval;
  741. }
  742. /*!
  743. \brief turn on the oscillator
  744. \param[in] osci: oscillator types, refer to rcu_osci_type_enum
  745. \arg RCU_HXTAL: HXTAL
  746. \arg RCU_LXTAL: LXTAL
  747. \arg RCU_IRC8M: IRC8M
  748. \arg RCU_IRC28M: IRC28M
  749. \arg RCU_IRC48M: IRC48M
  750. \arg RCU_IRC40K: IRC40K
  751. \arg RCU_PLL_CK: PLL
  752. \param[out] none
  753. \retval none
  754. */
  755. void rcu_osci_on(rcu_osci_type_enum osci)
  756. {
  757. RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci));
  758. }
  759. /*!
  760. \brief turn off the oscillator
  761. \param[in] osci: oscillator types, refer to rcu_osci_type_enum
  762. \arg RCU_HXTAL: HXTAL
  763. \arg RCU_LXTAL: LXTAL
  764. \arg RCU_IRC8M: IRC8M
  765. \arg RCU_IRC28M: IRC28M
  766. \arg RCU_IRC48M: IRC48M
  767. \arg RCU_IRC40K: IRC40K
  768. \arg RCU_PLL_CK: PLL
  769. \param[out] none
  770. \retval none
  771. */
  772. void rcu_osci_off(rcu_osci_type_enum osci)
  773. {
  774. RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci));
  775. }
  776. /*!
  777. \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
  778. \param[in] osci: oscillator types, refer to rcu_osci_type_enum
  779. \arg RCU_HXTAL: HXTAL
  780. \arg RCU_LXTAL: LXTAL
  781. \param[out] none
  782. \retval none
  783. */
  784. void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)
  785. {
  786. uint32_t reg;
  787. switch(osci){
  788. case RCU_HXTAL:
  789. /* HXTALEN must be reset before enable the oscillator bypass mode */
  790. reg = RCU_CTL0;
  791. RCU_CTL0 &= ~RCU_CTL0_HXTALEN;
  792. RCU_CTL0 = (reg | RCU_CTL0_HXTALBPS);
  793. break;
  794. case RCU_LXTAL:
  795. /* LXTALEN must be reset before enable the oscillator bypass mode */
  796. reg = RCU_BDCTL;
  797. RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
  798. RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS);
  799. break;
  800. case RCU_IRC8M:
  801. case RCU_IRC28M:
  802. case RCU_IRC48M:
  803. case RCU_IRC40K:
  804. case RCU_PLL_CK:
  805. break;
  806. default:
  807. break;
  808. }
  809. }
  810. /*!
  811. \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
  812. \param[in] osci: oscillator types, refer to rcu_osci_type_enum
  813. \arg RCU_HXTAL: HXTAL
  814. \arg RCU_LXTAL: LXTAL
  815. \param[out] none
  816. \retval none
  817. */
  818. void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)
  819. {
  820. uint32_t reg;
  821. switch(osci){
  822. case RCU_HXTAL:
  823. /* HXTALEN must be reset before disable the oscillator bypass mode */
  824. reg = RCU_CTL0;
  825. RCU_CTL0 &= ~RCU_CTL0_HXTALEN;
  826. RCU_CTL0 = (reg & (~RCU_CTL0_HXTALBPS));
  827. break;
  828. case RCU_LXTAL:
  829. /* LXTALEN must be reset before disable the oscillator bypass mode */
  830. reg = RCU_BDCTL;
  831. RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
  832. RCU_BDCTL = (reg & (~RCU_BDCTL_LXTALBPS));
  833. break;
  834. case RCU_IRC8M:
  835. case RCU_IRC28M:
  836. case RCU_IRC48M:
  837. case RCU_IRC40K:
  838. case RCU_PLL_CK:
  839. break;
  840. default:
  841. break;
  842. }
  843. }
  844. /*!
  845. \brief enable the HXTAL clock monitor
  846. \param[in] none
  847. \param[out] none
  848. \retval none
  849. */
  850. void rcu_hxtal_clock_monitor_enable(void)
  851. {
  852. RCU_CTL0 |= RCU_CTL0_CKMEN;
  853. }
  854. /*!
  855. \brief disable the HXTAL clock monitor
  856. \param[in] none
  857. \param[out] none
  858. \retval none
  859. */
  860. void rcu_hxtal_clock_monitor_disable(void)
  861. {
  862. RCU_CTL0 &= ~RCU_CTL0_CKMEN;
  863. }
  864. /*!
  865. \brief set the IRC8M adjust value
  866. \param[in] irc8m_adjval: IRC8M adjust value, must be between 0 and 0x1F
  867. \param[out] none
  868. \retval none
  869. */
  870. void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval)
  871. {
  872. uint32_t adjust = 0U;
  873. adjust = RCU_CTL0;
  874. /* reset the IRC8MADJ bits and set according to irc8m_adjval */
  875. adjust &= ~RCU_CTL0_IRC8MADJ;
  876. RCU_CTL0 = (adjust | (((uint32_t)irc8m_adjval)<<3));
  877. }
  878. /*!
  879. \brief set the IRC28M adjust value
  880. \param[in] irc28m_adjval: IRC28M adjust value, must be between 0 and 0x1F
  881. \param[out] none
  882. \retval none
  883. */
  884. void rcu_irc28m_adjust_value_set(uint8_t irc28m_adjval)
  885. {
  886. uint32_t adjust = 0U;
  887. adjust = RCU_CTL1;
  888. /* reset the IRC28MADJ bits and set according to irc28m_adjval */
  889. adjust &= ~RCU_CTL1_IRC28MADJ;
  890. RCU_CTL1 = (adjust | (((uint32_t)irc28m_adjval)<<3));
  891. }
  892. /*!
  893. \brief unlock the voltage key
  894. \param[in] none
  895. \param[out] none
  896. \retval none
  897. */
  898. void rcu_voltage_key_unlock(void)
  899. {
  900. /* reset the KEY bits and set 0x1A2B3C4D */
  901. RCU_VKEY &= ~RCU_VKEY_KEY;
  902. RCU_VKEY |= RCU_VKEY_UNLOCK;
  903. }
  904. /*!
  905. \brief set voltage in deep sleep mode
  906. \param[in] dsvol: deep sleep mode voltage
  907. \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V
  908. \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V
  909. \arg RCU_DEEPSLEEP_V_0_8: the core voltage is 0.8V
  910. \arg RCU_DEEPSLEEP_V_0_7: the core voltage is 0.7V
  911. \param[out] none
  912. \retval none
  913. */
  914. void rcu_deepsleep_voltage_set(uint32_t dsvol)
  915. {
  916. /* reset the DSLPVS bits and set according to dsvol */
  917. RCU_DSV &= ~RCU_DSV_DSLPVS;
  918. RCU_DSV |= dsvol;
  919. }
  920. /*!
  921. \brief get the system clock, bus and peripheral clock frequency
  922. \param[in] clock: the clock frequency which to get
  923. \arg CK_SYS: system clock frequency
  924. \arg CK_AHB: AHB clock frequency
  925. \arg CK_APB1: APB1 clock frequency
  926. \arg CK_APB2: APB2 clock frequency
  927. \arg CK_ADC: ADC clock frequency
  928. \arg CK_CEC: CEC clock frequency
  929. \arg CK_USART: USART clock frequency
  930. \param[out] none
  931. \retval clock frequency of system, AHB, APB1, APB2, ADC, CEC or USRAT
  932. */
  933. uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock)
  934. {
  935. uint32_t sws = 0U, adcps = 0U, adcps2 = 0U, ck_freq = 0U;
  936. uint32_t cksys_freq = 0U, ahb_freq = 0U, apb1_freq = 0U, apb2_freq = 0U;
  937. uint32_t adc_freq = 0U, cec_freq = 0U, usart_freq = 0U;
  938. uint32_t pllmf = 0U, pllmf4 = 0U, pllmf5 = 0U, pllsel = 0U, pllpresel = 0U, prediv = 0U, idx = 0U, clk_exp = 0U;
  939. /* exponent of AHB, APB1 and APB2 clock divider */
  940. const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
  941. const uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
  942. const uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
  943. sws = GET_BITS(RCU_CFG0, 2, 3);
  944. switch(sws){
  945. /* IRC8M is selected as CK_SYS */
  946. case SEL_IRC8M:
  947. cksys_freq = IRC8M_VALUE;
  948. break;
  949. /* HXTAL is selected as CK_SYS */
  950. case SEL_HXTAL:
  951. cksys_freq = HXTAL_VALUE;
  952. break;
  953. /* PLL is selected as CK_SYS */
  954. case SEL_PLL:
  955. /* get the value of PLLMF[3:0] */
  956. pllmf = GET_BITS(RCU_CFG0, 18, 21);
  957. pllmf4 = GET_BITS(RCU_CFG0, 27, 27);
  958. pllmf5 = GET_BITS(RCU_CFG1, 31, 31);
  959. /* high 16 bits */
  960. if(1U == pllmf4){
  961. pllmf += 17U;
  962. }else{
  963. pllmf += 2U;
  964. }
  965. if(1U == pllmf5){
  966. pllmf += 31U;
  967. }
  968. /* PLL clock source selection, HXTAL or IRC8M/2 */
  969. pllsel = GET_BITS(RCU_CFG0, 16, 16);
  970. pllpresel = GET_BITS(RCU_CFG1, 30, 30);
  971. if(0U != pllsel){
  972. prediv = (GET_BITS(RCU_CFG1,0, 3) + 1U);
  973. if(0U == pllpresel){
  974. cksys_freq = (HXTAL_VALUE / prediv) * pllmf;
  975. }else{
  976. cksys_freq = (IRC48M_VALUE / prediv) * pllmf;
  977. }
  978. }else{
  979. cksys_freq = (IRC8M_VALUE >> 1) * pllmf;
  980. }
  981. break;
  982. /* IRC8M is selected as CK_SYS */
  983. default:
  984. cksys_freq = IRC8M_VALUE;
  985. break;
  986. }
  987. /* calculate AHB clock frequency */
  988. idx = GET_BITS(RCU_CFG0, 4, 7);
  989. clk_exp = ahb_exp[idx];
  990. ahb_freq = cksys_freq >> clk_exp;
  991. /* calculate APB1 clock frequency */
  992. idx = GET_BITS(RCU_CFG0, 8, 10);
  993. clk_exp = apb1_exp[idx];
  994. apb1_freq = ahb_freq >> clk_exp;
  995. /* calculate APB2 clock frequency */
  996. idx = GET_BITS(RCU_CFG0, 11, 13);
  997. clk_exp = apb2_exp[idx];
  998. apb2_freq = ahb_freq >> clk_exp;
  999. /* return the clocks frequency */
  1000. switch(clock){
  1001. case CK_SYS:
  1002. ck_freq = cksys_freq;
  1003. break;
  1004. case CK_AHB:
  1005. ck_freq = ahb_freq;
  1006. break;
  1007. case CK_APB1:
  1008. ck_freq = apb1_freq;
  1009. break;
  1010. case CK_APB2:
  1011. ck_freq = apb2_freq;
  1012. break;
  1013. case CK_ADC:
  1014. /* calculate ADC clock frequency */
  1015. if(RCU_ADCSRC_APB2DIV != (RCU_CFG2 & RCU_CFG2_ADCSEL)){
  1016. if(RCU_ADC_IRC28M_DIV1 != (RCU_CFG2 & RCU_CFG2_IRC28MDIV)){
  1017. adc_freq = IRC28M_VALUE >> 1;
  1018. }else{
  1019. adc_freq = IRC28M_VALUE;
  1020. }
  1021. }else{
  1022. /* ADC clock select CK_APB2 divided by 2/3/4/5/6/7/8/9 */
  1023. adcps = GET_BITS(RCU_CFG0, 14, 15);
  1024. adcps2 = GET_BITS(RCU_CFG2, 31, 31);
  1025. switch(adcps){
  1026. case 0:
  1027. if(0U == adcps2){
  1028. adc_freq = apb2_freq / 2U;
  1029. }else{
  1030. adc_freq = apb2_freq / 3U;
  1031. }
  1032. break;
  1033. case 1:
  1034. if(0U == adcps2){
  1035. adc_freq = apb2_freq / 4U;
  1036. }else{
  1037. adc_freq = apb2_freq / 5U;
  1038. }
  1039. break;
  1040. case 2:
  1041. if(0U == adcps2){
  1042. adc_freq = apb2_freq / 6U;
  1043. }else{
  1044. adc_freq = apb2_freq / 7U;
  1045. }
  1046. break;
  1047. case 3:
  1048. if(0U == adcps2){
  1049. adc_freq = apb2_freq / 8U;
  1050. }else{
  1051. adc_freq = apb2_freq / 9U;
  1052. }
  1053. break;
  1054. default:
  1055. break;
  1056. }
  1057. }
  1058. ck_freq = adc_freq;
  1059. break;
  1060. case CK_CEC:
  1061. /* calculate CEC clock frequency */
  1062. if(RCU_CECSRC_LXTAL != (RCU_CFG2 & RCU_CFG2_CECSEL)){
  1063. cec_freq = IRC8M_VALUE / 244U;
  1064. }else{
  1065. cec_freq = LXTAL_VALUE;
  1066. }
  1067. ck_freq = cec_freq;
  1068. break;
  1069. case CK_USART:
  1070. /* calculate USART clock frequency */
  1071. if(RCU_USART0SRC_CKAPB2 == (RCU_CFG2 & RCU_CFG2_USART0SEL)){
  1072. usart_freq = apb2_freq;
  1073. }else if(RCU_USART0SRC_CKSYS == (RCU_CFG2 & RCU_CFG2_USART0SEL)){
  1074. usart_freq = cksys_freq;
  1075. }else if(RCU_USART0SRC_LXTAL == (RCU_CFG2 & RCU_CFG2_USART0SEL)){
  1076. usart_freq = LXTAL_VALUE;
  1077. }else if(RCU_USART0SRC_IRC8M == (RCU_CFG2 & RCU_CFG2_USART0SEL)){
  1078. usart_freq = IRC8M_VALUE;
  1079. }else{
  1080. }
  1081. ck_freq = usart_freq;
  1082. break;
  1083. default:
  1084. break;
  1085. }
  1086. return ck_freq;
  1087. }