gd32f4xx_rcu.c 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281
  1. /*!
  2. \file gd32f4xx_rcu.c
  3. \brief RCU driver
  4. */
  5. /*
  6. Copyright (C) 2016 GigaDevice
  7. 2016-08-15, V1.0.1, firmware for GD32F4xx
  8. */
  9. #include "gd32f4xx_rcu.h"
  10. #define SEL_IRC16M 0U
  11. #define SEL_HXTAL 1U
  12. #define SEL_PLLP 2U
  13. #define OSC_STARTUP_TIMEOUT ((uint16_t)0xfffffU)
  14. #define LXTAL_STARTUP_TIMEOUT ((uint16_t)0x3ffffffU)
  15. /*!
  16. \brief deinitialize the RCU
  17. \param[in] none
  18. \param[out] none
  19. \retval none
  20. */
  21. void rcu_deinit(void)
  22. {
  23. /* enable IRC16M */
  24. RCU_CTL |= RCU_CTL_IRC16MEN;
  25. rcu_osci_stab_wait(RCU_IRC16M);
  26. /* reset CFG0 register */
  27. RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC |
  28. RCU_CFG0_RTCDIV | RCU_CFG0_CKOUT0SEL | RCU_CFG0_I2SSEL | RCU_CFG0_CKOUT0DIV |
  29. RCU_CFG0_CKOUT1DIV | RCU_CFG0_CKOUT1SEL);
  30. /* reset CTL register */
  31. RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN | RCU_CTL_PLLI2SEN |
  32. RCU_CTL_PLLSAIEN | RCU_CTL_HXTALBPS);
  33. /* reset PLL register */
  34. RCU_PLL = 0x24003010U;
  35. /* reset PLLI2S register */
  36. RCU_PLLI2S = 0x24003000U;
  37. /* reset PLLSAI register */
  38. RCU_PLLSAI = 0x24003010U;
  39. /* reset INT register */
  40. RCU_INT = 0x00000000U;
  41. /* reset CFG1 register */
  42. RCU_CFG1 &= ~(RCU_CFG1_PLLSAIRDIV | RCU_CFG1_TIMERSEL);
  43. }
  44. /*!
  45. \brief enable the peripherals clock
  46. \param[in] periph: RCU peripherals, refer to rcu_periph_enum
  47. only one parameter can be selected which is shown as below:
  48. \arg RCU_GPIOx (x=A,B,C,D,E,F,G,H,I): GPIO ports clock
  49. \arg RCU_CRC: CRC clock
  50. \arg RCU_BKPSRAM: BKPSRAM clock
  51. \arg RCU_TCMSRAM: TCMSRAM clock
  52. \arg RCU_DMAx (x=0,1): DMA clock
  53. \arg RCU_IPA: IPA clock
  54. \arg RCU_ENET: ENET clock
  55. \arg RCU_ENETTX: ENETTX clock
  56. \arg RCU_ENETRX: ENETRX clock
  57. \arg RCU_ENETPTP: ENETPTP clock
  58. \arg RCU_USBHS: USBHS clock
  59. \arg RCU_USBHSULPI: USBHSULPI clock
  60. \arg RCU_DCI: DCI clock
  61. \arg RCU_TRNG: TRNG clock
  62. \arg RCU_USBFS: USBFS clock
  63. \arg RCU_EXMC: EXMC clock
  64. \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): TIMER clock
  65. \arg RCU_WWDGT: WWDGT clock
  66. \arg RCU_SPIx (x=0,1,2,3,4,5): SPI clock
  67. \arg RCU_USARTx (x=0,1,2,5): USART clock
  68. \arg RCU_UARTx (x=3,4,6,7): UART clock
  69. \arg RCU_I2Cx (x=0,1,2): I2C clock
  70. \arg RCU_CANx (x=0,1): CAN clock
  71. \arg RCU_PMU: PMU clock
  72. \arg RCU_DAC: DAC clock
  73. \arg RCU_RTC: RTC clock
  74. \arg RCU_ADCx (x=0,1,2): ADC clock
  75. \arg RCU_SDIO: SDIO clock
  76. \arg RCU_SYSCFG: SYSCFG clock
  77. \arg RCU_TLI: TLI clock
  78. \arg RCU_CTC: CTC clock
  79. \arg RCU_IREF: IREF clock
  80. \param[out] none
  81. \retval none
  82. */
  83. void rcu_periph_clock_enable(rcu_periph_enum periph)
  84. {
  85. RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
  86. }
  87. /*!
  88. \brief disable the peripherals clock
  89. \param[in] periph: RCU peripherals, refer to rcu_periph_enum
  90. only one parameter can be selected which is shown as below:
  91. \arg RCU_GPIOx (x=A,B,C,D,E,F,G,H,I): GPIO ports clock
  92. \arg RCU_CRC: CRC clock
  93. \arg RCU_BKPSRAM: BKPSRAM clock
  94. \arg RCU_TCMSRAM: TCMSRAM clock
  95. \arg RCU_DMAx (x=0,1): DMA clock
  96. \arg RCU_IPA: IPA clock
  97. \arg RCU_ENET: ENET clock
  98. \arg RCU_ENETTX: ENETTX clock
  99. \arg RCU_ENETRX: ENETRX clock
  100. \arg RCU_ENETPTP: ENETPTP clock
  101. \arg RCU_USBHS: USBHS clock
  102. \arg RCU_USBHSULPI: USBHSULPI clock
  103. \arg RCU_DCI: DCI clock
  104. \arg RCU_TRNG: TRNG clock
  105. \arg RCU_USBFS: USBFS clock
  106. \arg RCU_EXMC: EXMC clock
  107. \arg RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): TIMER clock
  108. \arg RCU_WWDGT: WWDGT clock
  109. \arg RCU_SPIx (x=0,1,2,3,4,5): SPI clock
  110. \arg RCU_USARTx (x=0,1,2,5): USART clock
  111. \arg RCU_UARTx (x=3,4,6,7): UART clock
  112. \arg RCU_I2Cx (x=0,1,2): I2C clock
  113. \arg RCU_CANx (x=0,1): CAN clock
  114. \arg RCU_PMU: PMU clock
  115. \arg RCU_DAC: DAC clock
  116. \arg RCU_RTC: RTC clock
  117. \arg RCU_ADCx (x=0,1,2): ADC clock
  118. \arg RCU_SDIO: SDIO clock
  119. \arg RCU_SYSCFG: SYSCFG clock
  120. \arg RCU_TLI: TLI clock
  121. \arg RCU_CTC: CTC clock
  122. \arg RCU_IREF: IREF clock
  123. \param[out] none
  124. \retval none
  125. */
  126. void rcu_periph_clock_disable(rcu_periph_enum periph)
  127. {
  128. RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
  129. }
  130. /*!
  131. \brief enable the peripherals clock when sleep mode
  132. \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum
  133. only one parameter can be selected which is shown as below:
  134. \arg RCU_GPIOx_SLP (x=A,B,C,D,E,F,G,H,I): GPIO ports clock
  135. \arg RCU_CRC_SLP: CRC clock
  136. \arg RCU_FMC_SLP: FMC clock
  137. \arg RCU_SRAM0_SLP: SRAM0 clock
  138. \arg RCU_SRAM1_SLP: SRAM1 clock
  139. \arg RCU_BKPSRAM: BKPSRAM clock
  140. \arg RCU_SRAM2_SLP: SRAM2 clock
  141. \arg RCU_DMAx_SLP (x=0,1): DMA clock
  142. \arg RCU_IPA_SLP: IPA clock
  143. \arg RCU_ENET_SLP: ENET clock
  144. \arg RCU_ENETTX_SLP: ENETTX clock
  145. \arg RCU_ENETRX_SLP: ENETRX clock
  146. \arg RCU_ENETPTP_SLP: ENETPTP clock
  147. \arg RCU_USBHS_SLP: USBHS clock
  148. \arg RCU_USBHSULPI_SLP: USBHSULPI clock
  149. \arg RCU_DCI_SLP: DCI clock
  150. \arg RCU_TRNG_SLP: TRNG clock
  151. \arg RCU_USBFS_SLP: USBFS clock
  152. \arg RCU_EXMC_SLP: EXMC clock
  153. \arg RCU_TIMERx_SLP (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): TIMER clock
  154. \arg RCU_WWDGT_SLP: WWDGT clock
  155. \arg RCU_SPIx_SLP (x=0,1,2,3,4,5): SPI clock
  156. \arg RCU_USARTx_SLP (x=0,1,2,5): USART clock
  157. \arg RCU_UARTx_SLP (x=3,4,6,7): UART clock
  158. \arg RCU_I2Cx_SLP (x=0,1,2): I2C clock
  159. \arg RCU_CANx_SLP (x=0,1): CAN clock
  160. \arg RCU_PMU_SLP: PMU clock
  161. \arg RCU_DAC_SLP: DAC clock
  162. \arg RCU_RTC_SLP: RTC clock
  163. \arg RCU_ADCx_SLP (x=0,1,2): ADC clock
  164. \arg RCU_SDIO_SLP: SDIO clock
  165. \arg RCU_SYSCFG_SLP: SYSCFG clock
  166. \arg RCU_TLI_SLP: TLI clock
  167. \arg RCU_CTC_SLP: CTC clock
  168. \arg RCU_IREF_SLP: IREF clock
  169. \param[out] none
  170. \retval none
  171. */
  172. void rcu_periph_clock_sleep_enable(rcu_periph_sleep_enum periph)
  173. {
  174. RCU_REG_VAL(periph) |= BIT(RCU_BIT_POS(periph));
  175. }
  176. /*!
  177. \brief disable the peripherals clock when sleep mode
  178. \param[in] periph: RCU peripherals, refer to rcu_periph_sleep_enum
  179. only one parameter can be selected which is shown as below:
  180. \arg RCU_GPIOx_SLP (x=A,B,C,D,E,F,G,H,I): GPIO ports clock
  181. \arg RCU_CRC_SLP: CRC clock
  182. \arg RCU_FMC_SLP: FMC clock
  183. \arg RCU_SRAM0_SLP: SRAM0 clock
  184. \arg RCU_SRAM1_SLP: SRAM1 clock
  185. \arg RCU_BKPSRAM: BKPSRAM clock
  186. \arg RCU_SRAM2_SLP: SRAM2 clock
  187. \arg RCU_DMAx_SLP (x=0,1): DMA clock
  188. \arg RCU_IPA_SLP: IPA clock
  189. \arg RCU_ENET_SLP: ENET clock
  190. \arg RCU_ENETTX_SLP: ENETTX clock
  191. \arg RCU_ENETRX_SLP: ENETRX clock
  192. \arg RCU_ENETPTP_SLP: ENETPTP clock
  193. \arg RCU_USBHS_SLP: USBHS clock
  194. \arg RCU_USBHSULPI_SLP: USBHSULPI clock
  195. \arg RCU_DCI_SLP: DCI clock
  196. \arg RCU_TRNG_SLP: TRNG clock
  197. \arg RCU_USBFS_SLP: USBFS clock
  198. \arg RCU_EXMC_SLP: EXMC clock
  199. \arg RCU_TIMERx_SLP (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): TIMER clock
  200. \arg RCU_WWDGT_SLP: WWDGT clock
  201. \arg RCU_SPIx_SLP (x=0,1,2,3,4,5): SPI clock
  202. \arg RCU_USARTx_SLP (x=0,1,2,5): USART clock
  203. \arg RCU_UARTx_SLP (x=3,4,6,7): UART clock
  204. \arg RCU_I2Cx_SLP (x=0,1,2): I2C clock
  205. \arg RCU_CANx_SLP (x=0,1): CAN clock
  206. \arg RCU_PMU_SLP: PMU clock
  207. \arg RCU_DAC_SLP: DAC clock
  208. \arg RCU_RTC_SLP: RTC clock
  209. \arg RCU_ADCx_SLP (x=0,1,2): ADC clock
  210. \arg RCU_SDIO_SLP: SDIO clock
  211. \arg RCU_SYSCFG_SLP: SYSCFG clock
  212. \arg RCU_TLI_SLP: TLI clock
  213. \arg RCU_CTC_SLP: CTC clock
  214. \arg RCU_IREF_SLP: IREF clock
  215. \param[out] none
  216. \retval none
  217. */
  218. void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph)
  219. {
  220. RCU_REG_VAL(periph) &= ~BIT(RCU_BIT_POS(periph));
  221. }
  222. /*!
  223. \brief reset the peripherals
  224. \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
  225. only one parameter can be selected which is shown as below:
  226. \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G,H,I): reset GPIO ports
  227. \arg RCU_CRCRST: reset CRC
  228. \arg RCU_DMAxRST (x=0,1): reset DMA
  229. \arg RCU_IPAENRST: reset IPA
  230. \arg RCU_ENETRST: reset ENET
  231. \arg RCU_USBHSRST: reset USBHS
  232. \arg RCU_DCIRST: reset DCI
  233. \arg RCU_TRNGRST: reset TRNG
  234. \arg RCU_USBFSRST: reset USBFS
  235. \arg RCU_EXMCRST: reset EXMC
  236. \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): reset TIMER
  237. \arg RCU_WWDGTRST: reset WWDGT
  238. \arg RCU_SPIxRST (x=0,1,2,3,4,5): reset SPI
  239. \arg RCU_USARTxRST (x=0,1,2,5): reset USART
  240. \arg RCU_UARTxRST (x=3,4,6,7): reset UART
  241. \arg RCU_I2CxRST (x=0,1,2): reset I2C
  242. \arg RCU_CANxRST (x=0,1): reset CAN
  243. \arg RCU_PMURST: reset PMU
  244. \arg RCU_DACRST: reset DAC
  245. \arg RCU_ADCRST (x=0,1,2): reset ADC
  246. \arg RCU_SDIORST: reset SDIO
  247. \arg RCU_SYSCFGRST: reset SYSCFG
  248. \arg RCU_TLIRST: reset TLI
  249. \arg RCU_CTCRST: reset CTC
  250. \arg RCU_IREFRST: reset IREF
  251. \param[out] none
  252. \retval none
  253. */
  254. void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset)
  255. {
  256. RCU_REG_VAL(periph_reset) |= BIT(RCU_BIT_POS(periph_reset));
  257. }
  258. /*!
  259. \brief disable reset the peripheral
  260. \param[in] periph_reset: RCU peripherals reset, refer to rcu_periph_reset_enum
  261. only one parameter can be selected which is shown as below:
  262. \arg RCU_GPIOxRST (x=A,B,C,D,E,F,G,H,I): reset GPIO ports
  263. \arg RCU_CRCRST: reset CRC
  264. \arg RCU_DMAxRST (x=0,1): reset DMA
  265. \arg RCU_IPAENRST: reset IPA
  266. \arg RCU_ENETRST: reset ENET
  267. \arg RCU_USBHSRST: reset USBHS
  268. \arg RCU_DCIRST: reset DCI
  269. \arg RCU_TRNGRST: reset TRNG
  270. \arg RCU_USBFSRST: reset USBFS
  271. \arg RCU_EXMCRST: reset EXMC
  272. \arg RCU_TIMERxRST (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): reset TIMER
  273. \arg RCU_WWDGTRST: reset WWDGT
  274. \arg RCU_SPIxRST (x=0,1,2,3,4,5): reset SPI
  275. \arg RCU_USARTxRST (x=0,1,2,5): reset USART
  276. \arg RCU_UARTxRST (x=3,4,6,7): reset UART
  277. \arg RCU_I2CxRST (x=0,1,2): reset I2C
  278. \arg RCU_CANxRST (x=0,1): reset CAN
  279. \arg RCU_PMURST: reset PMU
  280. \arg RCU_DACRST: reset DAC
  281. \arg RCU_ADCRST (x=0,1,2): reset ADC
  282. \arg RCU_SDIORST: reset SDIO
  283. \arg RCU_SYSCFGRST: reset SYSCFG
  284. \arg RCU_TLIRST: reset TLI
  285. \arg RCU_CTCRST: reset CTC
  286. \arg RCU_IREFRST: reset IREF
  287. \param[out] none
  288. \retval none
  289. */
  290. void rcu_periph_reset_disable(rcu_periph_reset_enum periph_reset)
  291. {
  292. RCU_REG_VAL(periph_reset) &= ~BIT(RCU_BIT_POS(periph_reset));
  293. }
  294. /*!
  295. \brief reset the BKP
  296. \param[in] none
  297. \param[out] none
  298. \retval none
  299. */
  300. void rcu_bkp_reset_enable(void)
  301. {
  302. RCU_BDCTL |= RCU_BDCTL_BKPRST;
  303. }
  304. /*!
  305. \brief disable the BKP reset
  306. \param[in] none
  307. \param[out] none
  308. \retval none
  309. */
  310. void rcu_bkp_reset_disable(void)
  311. {
  312. RCU_BDCTL &= ~RCU_BDCTL_BKPRST;
  313. }
  314. /*!
  315. \brief configure the system clock source
  316. \param[in] ck_sys: system clock source select
  317. only one parameter can be selected which is shown as below:
  318. \arg RCU_CKSYSSRC_IRC16M: select CK_IRC16M as the CK_SYS source
  319. \arg RCU_CKSYSSRC_HXTAL: select CK_HXTAL as the CK_SYS source
  320. \arg RCU_CKSYSSRC_PLLP: select CK_PLLP as the CK_SYS source
  321. \param[out] none
  322. \retval none
  323. */
  324. void rcu_system_clock_source_config(uint32_t ck_sys)
  325. {
  326. uint32_t reg;
  327. reg = RCU_CFG0;
  328. /* reset the SCS bits and set according to ck_sys */
  329. reg &= ~RCU_CFG0_SCS;
  330. RCU_CFG0 = (reg | ck_sys);
  331. }
  332. /*!
  333. \brief get the system clock source
  334. \param[in] none
  335. \param[out] none
  336. \retval which clock is selected as CK_SYS source
  337. \arg RCU_SCSS_IRC16M: CK_IRC16M is selected as the CK_SYS source
  338. \arg RCU_SCSS_HXTAL: CK_HXTAL is selected as the CK_SYS source
  339. \arg RCU_SCSS_PLLP: CK_PLLP is selected as the CK_SYS source
  340. */
  341. uint32_t rcu_system_clock_source_get(void)
  342. {
  343. return (RCU_CFG0 & RCU_CFG0_SCSS);
  344. }
  345. /*!
  346. \brief configure the AHB clock prescaler selection
  347. \param[in] ck_ahb: AHB clock prescaler selection
  348. only one parameter can be selected which is shown as below:
  349. \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512
  350. \param[out] none
  351. \retval none
  352. */
  353. void rcu_ahb_clock_config(uint32_t ck_ahb)
  354. {
  355. uint32_t reg;
  356. reg = RCU_CFG0;
  357. /* reset the AHBPS bits and set according to ck_ahb */
  358. reg &= ~RCU_CFG0_AHBPSC;
  359. RCU_CFG0 = (reg | ck_ahb);
  360. }
  361. /*!
  362. \brief configure the APB1 clock prescaler selection
  363. \param[in] ck_apb1: APB1 clock prescaler selection
  364. only one parameter can be selected which is shown as below:
  365. \arg RCU_APB1_CKAHB_DIV1: select CK_AHB as CK_APB1
  366. \arg RCU_APB1_CKAHB_DIV2: select CK_AHB/2 as CK_APB1
  367. \arg RCU_APB1_CKAHB_DIV4: select CK_AHB/4 as CK_APB1
  368. \arg RCU_APB1_CKAHB_DIV8: select CK_AHB/8 as CK_APB1
  369. \arg RCU_APB1_CKAHB_DIV16: select CK_AHB/16 as CK_APB1
  370. \param[out] none
  371. \retval none
  372. */
  373. void rcu_apb1_clock_config(uint32_t ck_apb1)
  374. {
  375. uint32_t reg;
  376. reg = RCU_CFG0;
  377. /* reset the APB1PS and set according to ck_apb1 */
  378. reg &= ~RCU_CFG0_APB1PSC;
  379. RCU_CFG0 = (reg | ck_apb1);
  380. }
  381. /*!
  382. \brief configure the APB2 clock prescaler selection
  383. \param[in] ck_apb2: APB2 clock prescaler selection
  384. only one parameter can be selected which is shown as below:
  385. \arg RCU_APB2_CKAHB_DIV1: select CK_AHB as CK_APB2
  386. \arg RCU_APB2_CKAHB_DIV2: select CK_AHB/2 as CK_APB2
  387. \arg RCU_APB2_CKAHB_DIV4: select CK_AHB/4 as CK_APB2
  388. \arg RCU_APB2_CKAHB_DIV8: select CK_AHB/8 as CK_APB2
  389. \arg RCU_APB2_CKAHB_DIV16: select CK_AHB/16 as CK_APB2
  390. \param[out] none
  391. \retval none
  392. */
  393. void rcu_apb2_clock_config(uint32_t ck_apb2)
  394. {
  395. uint32_t reg;
  396. reg = RCU_CFG0;
  397. /* reset the APB2PS and set according to ck_apb2 */
  398. reg &= ~RCU_CFG0_APB2PSC;
  399. RCU_CFG0 = (reg | ck_apb2);
  400. }
  401. /*!
  402. \brief configure the CK_OUT0 clock source and divider
  403. \param[in] ckout0_src: CK_OUT0 clock source selection
  404. only one parameter can be selected which is shown as below:
  405. \arg RCU_CKOUT0SRC_IRC16M: IRC16M selected
  406. \arg RCU_CKOUT0SRC_LXTAL: LXTAL selected
  407. \arg RCU_CKOUT0SRC_HXTAL: HXTAL selected
  408. \arg RCU_CKOUT0SRC_PLLP: PLLP selected
  409. \param[in] ckout0_div: CK_OUT0 divider
  410. \arg RCU_CKOUT0_DIVx(x=1,2,3,4,5): CK_OUT0 is divided by x
  411. \param[out] none
  412. \retval none
  413. */
  414. void rcu_ckout0_config(uint32_t ckout0_src, uint32_t ckout0_div)
  415. {
  416. uint32_t reg;
  417. reg = RCU_CFG0;
  418. /* reset the CKOUT0SRC, CKOUT0DIV and set according to ckout0_src and ckout0_div */
  419. reg &= ~(RCU_CFG0_CKOUT0SEL | RCU_CFG0_CKOUT0DIV );
  420. RCU_CFG0 = (reg | ckout0_src | ckout0_div);
  421. }
  422. /*!
  423. \brief configure the CK_OUT1 clock source and divider
  424. \param[in] ckout1_src: CK_OUT1 clock source selection
  425. only one parameter can be selected which is shown as below:
  426. \arg RCU_CKOUT1SRC_SYSTEMCLOCK: system clock selected
  427. \arg RCU_CKOUT1SRC_PLLI2SR: PLLI2SR selected
  428. \arg RCU_CKOUT1SRC_HXTAL: HXTAL selected
  429. \arg RCU_CKOUT1SRC_PLLP: PLLP selected
  430. \param[in] ckout1_div: CK_OUT1 divider
  431. \arg RCU_CKOUT1_DIVx(x=1,2,3,4,5): CK_OUT1 is divided by x
  432. \param[out] none
  433. \retval none
  434. */
  435. void rcu_ckout1_config(uint32_t ckout1_src, uint32_t ckout1_div)
  436. {
  437. uint32_t reg;
  438. reg = RCU_CFG0;
  439. /* reset the CKOUT1SRC, CKOUT1DIV and set according to ckout1_src and ckout1_div */
  440. reg &= ~(RCU_CFG0_CKOUT1SEL | RCU_CFG0_CKOUT1DIV);
  441. RCU_CFG0 = (reg | ckout1_src | ckout1_div);
  442. }
  443. /*!
  444. \brief configure the main PLL clock
  445. \param[in] pll_src: PLL clock source selection
  446. \arg RCU_PLLSRC_IRC16M: select IRC16M as PLL source clock
  447. \arg RCU_PLLSRC_HXTAL: select HXTAL as PLL source clock
  448. \param[in] pll_psc: the PLL VCO source clock prescaler
  449. \arg this parameter should be selected between 2 and 63
  450. \param[in] pll_n: the PLL VCO clock multi factor
  451. \arg this parameter should be selected between 64 and 500
  452. \param[in] pll_p: the PLLP output frequency division factor from PLL VCO clock
  453. \arg this parameter should be selected 2,4,6,8
  454. \param[in] pll_q: the PLL Q output frequency division factor from PLL VCO clock
  455. \arg this parameter should be selected between 2 and 15
  456. \param[out] none
  457. \retval ErrStatus: SUCCESS or ERROR
  458. */
  459. ErrStatus rcu_pll_config(uint32_t pll_src, uint32_t pll_psc, uint32_t pll_n, uint32_t pll_p, uint32_t pll_q)
  460. {
  461. uint32_t ss_modulation_inc;
  462. uint32_t ss_modulation_reg;
  463. ss_modulation_inc = 0U;
  464. ss_modulation_reg = RCU_PLLSSCTL;
  465. /* calculate the minimum factor of PLLN */
  466. if((ss_modulation_reg & RCU_PLLSSCTL_SSCGON) == RCU_PLLSSCTL_SSCGON){
  467. if((ss_modulation_reg & RCU_SS_TYPE_DOWN) == RCU_SS_TYPE_DOWN){
  468. ss_modulation_inc += RCU_SS_MODULATION_DOWN_INC;
  469. }else{
  470. ss_modulation_inc += RCU_SS_MODULATION_CENTER_INC;
  471. }
  472. }
  473. /* check the function parameter */
  474. if(CHECK_PLL_PSC_VALID(pll_psc) && CHECK_PLL_N_VALID(pll_n,ss_modulation_inc) &&
  475. CHECK_PLL_P_VALID(pll_p) && CHECK_PLL_Q_VALID(pll_q)){
  476. RCU_PLL = pll_psc | (pll_n << 6) | (((pll_p >> 1) - 1U) << 16) |
  477. (pll_src) | (pll_q << 24);
  478. }else{
  479. /* return status */
  480. return ERROR;
  481. }
  482. /* return status */
  483. return SUCCESS;
  484. }
  485. /*!
  486. \brief configure the PLLI2S clock
  487. \param[in] plli2s_n: the PLLI2S VCO clock multi factor
  488. \arg this parameter should be selected between 50 and 500
  489. \param[in] plli2s_q: the PLLI2S Q output frequency division factor from PLLI2S VCO clock
  490. \arg this parameter should be selected between 2 and 15
  491. \param[in] plli2s_r: the PLLI2S R output frequency division factor from PLLI2S VCO clock
  492. \arg this parameter should be selected between 2 and 7
  493. \param[out] none
  494. \retval ErrStatus: SUCCESS or ERROR
  495. */
  496. ErrStatus rcu_plli2s_config(uint32_t plli2s_n, uint32_t plli2s_q, uint32_t plli2s_r)
  497. {
  498. /* check the function parameter */
  499. if(CHECK_PLLI2S_N_VALID(plli2s_n) && CHECK_PLLI2S_Q_VALID(plli2s_q) && CHECK_PLLI2S_R_VALID(plli2s_r)){
  500. RCU_PLLI2S = (plli2s_n << 6) | (plli2s_q << 24) | (plli2s_r << 28);
  501. }else{
  502. /* return status */
  503. return ERROR;
  504. }
  505. /* return status */
  506. return SUCCESS;
  507. }
  508. /*!
  509. \brief configure the PLLSAI clock
  510. \param[in] pllsai_n: the PLLSAI VCO clock multi factor
  511. \arg this parameter should be selected between 50 and 500
  512. \param[in] pllsai_p: the PLLSAI P output frequency division factor from PLL VCO clock
  513. \arg this parameter should be selected 2,4,6,8
  514. \param[in] pllsai_q: the PLLSAI Q output frequency division factor from PLL VCO clock
  515. \arg this parameter should be selected between 2 and 15
  516. \param[in] pllsai_r: the PLLSAI R output frequency division factor from PLL VCO clock
  517. \arg this parameter should be selected between 2 and 7
  518. \param[out] none
  519. \retval ErrStatus: SUCCESS or ERROR
  520. */
  521. ErrStatus rcu_pllsai_config(uint32_t pllsai_n, uint32_t pllsai_p, uint32_t pllsai_q, uint32_t pllsai_r)
  522. {
  523. /* check the function parameter */
  524. if(CHECK_PLLSAI_N_VALID(pllsai_n) && CHECK_PLLSAI_P_VALID(pllsai_p) &&
  525. CHECK_PLLSAI_Q_VALID(pllsai_q) && CHECK_PLLSAI_R_VALID(pllsai_r)){
  526. RCU_PLLSAI = (pllsai_n << 6U) | (((pllsai_p >> 1U) - 1U) << 16U) | (pllsai_q << 24U) | (pllsai_r << 28U);
  527. }else{
  528. /* return status */
  529. return ERROR;
  530. }
  531. /* return status */
  532. return SUCCESS;
  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_IRC32K: CK_IRC32K selected as RTC source clock
  541. \arg RCU_RTCSRC_HXTAL_DIV_RTCDIV: CK_HXTAL/RTCDIV 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. /*!
  554. \brief configure the I2S clock source selection
  555. \param[in] i2s_clock_source: I2S clock source selection
  556. only one parameter can be selected which is shown as below:
  557. \arg RCU_I2SSRC_PLLI2S: CK_PLLI2S selected as I2S source clock
  558. \arg RCU_I2SSRC_I2S_CKIN: external i2s_ckin pin selected as I2S source clock
  559. \param[out] none
  560. \retval none
  561. */
  562. void rcu_i2s_clock_config(uint32_t i2s_clock_source)
  563. {
  564. uint32_t reg;
  565. reg = RCU_CFG0;
  566. /* reset the I2SSEL bit and set according to i2s_clock_source */
  567. reg &= ~RCU_CFG0_I2SSEL;
  568. RCU_CFG0 = (reg | i2s_clock_source);
  569. }
  570. /*!
  571. \brief configure the CK48M clock source selection
  572. \param[in] ck48m_clock_source: CK48M clock source selection
  573. only one parameter can be selected which is shown as below:
  574. \arg RCU_CK48MSRC_PLL48M: CK_PLL48M selected as CK48M source clock
  575. \arg RCU_CK48MSRC_IRC48M: CK_IRC48M selected as CK48M source clock
  576. \param[out] none
  577. \retval none
  578. */
  579. void rcu_ck48m_clock_config(uint32_t ck48m_clock_source)
  580. {
  581. uint32_t reg;
  582. reg = RCU_ADDCTL;
  583. /* reset the I2SSEL bit and set according to i2s_clock_source */
  584. reg &= ~RCU_ADDCTL_CK48MSEL;
  585. RCU_ADDCTL = (reg | ck48m_clock_source);
  586. }
  587. /*!
  588. \brief configure the PLL48M clock source selection
  589. \param[in] pll48m_clock_source: PLL48M clock source selection
  590. only one parameter can be selected which is shown as below:
  591. \arg RCU_PLL48MSRC_PLLQ: CK_PLLQ selected as PLL48M source clock
  592. \arg RCU_PLL48MSRC_PLLSAIP: CK_PLLSAIP selected as PLL48M source clock
  593. \param[out] none
  594. \retval none
  595. */
  596. void rcu_pll48m_clock_config(uint32_t pll48m_clock_source)
  597. {
  598. uint32_t reg;
  599. reg = RCU_ADDCTL;
  600. /* reset the PLL48MSEL bit and set according to pll48m_clock_source */
  601. reg &= ~RCU_ADDCTL_PLL48MSEL;
  602. RCU_ADDCTL = (reg | pll48m_clock_source);
  603. }
  604. /*!
  605. \brief configure the TIMER clock prescaler selection
  606. \param[in] timer_clock_prescaler: TIMER clock selection
  607. only one parameter can be selected which is shown as below:
  608. \arg RCU_TIMER_PSC_MUL2: if APB1PSC/APB2PSC in RCU_CFG0 register is 0b0xx(CK_APBx = CK_AHB)
  609. or 0b100(CK_APBx = CK_AHB/2), the TIMER clock is equal to CK_AHB(CK_TIMERx = CK_AHB).
  610. or else, the TIMER clock is twice the corresponding APB clock (TIMER in APB1 domain: CK_TIMERx = 2 x CK_APB1;
  611. TIMER in APB2 domain: CK_TIMERx = 2 x CK_APB2)
  612. \arg RCU_TIMER_PSC_MUL4: if APB1PSC/APB2PSC in RCU_CFG0 register is 0b0xx(CK_APBx = CK_AHB),
  613. 0b100(CK_APBx = CK_AHB/2), or 0b101(CK_APBx = CK_AHB/4), the TIMER clock is equal to CK_AHB(CK_TIMERx = CK_AHB).
  614. or else, the TIMER clock is four timers the corresponding APB clock (TIMER in APB1 domain: CK_TIMERx = 4 x CK_APB1;
  615. TIMER in APB2 domain: CK_TIMERx = 4 x CK_APB2)
  616. \param[out] none
  617. \retval none
  618. */
  619. void rcu_timer_clock_prescaler_config(uint32_t timer_clock_prescaler)
  620. {
  621. /* configure the TIMERSEL bit and select the TIMER clock prescaler */
  622. if(timer_clock_prescaler == RCU_TIMER_PSC_MUL2){
  623. RCU_CFG1 &= timer_clock_prescaler;
  624. }else{
  625. RCU_CFG1 |= timer_clock_prescaler;
  626. }
  627. }
  628. /*!
  629. \brief configure the PLLSAIR divider used as input of TLI
  630. \param[in] pllsai_r_div: PLLSAIR divider used as input of TLI
  631. only one parameter can be selected which is shown as below:
  632. \arg RCU_PLLSAIR_DIVx(x=2,4,8,16): PLLSAIR divided x used as input of TLI
  633. \param[out] none
  634. \retval none
  635. */
  636. void rcu_tli_clock_div_config(uint32_t pllsai_r_div)
  637. {
  638. uint32_t reg;
  639. reg = RCU_CFG1;
  640. /* reset the PLLSAIRDIV bit and set according to pllsai_r_div */
  641. reg &= ~RCU_CFG1_PLLSAIRDIV;
  642. RCU_CFG1 = (reg | pllsai_r_div);
  643. }
  644. /*!
  645. \brief get the clock stabilization and periphral reset flags
  646. \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum
  647. only one parameter can be selected which is shown as below:
  648. \arg RCU_FLAG_IRC16MSTB: IRC16M stabilization flag
  649. \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag
  650. \arg RCU_FLAG_PLLSTB: PLL stabilization flag
  651. \arg RCU_FLAG_PLLI2SSTB: PLLI2S stabilization flag
  652. \arg RCU_FLAG_PLLSAISTB: PLLSAI stabilization flag
  653. \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag
  654. \arg RCU_FLAG_IRC32KSTB: IRC32K stabilization flag
  655. \arg RCU_FLAG_IRC48MSTB: IRC48M stabilization flag
  656. \arg RCU_FLAG_BORRST: BOR reset flags
  657. \arg RCU_FLAG_EPRST: external PIN reset flag
  658. \arg RCU_FLAG_PORRST: Power reset flag
  659. \arg RCU_FLAG_SWRST: software reset flag
  660. \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag
  661. \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag
  662. \arg RCU_FLAG_LPRST: low-power reset flag
  663. \param[out] none
  664. \retval none
  665. */
  666. FlagStatus rcu_flag_get(rcu_flag_enum flag)
  667. {
  668. /* get the rcu flag */
  669. if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){
  670. return SET;
  671. }else{
  672. return RESET;
  673. }
  674. }
  675. /*!
  676. \brief clear all the reset flag
  677. \param[in] none
  678. \param[out] none
  679. \retval none
  680. */
  681. void rcu_all_reset_flag_clear(void)
  682. {
  683. RCU_RSTSCK |= RCU_RSTSCK_RSTFC;
  684. }
  685. /*!
  686. \brief get the clock stabilization interrupt and ckm flags
  687. \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum
  688. only one parameter can be selected which is shown as below:
  689. \arg RCU_INT_FLAG_IRC32KSTB: IRC40K stabilization interrupt flag
  690. \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag
  691. \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag
  692. \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag
  693. \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag
  694. \arg RCU_INT_FLAG_PLLI2SSTB: PLLI2S stabilization interrupt flag
  695. \arg RCU_INT_FLAG_PLLSAISTB: PLLSAI stabilization interrupt flag
  696. \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag
  697. \arg RCU_INT_FLAG_IRC48MSTB: IRC48M stabilization interrupt flag
  698. \param[out] none
  699. \retval FlagStatus: SET or RESET
  700. */
  701. FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag)
  702. {
  703. /* get the rcu interrupt flag */
  704. if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){
  705. return SET;
  706. }else{
  707. return RESET;
  708. }
  709. }
  710. /*!
  711. \brief clear the interrupt flags
  712. \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum
  713. only one parameter can be selected which is shown as below:
  714. \arg RCU_INT_FLAG_IRC32KSTB_CLR: IRC32K stabilization interrupt flag clear
  715. \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear
  716. \arg RCU_INT_FLAG_IRC16MSTB_CLR: IRC16M stabilization interrupt flag clear
  717. \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear
  718. \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear
  719. \arg RCU_INT_FLAG_PLLI2SSTB_CLR: PLLI2S stabilization interrupt flag clear
  720. \arg RCU_INT_FLAG_PLLSAISTB_CLR: PLLSAI stabilization interrupt flag clear
  721. \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear
  722. \arg RCU_INT_FLAG_IRC48MSTB_CLR: IRC48M stabilization interrupt flag clear
  723. \param[out] none
  724. \retval none
  725. */
  726. void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear)
  727. {
  728. RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear));
  729. }
  730. /*!
  731. \brief enable the stabilization interrupt
  732. \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum
  733. Only one parameter can be selected which is shown as below:
  734. \arg RCU_INT_IRC32KSTB: IRC32K stabilization interrupt enable
  735. \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable
  736. \arg RCU_INT_IRC16MSTB: IRC16M stabilization interrupt enable
  737. \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable
  738. \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable
  739. \arg RCU_INT_PLLI2SSTB: PLLI2S stabilization interrupt enable
  740. \arg RCU_INT_PLLSAISTB: PLLSAI stabilization interrupt enable
  741. \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt enable
  742. \param[out] none
  743. \retval none
  744. */
  745. void rcu_interrupt_enable(rcu_int_enum stab_int)
  746. {
  747. RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int));
  748. }
  749. /*!
  750. \brief disable the stabilization interrupt
  751. \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum
  752. only one parameter can be selected which is shown as below:
  753. \arg RCU_INT_IRC32KSTB: IRC32K stabilization interrupt disable
  754. \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt disable
  755. \arg RCU_INT_IRC16MSTB: IRC16M stabilization interrupt disable
  756. \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt disable
  757. \arg RCU_INT_PLLSTB: PLL stabilization interrupt disable
  758. \arg RCU_INT_PLLI2SSTB: PLLI2S stabilization interrupt disable
  759. \arg RCU_INT_PLLSAISTB: PLLSAI stabilization interrupt disable
  760. \arg RCU_INT_IRC48MSTB: IRC48M stabilization interrupt disable
  761. \param[out] none
  762. \retval none
  763. */
  764. void rcu_interrupt_disable(rcu_int_enum stab_int)
  765. {
  766. RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int));
  767. }
  768. /*!
  769. \brief configure the LXTAL drive capability
  770. \param[in] lxtal_dricap: drive capability of LXTAL
  771. only one parameter can be selected which is shown as below:
  772. \arg RCU_LXTALDRI_LOWER_DRIVE: lower driving capability
  773. \arg RCU_LXTALDRI_HIGHER_DRIVE: higher driving capability
  774. \param[out] none
  775. \retval none
  776. */
  777. void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap)
  778. {
  779. uint32_t reg;
  780. reg = RCU_BDCTL;
  781. /* reset the LXTALDRI bits and set according to lxtal_dricap */
  782. reg &= ~RCU_BDCTL_LXTALDRI;
  783. RCU_BDCTL = (reg | lxtal_dricap);
  784. }
  785. /*!
  786. \brief wait for oscillator stabilization flags is SET or oscillator startup is timeout
  787. \param[in] osci: oscillator types, refer to rcu_osci_type_enum
  788. only one parameter can be selected which is shown as below:
  789. \arg RCU_HXTAL: HXTAL
  790. \arg RCU_LXTAL: LXTAL
  791. \arg RCU_IRC16M: IRC16M
  792. \arg RCU_IRC48M: IRC48M
  793. \arg RCU_IRC32K: IRC32K
  794. \arg RCU_PLL_CK: PLL
  795. \arg RCU_PLLI2S_CK: PLLI2S
  796. \arg RCU_PLLSAI_CK: PLLSAI
  797. \param[out] none
  798. \retval ErrStatus: SUCCESS or ERROR
  799. */
  800. ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci)
  801. {
  802. uint32_t stb_cnt = 0U;
  803. ErrStatus reval = ERROR;
  804. FlagStatus osci_stat = RESET;
  805. switch(osci){
  806. /* wait HXTAL stable */
  807. case RCU_HXTAL:
  808. while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){
  809. osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB);
  810. stb_cnt++;
  811. }
  812. /* check whether flag is set */
  813. if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){
  814. reval = SUCCESS;
  815. }
  816. break;
  817. /* wait LXTAL stable */
  818. case RCU_LXTAL:
  819. while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){
  820. osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB);
  821. stb_cnt++;
  822. }
  823. /* check whether flag is set */
  824. if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){
  825. reval = SUCCESS;
  826. }
  827. break;
  828. /* wait IRC16M stable */
  829. case RCU_IRC16M:
  830. while((RESET == osci_stat) && (IRC16M_STARTUP_TIMEOUT != stb_cnt)){
  831. osci_stat = rcu_flag_get(RCU_FLAG_IRC16MSTB);
  832. stb_cnt++;
  833. }
  834. /* check whether flag is set */
  835. if(RESET != rcu_flag_get(RCU_FLAG_IRC16MSTB)){
  836. reval = SUCCESS;
  837. }
  838. break;
  839. /* wait IRC48M stable */
  840. case RCU_IRC48M:
  841. while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
  842. osci_stat = rcu_flag_get(RCU_FLAG_IRC48MSTB);
  843. stb_cnt++;
  844. }
  845. /* check whether flag is set */
  846. if (RESET != rcu_flag_get(RCU_FLAG_IRC48MSTB)){
  847. reval = SUCCESS;
  848. }
  849. break;
  850. /* wait IRC32K stable */
  851. case RCU_IRC32K:
  852. while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
  853. osci_stat = rcu_flag_get(RCU_FLAG_IRC32KSTB);
  854. stb_cnt++;
  855. }
  856. /* check whether flag is set */
  857. if(RESET != rcu_flag_get(RCU_FLAG_IRC32KSTB)){
  858. reval = SUCCESS;
  859. }
  860. break;
  861. /* wait PLL stable */
  862. case RCU_PLL_CK:
  863. while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
  864. osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB);
  865. stb_cnt++;
  866. }
  867. /* check whether flag is set */
  868. if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){
  869. reval = SUCCESS;
  870. }
  871. break;
  872. /* wait PLLI2S stable */
  873. case RCU_PLLI2S_CK:
  874. while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
  875. osci_stat = rcu_flag_get(RCU_FLAG_PLLI2SSTB);
  876. stb_cnt++;
  877. }
  878. /* check whether flag is set */
  879. if(RESET != rcu_flag_get(RCU_FLAG_PLLI2SSTB)){
  880. reval = SUCCESS;
  881. }
  882. break;
  883. /* wait PLLSAI stable */
  884. case RCU_PLLSAI_CK:
  885. while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){
  886. osci_stat = rcu_flag_get(RCU_FLAG_PLLSAISTB);
  887. stb_cnt++;
  888. }
  889. /* check whether flag is set */
  890. if(RESET != rcu_flag_get(RCU_FLAG_PLLSAISTB)){
  891. reval = SUCCESS;
  892. }
  893. break;
  894. default:
  895. break;
  896. }
  897. /* return value */
  898. return reval;
  899. }
  900. /*!
  901. \brief turn on the oscillator
  902. \param[in] osci: oscillator types, refer to rcu_osci_type_enum
  903. only one parameter can be selected which is shown as below:
  904. \arg RCU_HXTAL: HXTAL
  905. \arg RCU_LXTAL: LXTAL
  906. \arg RCU_IRC16M: IRC16M
  907. \arg RCU_IRC48M: IRC48M
  908. \arg RCU_IRC32K: IRC32K
  909. \arg RCU_PLL_CK: PLL
  910. \arg RCU_PLLI2S_CK: PLLI2S
  911. \arg RCU_PLLSAI_CK: PLLSAI
  912. \param[out] none
  913. \retval none
  914. */
  915. void rcu_osci_on(rcu_osci_type_enum osci)
  916. {
  917. RCU_REG_VAL(osci) |= BIT(RCU_BIT_POS(osci));
  918. }
  919. /*!
  920. \brief turn off the oscillator
  921. \param[in] osci: oscillator types, refer to rcu_osci_type_enum
  922. only one parameter can be selected which is shown as below:
  923. \arg RCU_HXTAL: HXTAL
  924. \arg RCU_LXTAL: LXTAL
  925. \arg RCU_IRC16M: IRC16M
  926. \arg RCU_IRC48M: IRC48M
  927. \arg RCU_IRC32K: IRC32K
  928. \arg RCU_PLL_CK: PLL
  929. \arg RCU_PLLI2S_CK: PLLI2S
  930. \arg RCU_PLLSAI_CK: PLLSAI
  931. \param[out] none
  932. \retval none
  933. */
  934. void rcu_osci_off(rcu_osci_type_enum osci)
  935. {
  936. RCU_REG_VAL(osci) &= ~BIT(RCU_BIT_POS(osci));
  937. }
  938. /*!
  939. \brief enable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
  940. \param[in] osci: oscillator types, refer to rcu_osci_type_enum
  941. only one parameter can be selected which is shown as below:
  942. \arg RCU_HXTAL: HXTAL
  943. \arg RCU_LXTAL: LXTAL
  944. \param[out] none
  945. \retval none
  946. */
  947. void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci)
  948. {
  949. uint32_t reg;
  950. switch(osci){
  951. /* enable HXTAL to bypass mode */
  952. case RCU_HXTAL:
  953. reg = RCU_CTL;
  954. RCU_CTL &= ~RCU_CTL_HXTALEN;
  955. RCU_CTL = (reg | RCU_CTL_HXTALBPS);
  956. break;
  957. /* enable LXTAL to bypass mode */
  958. case RCU_LXTAL:
  959. reg = RCU_BDCTL;
  960. RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
  961. RCU_BDCTL = (reg | RCU_BDCTL_LXTALBPS);
  962. break;
  963. case RCU_IRC16M:
  964. case RCU_IRC48M:
  965. case RCU_IRC32K:
  966. case RCU_PLL_CK:
  967. case RCU_PLLI2S_CK:
  968. case RCU_PLLSAI_CK:
  969. break;
  970. default:
  971. break;
  972. }
  973. }
  974. /*!
  975. \brief disable the oscillator bypass mode, HXTALEN or LXTALEN must be reset before it
  976. \param[in] osci: oscillator types, refer to rcu_osci_type_enum
  977. only one parameter can be selected which is shown as below:
  978. \arg RCU_HXTAL: HXTAL
  979. \arg RCU_LXTAL: LXTAL
  980. \param[out] none
  981. \retval none
  982. */
  983. void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci)
  984. {
  985. uint32_t reg;
  986. switch(osci){
  987. /* disable HXTAL to bypass mode */
  988. case RCU_HXTAL:
  989. reg = RCU_CTL;
  990. RCU_CTL &= ~RCU_CTL_HXTALEN;
  991. RCU_CTL = (reg & ~RCU_CTL_HXTALBPS);
  992. break;
  993. /* disable LXTAL to bypass mode */
  994. case RCU_LXTAL:
  995. reg = RCU_BDCTL;
  996. RCU_BDCTL &= ~RCU_BDCTL_LXTALEN;
  997. RCU_BDCTL = (reg & ~RCU_BDCTL_LXTALBPS);
  998. break;
  999. case RCU_IRC16M:
  1000. case RCU_IRC48M:
  1001. case RCU_IRC32K:
  1002. case RCU_PLL_CK:
  1003. case RCU_PLLI2S_CK:
  1004. case RCU_PLLSAI_CK:
  1005. break;
  1006. default:
  1007. break;
  1008. }
  1009. }
  1010. /*!
  1011. \brief enable the HXTAL clock monitor
  1012. \param[in] none
  1013. \param[out] none
  1014. \retval none
  1015. */
  1016. void rcu_hxtal_clock_monitor_enable(void)
  1017. {
  1018. RCU_CTL |= RCU_CTL_CKMEN;
  1019. }
  1020. /*!
  1021. \brief disable the HXTAL clock monitor
  1022. \param[in] none
  1023. \param[out] none
  1024. \retval none
  1025. */
  1026. void rcu_hxtal_clock_monitor_disable(void)
  1027. {
  1028. RCU_CTL &= ~RCU_CTL_CKMEN;
  1029. }
  1030. /*!
  1031. \brief set the IRC16M adjust value
  1032. \param[in] irc16m_adjval: IRC16M adjust value, must be between 0 and 0x1F
  1033. \param[out] none
  1034. \retval none
  1035. */
  1036. void rcu_irc16m_adjust_value_set(uint32_t irc16m_adjval)
  1037. {
  1038. uint32_t reg;
  1039. reg = RCU_CTL;
  1040. /* reset the IRC16MADJ bits and set according to irc16m_adjval */
  1041. reg &= ~RCU_CTL_IRC16MADJ;
  1042. RCU_CTL = (reg | ((irc16m_adjval & 0x1FU) << 3));
  1043. }
  1044. /*!
  1045. \brief unlock the voltage key
  1046. \param[in] none
  1047. \param[out] none
  1048. \retval none
  1049. */
  1050. void rcu_voltage_key_unlock(void)
  1051. {
  1052. RCU_VKEY = RCU_VKEY_UNLOCK;
  1053. }
  1054. /*!
  1055. \brief deep-sleep mode voltage select
  1056. \param[in] dsvol: deep sleep mode voltage
  1057. only one parameter can be selected which is shown as below:
  1058. \arg RCU_DEEPSLEEP_V_1_2: the core voltage is 1.2V
  1059. \arg RCU_DEEPSLEEP_V_1_1: the core voltage is 1.1V
  1060. \arg RCU_DEEPSLEEP_V_1_0: the core voltage is 1.0V
  1061. \arg RCU_DEEPSLEEP_V_0_9: the core voltage is 0.9V
  1062. \param[out] none
  1063. \retval none
  1064. */
  1065. void rcu_deepsleep_voltage_set(uint32_t dsvol)
  1066. {
  1067. dsvol &= RCU_DSV_DSLPVS;
  1068. RCU_DSV = dsvol;
  1069. }
  1070. /*!
  1071. \brief configure the spread spectrum modulation for the main PLL clock
  1072. \param[in] spread_spectrum_type: PLL spread spectrum modulation type select
  1073. \arg RCU_SS_TYPE_CENTER: center spread type is selected
  1074. \arg RCU_SS_TYPE_DOWN: down spread type is selected
  1075. \param[in] modstep: configure PLL spread spectrum modulation profile amplitude and frequency
  1076. \arg This parameter should be selected between 0 and 7FFF.The following criteria must be met: MODSTEP*MODCNT=215-1
  1077. \param[in] modcnt: configure PLL spread spectrum modulation profile amplitude and frequency
  1078. \arg This parameter should be selected between 0 and 1FFF.The following criteria must be met: MODSTEP*MODCNT=215-1
  1079. \param[out] none
  1080. \retval none
  1081. */
  1082. void rcu_spread_spectrum_config(uint32_t spread_spectrum_type, uint32_t modstep, uint32_t modcnt)
  1083. {
  1084. uint32_t reg;
  1085. reg = RCU_PLLSSCTL;
  1086. /* reset the RCU_PLLSSCTL register bits */
  1087. reg &= ~(RCU_PLLSSCTL_MODCNT | RCU_PLLSSCTL_MODSTEP | RCU_PLLSSCTL_SS_TYPE);
  1088. RCU_PLLSSCTL = (reg | spread_spectrum_type | modstep << 13 | modcnt);
  1089. }
  1090. /*!
  1091. \brief enable the PLL spread spectrum modulation
  1092. \param[in] none
  1093. \param[out] none
  1094. \retval none
  1095. */
  1096. void rcu_spread_spectrum_enable(void)
  1097. {
  1098. RCU_PLLSSCTL |= RCU_PLLSSCTL_SSCGON;
  1099. }
  1100. /*!
  1101. \brief disable the PLL spread spectrum modulation
  1102. \param[in] none
  1103. \param[out] none
  1104. \retval none
  1105. */
  1106. void rcu_spread_spectrum_disable(void)
  1107. {
  1108. RCU_PLLSSCTL &= ~RCU_PLLSSCTL_SSCGON;
  1109. }
  1110. /*!
  1111. \brief get the system clock, bus and peripheral clock frequency
  1112. \param[in] clock: the clock frequency which to get
  1113. only one parameter can be selected which is shown as below:
  1114. \arg CK_SYS: system clock frequency
  1115. \arg CK_AHB: AHB clock frequency
  1116. \arg CK_APB1: APB1 clock frequency
  1117. \arg CK_APB2: APB2 clock frequency
  1118. \param[out] none
  1119. \retval clock frequency of system, AHB, APB1, APB2
  1120. */
  1121. uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock)
  1122. {
  1123. uint32_t sws, ck_freq = 0U;
  1124. uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq;
  1125. uint32_t pllpsc, plln, pllsel, pllp, ck_src, idx, clk_exp;
  1126. /* exponent of AHB, APB1 and APB2 clock divider */
  1127. const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
  1128. const uint8_t apb1_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
  1129. const uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4};
  1130. sws = GET_BITS(RCU_CFG0, 2, 3);
  1131. switch(sws){
  1132. /* IRC16M is selected as CK_SYS */
  1133. case SEL_IRC16M:
  1134. cksys_freq = IRC16M_VALUE;
  1135. break;
  1136. /* HXTAL is selected as CK_SYS */
  1137. case SEL_HXTAL:
  1138. cksys_freq = HXTAL_VALUE;
  1139. break;
  1140. /* PLLP is selected as CK_SYS */
  1141. case SEL_PLLP:
  1142. /* get the value of PLLPSC[5:0] */
  1143. pllpsc = GET_BITS(RCU_PLL, 0U, 5U);
  1144. plln = GET_BITS(RCU_PLL, 6U, 14U);
  1145. pllp = (GET_BITS(RCU_PLL, 16U, 17U) + 1U) * 2U;
  1146. /* PLL clock source selection, HXTAL or IRC8M/2 */
  1147. pllsel = (RCU_PLL & RCU_PLL_PLLSEL);
  1148. if (RCU_PLLSRC_HXTAL == pllsel) {
  1149. ck_src = HXTAL_VALUE;
  1150. } else {
  1151. ck_src = IRC16M_VALUE;
  1152. }
  1153. cksys_freq = ((ck_src / pllpsc) * plln)/pllp;
  1154. break;
  1155. /* IRC16M is selected as CK_SYS */
  1156. default:
  1157. cksys_freq = IRC16M_VALUE;
  1158. break;
  1159. }
  1160. /* calculate AHB clock frequency */
  1161. idx = GET_BITS(RCU_CFG0, 4, 7);
  1162. clk_exp = ahb_exp[idx];
  1163. ahb_freq = cksys_freq >> clk_exp;
  1164. /* calculate APB1 clock frequency */
  1165. idx = GET_BITS(RCU_CFG0, 10, 12);
  1166. clk_exp = apb1_exp[idx];
  1167. apb1_freq = ahb_freq >> clk_exp;
  1168. /* calculate APB2 clock frequency */
  1169. idx = GET_BITS(RCU_CFG0, 13, 15);
  1170. clk_exp = apb2_exp[idx];
  1171. apb2_freq = ahb_freq >> clk_exp;
  1172. /* return the clocks frequency */
  1173. switch(clock){
  1174. case CK_SYS:
  1175. ck_freq = cksys_freq;
  1176. break;
  1177. case CK_AHB:
  1178. ck_freq = ahb_freq;
  1179. break;
  1180. case CK_APB1:
  1181. ck_freq = apb1_freq;
  1182. break;
  1183. case CK_APB2:
  1184. ck_freq = apb2_freq;
  1185. break;
  1186. default:
  1187. break;
  1188. }
  1189. return ck_freq;
  1190. }