gd32f4xx_rcu.c 47 KB

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