1
0

am_hal_clkgen.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. //*****************************************************************************
  2. //
  3. // am_hal_clkgen.c
  4. //! @file
  5. //!
  6. //! @brief Functions for interfacing with the CLKGEN.
  7. //!
  8. //! @addtogroup clkgen2 Clock Generator (CLKGEN)
  9. //! @ingroup apollo2hal
  10. //! @{
  11. //
  12. //*****************************************************************************
  13. //*****************************************************************************
  14. //
  15. // Copyright (c) 2017, Ambiq Micro
  16. // All rights reserved.
  17. //
  18. // Redistribution and use in source and binary forms, with or without
  19. // modification, are permitted provided that the following conditions are met:
  20. //
  21. // 1. Redistributions of source code must retain the above copyright notice,
  22. // this list of conditions and the following disclaimer.
  23. //
  24. // 2. Redistributions in binary form must reproduce the above copyright
  25. // notice, this list of conditions and the following disclaimer in the
  26. // documentation and/or other materials provided with the distribution.
  27. //
  28. // 3. Neither the name of the copyright holder nor the names of its
  29. // contributors may be used to endorse or promote products derived from this
  30. // software without specific prior written permission.
  31. //
  32. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  33. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  34. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  36. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  37. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  38. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  39. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  40. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  41. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  42. // POSSIBILITY OF SUCH DAMAGE.
  43. //
  44. // This is part of revision 1.2.9 of the AmbiqSuite Development Package.
  45. //
  46. //*****************************************************************************
  47. #include <stdint.h>
  48. #include <stdbool.h>
  49. #include "am_mcu_apollo.h"
  50. //*****************************************************************************
  51. //
  52. // CLKGEN HFADJ register
  53. //
  54. //*****************************************************************************
  55. #define AM_REG_CLKGEN_HFADJ_HFXTADJ_DEFAULT 0x5B8
  56. //*****************************************************************************
  57. //
  58. //! @brief Select the clock divisor for the main system clock.
  59. //!
  60. //! @param ui32ClockSetting - The divisor value for the system clock.
  61. //!
  62. //! This function can be used to select the frequency of the main system clock.
  63. //! The \e ui32ClockSetting parameter should be set to one of the following
  64. //! values:
  65. //!
  66. //! AM_HAL_CLKGEN_SYSCLK_MAX
  67. //! AM_HAL_CLKGEN_SYSCLK_48MHZ
  68. //!
  69. //! @return None.
  70. //
  71. //*****************************************************************************
  72. void
  73. am_hal_clkgen_sysclk_select(uint32_t ui32ClockSetting)
  74. {
  75. am_hal_debug_assert_msg(ui32ClockSetting == AM_HAL_CLKGEN_SYSCLK_48MHZ,
  76. "am_hal_clkgen_sysclk_select(): invalid clock setting.");
  77. //
  78. // Unlock the clock control register.
  79. //
  80. AM_REG(CLKGEN, CLKKEY) = AM_REG_CLKGEN_CLKKEY_KEYVAL;
  81. //
  82. // Set the HFRC divisor to the user-selected value.
  83. //
  84. AM_REG(CLKGEN, CCTRL) = ui32ClockSetting;
  85. //
  86. // Lock the clock configuration registers.
  87. //
  88. AM_REG(CLKGEN, CLKKEY) = 0;
  89. }
  90. //*****************************************************************************
  91. //
  92. //! @brief Get the current system clock frequency.
  93. //!
  94. //! This function can be used to determine the frequency of the main system
  95. //! clock. The return value is the system clock frequency measured in hertz.
  96. //!
  97. //! @return System clock frequency in Hz
  98. //
  99. //*****************************************************************************
  100. uint32_t
  101. am_hal_clkgen_sysclk_get(void)
  102. {
  103. uint32_t ui32ClockSetting;
  104. //
  105. // Read the value of the clock divider.
  106. //
  107. ui32ClockSetting = AM_REG(CLKGEN, CCTRL) & AM_REG_CLKGEN_CCTRL_CORESEL_M;
  108. switch ( ui32ClockSetting )
  109. {
  110. case AM_REG_CLKGEN_CCTRL_CORESEL_HFRC:
  111. return 48000000;
  112. case AM_REG_CLKGEN_CCTRL_CORESEL_HFRC_DIV2:
  113. return 24000000;
  114. default:
  115. return 0xFFFFFFFF;
  116. }
  117. }
  118. //*****************************************************************************
  119. //
  120. //! @brief Enable selected CLKGEN Interrupts.
  121. //!
  122. //! Use this function to enable the interrupts.
  123. //!
  124. //! @param ui32Interrupt - Use the macro bit fields provided in am_hal_clkgen.h
  125. //!
  126. //! @return None
  127. //
  128. //*****************************************************************************
  129. void
  130. am_hal_clkgen_int_enable(uint32_t ui32Interrupt)
  131. {
  132. //
  133. // Enable the interrupts.
  134. //
  135. AM_REG(CLKGEN, INTEN) |= ui32Interrupt;
  136. }
  137. //*****************************************************************************
  138. //
  139. //! @brief Return enabled CLKGEN Interrupts.
  140. //!
  141. //! Use this function to get all enabled CLKGEN interrupts.
  142. //!
  143. //! @return enabled CLKGEN interrupts.
  144. //
  145. //*****************************************************************************
  146. uint32_t
  147. am_hal_clkgen_int_enable_get(void)
  148. {
  149. //
  150. // Return the enabled interrupts.
  151. //
  152. return AM_REG(CLKGEN, INTEN);
  153. }
  154. //*****************************************************************************
  155. //
  156. //! @brief Disable selected CLKGEN Interrupts.
  157. //!
  158. //! Use this function to disable the CLKGEN interrupts.
  159. //!
  160. //! @param ui32Interrupt - Use the macro bit fields provided in am_hal_clkgen.h
  161. //!
  162. //! @return None
  163. //
  164. //*****************************************************************************
  165. void
  166. am_hal_clkgen_int_disable(uint32_t ui32Interrupt)
  167. {
  168. //
  169. // Disable the interrupts.
  170. //
  171. AM_REG(CLKGEN, INTEN) &= ~ui32Interrupt;
  172. }
  173. //*****************************************************************************
  174. //
  175. //! @brief Sets the interrupt status.
  176. //!
  177. //! @param ui32IntFlags interrupts to be enabled.
  178. //!
  179. //! This function sets the interrupts.
  180. //!
  181. //! Valid values for ui32IntFlags are:
  182. //!
  183. //! AM_HAL_CLKGEN_INT_RTC_ALARM
  184. //! AM_HAL_CLKGEN_INT_XT_FAIL
  185. //! AM_HAL_CLKGEN_INT_AUTOCAL_COMPLETE
  186. //! AM_HAL_CLKGEN_INT AUTOCAL_FAIL
  187. //!
  188. //! @return None.
  189. //
  190. //*****************************************************************************
  191. void
  192. am_hal_clkgen_int_set(uint32_t ui32Interrupt)
  193. {
  194. //
  195. // Set the interrupt status.
  196. //
  197. AM_REG(CLKGEN, INTSET) = ui32Interrupt;
  198. }
  199. //*****************************************************************************
  200. //
  201. //! @brief Gets the interrupt configuration.
  202. //!
  203. //! @param bEnabledOnly - return the status of only the enabled interrupts.
  204. //!
  205. //! This function gets the currently configured interrupts.
  206. //!
  207. //! @return the configured interrupts.
  208. //!
  209. //! Possible values for the return are:
  210. //!
  211. //! AM_HAL_CLKGEN_INT_RTC_ALARM
  212. //! AM_HAL_CLKGEN_INT_XT_FAIL
  213. //! AM_HAL_CLKGEN_INT_AUTOCAL_COMPLETE
  214. //! AM_HAL_CLKGEN_INT AUTOCAL_FAIL
  215. //
  216. //*****************************************************************************
  217. uint32_t
  218. am_hal_clkgen_int_status_get(bool bEnabledOnly)
  219. {
  220. //
  221. // Return the status.
  222. //
  223. if ( bEnabledOnly )
  224. {
  225. uint32_t u32RetVal = AM_REG(CLKGEN, INTSTAT);
  226. u32RetVal &= AM_REG(CLKGEN, INTEN);
  227. return u32RetVal;
  228. }
  229. else
  230. {
  231. return AM_REG(CLKGEN, INTSTAT);
  232. }
  233. }
  234. //*****************************************************************************
  235. //
  236. //! @brief Clears the interrupts.
  237. //!
  238. //! @param ui32IntFlags interrupts to be cleared.
  239. //!
  240. //! This function clears the interrupts.
  241. //!
  242. //! Valid values for ui32IntFlags are:
  243. //!
  244. //! AM_HAL_CLKGEN_INT_RTC_ALARM
  245. //! AM_HAL_CLKGEN_INT_XT_FAIL
  246. //! AM_HAL_CLKGEN_INT_AUTOCAL_COMPLETE
  247. //! AM_HAL_CLKGEN_INT AUTOCAL_FAIL
  248. //!
  249. //! @return None.
  250. //
  251. //*****************************************************************************
  252. void
  253. am_hal_clkgen_int_clear(uint32_t ui32Interrupt)
  254. {
  255. //
  256. // Clear the interrupts.
  257. //
  258. AM_REG(CLKGEN, INTCLR) = ui32Interrupt;
  259. }
  260. //*****************************************************************************
  261. //
  262. //! @brief Starts the desired oscillator(s) (OSC).
  263. //!
  264. //! @param ui32OscFlags oscillator(s) to start.
  265. //!
  266. //! This function starts the desired oscillator(s) (OSC).
  267. //!
  268. //! Valid values for ui32OscFlags are:
  269. //!
  270. //! AM_HAL_CLKGEN_OSC_LFRC
  271. //! AM_HAL_CLKGEN_OSC_XT
  272. //!
  273. //! @return 0 None.
  274. //
  275. //*****************************************************************************
  276. void
  277. am_hal_clkgen_osc_start(uint32_t ui32OscFlags)
  278. {
  279. //
  280. // Start the oscillator(s).
  281. //
  282. AM_REG(CLKGEN, OCTRL) &= ~ui32OscFlags;
  283. }
  284. //*****************************************************************************
  285. //
  286. //! @brief Stops the desired oscillator(s) (OSC).
  287. //!
  288. //! @param ui32OscFlags oscillator(s) to stop.
  289. //!
  290. //! This function stops the desired oscillator(s) (OSC).
  291. //!
  292. //! Valid values for ui32OscFlags are:
  293. //!
  294. //! AM_HAL_CLKGEN_OSC_LFRC
  295. //! AM_HAL_CLKGEN_OSC_XT
  296. //!
  297. //! @return None.
  298. //
  299. //*****************************************************************************
  300. void
  301. am_hal_clkgen_osc_stop(uint32_t ui32OscFlags)
  302. {
  303. //
  304. // Stop the oscillator(s).
  305. //
  306. AM_REG(CLKGEN, OCTRL) |= ui32OscFlags;
  307. }
  308. //*****************************************************************************
  309. //
  310. //! @brief Enables the clock out signal.
  311. //!
  312. //! @param ui32Signal desired location for the clock out signal.
  313. //!
  314. //! This function enables the clock out signal. See am_hal_clkgen.h for
  315. //! available signals.
  316. //!
  317. //! e.g. AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC
  318. //! AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC_DIV4
  319. //! AM_HAL_CLKGEN_CLKOUT_CKSEL_LFRC
  320. //!
  321. //! @return None.
  322. //
  323. //*****************************************************************************
  324. void
  325. am_hal_clkgen_clkout_enable(uint32_t ui32Signal)
  326. {
  327. //
  328. // Enable the clock out on desired signal.
  329. //
  330. AM_REG(CLKGEN, CLKOUT) = AM_REG_CLKGEN_CLKOUT_CKEN_M | ui32Signal;
  331. }
  332. //*****************************************************************************
  333. //
  334. //! @brief Disables the clock out signal.
  335. //!
  336. //! This function disables the clock out signal.
  337. //!
  338. //! @return None.
  339. //
  340. //*****************************************************************************
  341. void
  342. am_hal_clkgen_clkout_disable(void)
  343. {
  344. //
  345. // Disable the clock out.
  346. //
  347. AM_REG(CLKGEN, CLKOUT) = 0;
  348. }
  349. //*****************************************************************************
  350. //
  351. //! @brief Enable UART system clock.
  352. //!
  353. //! This function enables or disables the UART system clock.
  354. //!
  355. //! @param ui32Module is 0 or 1 for Apollo2.
  356. //! @param ui32UartEn is one of the following.
  357. //! AM_HAL_CLKGEN_UARTEN_DIS
  358. //! AM_HAL_CLKGEN_UARTEN_EN
  359. //! AM_HAL_CLKGEN_UARTEN_REDUCE_FREQ
  360. //! AM_HAL_CLKGEN_UARTEN_EN_POWER_SAV
  361. //!
  362. //! @return None.
  363. //
  364. //*****************************************************************************
  365. void
  366. am_hal_clkgen_uarten_set(uint32_t ui32Module, uint32_t ui32UartEn)
  367. {
  368. uint32_t ui32Mask;
  369. if ( (ui32Module >= AM_REG_UART_NUM_MODULES) ||
  370. (ui32UartEn > AM_HAL_CLKGEN_UARTEN_EN_POWER_SAV) )
  371. {
  372. return;
  373. }
  374. ui32UartEn <<= (ui32Module * AM_HAL_CLKGEN_UARTEN_UARTENn_S(ui32Module));
  375. ui32Mask = ~(AM_HAL_CLKGEN_UARTEN_UARTENn_M(ui32Module));
  376. //
  377. // Begin critical section.
  378. //
  379. AM_CRITICAL_BEGIN_ASM
  380. //
  381. // Set the UART clock
  382. //
  383. AM_REG(CLKGEN, UARTEN) &= ui32Mask;
  384. AM_REG(CLKGEN, UARTEN) |= ui32UartEn;
  385. //
  386. // Begin critical section.
  387. //
  388. AM_CRITICAL_END_ASM
  389. }
  390. //*****************************************************************************
  391. //
  392. //! @brief Enables HFRC auto-adjustment at the specified interval.
  393. //!
  394. //! @param ui32Warmup - How long to give the HFRC to stabilize during each
  395. //! calibration attempt.
  396. //! @param ui32Frequency - How often the auto-adjustment should happen.
  397. //!
  398. //! This function enables HFRC auto-adjustment from an external crystal
  399. //! oscillator even when the crystal is not normally being used.
  400. //!
  401. //! ui32Warmup should be one of the following values:
  402. //!
  403. //! AM_REG_CLKGEN_HFADJ_HFWARMUP_1SEC
  404. //! AM_REG_CLKGEN_HFADJ_HFWARMUP_2SEC
  405. //!
  406. //! ui32Frequency should be one of the following values:
  407. //!
  408. //! AM_REG_CLKGEN_HFADJ_HFADJCK_4SEC
  409. //! AM_REG_CLKGEN_HFADJ_HFADJCK_16SEC
  410. //! AM_REG_CLKGEN_HFADJ_HFADJCK_32SEC
  411. //! AM_REG_CLKGEN_HFADJ_HFADJCK_64SEC
  412. //! AM_REG_CLKGEN_HFADJ_HFADJCK_128SEC
  413. //! AM_REG_CLKGEN_HFADJ_HFADJCK_256SEC
  414. //! AM_REG_CLKGEN_HFADJ_HFADJCK_512SEC
  415. //! AM_REG_CLKGEN_HFADJ_HFADJCK_1024SEC
  416. //!
  417. //! @return None.
  418. //
  419. //*****************************************************************************
  420. void
  421. am_hal_clkgen_hfrc_adjust_enable(uint32_t ui32Warmup, uint32_t ui32Frequency)
  422. {
  423. //
  424. // Set the HFRC Auto-adjust register for the user's chosen settings. Assume
  425. // that the HFRC should be calibrated to 48 MHz and that the crystal is
  426. // running at 32.768 kHz.
  427. //
  428. AM_REG(CLKGEN, HFADJ) =
  429. AM_REG_CLKGEN_HFADJ_HFADJ_GAIN_Gain_of_1_in_2 |
  430. ui32Warmup |
  431. AM_REG_CLKGEN_HFADJ_HFXTADJ(AM_REG_CLKGEN_HFADJ_HFXTADJ_DEFAULT) |
  432. ui32Frequency |
  433. AM_REG_CLKGEN_HFADJ_HFADJEN_EN;
  434. }
  435. //*****************************************************************************
  436. //
  437. //! @brief Disables HFRC auto-adjustment.
  438. //!
  439. //! This function disables HFRC auto-adjustment.
  440. //!
  441. //! @return None.
  442. //
  443. //*****************************************************************************
  444. void
  445. am_hal_clkgen_hfrc_adjust_disable(void)
  446. {
  447. //
  448. // Disable the clock out.
  449. //
  450. AM_REG(CLKGEN, HFADJ) =
  451. AM_REG_CLKGEN_HFADJ_HFADJ_GAIN_Gain_of_1_in_2 |
  452. AM_REG_CLKGEN_HFADJ_HFWARMUP_1SEC |
  453. AM_REG_CLKGEN_HFADJ_HFXTADJ(AM_REG_CLKGEN_HFADJ_HFXTADJ_DEFAULT) |
  454. AM_REG_CLKGEN_HFADJ_HFADJCK_4SEC |
  455. AM_REG_CLKGEN_HFADJ_HFADJEN_DIS;
  456. }
  457. //*****************************************************************************
  458. //
  459. // End Doxygen group.
  460. //! @}
  461. //
  462. //*****************************************************************************