am_hal_clkgen.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  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.11 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 None.
  274. //
  275. //*****************************************************************************
  276. void
  277. am_hal_clkgen_osc_start(uint32_t ui32OscFlags)
  278. {
  279. if ( ui32OscFlags & (AM_HAL_CLKGEN_OSC_LFRC | AM_HAL_CLKGEN_OSC_XT) )
  280. {
  281. //
  282. // Start the oscillator(s).
  283. // Note that these bits are cleared in order to enable the oscillator.
  284. //
  285. AM_REG(CLKGEN, OCTRL) &= ~ui32OscFlags;
  286. }
  287. }
  288. //*****************************************************************************
  289. //
  290. //! @brief Stops the desired oscillator(s) (OSC).
  291. //!
  292. //! @param ui32OscFlags oscillator(s) to stop.
  293. //!
  294. //! This function stops the desired oscillator(s) (OSC).
  295. //!
  296. //! Valid values for ui32OscFlags are:
  297. //!
  298. //! AM_HAL_CLKGEN_OSC_LFRC
  299. //! AM_HAL_CLKGEN_OSC_XT
  300. //!
  301. //! @return None.
  302. //
  303. //*****************************************************************************
  304. void
  305. am_hal_clkgen_osc_stop(uint32_t ui32OscFlags)
  306. {
  307. if ( ui32OscFlags & (AM_HAL_CLKGEN_OSC_LFRC | AM_HAL_CLKGEN_OSC_XT) )
  308. {
  309. //
  310. // Stop the oscillator(s).
  311. // Note that these bits are set in order to stop the oscillator.
  312. //
  313. AM_REG(CLKGEN, OCTRL) |= ui32OscFlags;
  314. }
  315. }
  316. //*****************************************************************************
  317. //
  318. //! @brief Enables the clock out signal.
  319. //!
  320. //! @param ui32Signal desired location for the clock out signal.
  321. //!
  322. //! This function enables the clock out signal. See am_hal_clkgen.h for
  323. //! available signals.
  324. //!
  325. //! e.g. AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC
  326. //! AM_HAL_CLKGEN_CLKOUT_CKSEL_HFRC_DIV4
  327. //! AM_HAL_CLKGEN_CLKOUT_CKSEL_LFRC
  328. //!
  329. //! @return None.
  330. //
  331. //*****************************************************************************
  332. void
  333. am_hal_clkgen_clkout_enable(uint32_t ui32Signal)
  334. {
  335. //
  336. // Enable the clock out on desired signal.
  337. //
  338. AM_REG(CLKGEN, CLKOUT) = AM_REG_CLKGEN_CLKOUT_CKEN_M | ui32Signal;
  339. }
  340. //*****************************************************************************
  341. //
  342. //! @brief Disables the clock out signal.
  343. //!
  344. //! This function disables the clock out signal.
  345. //!
  346. //! @return None.
  347. //
  348. //*****************************************************************************
  349. void
  350. am_hal_clkgen_clkout_disable(void)
  351. {
  352. //
  353. // Disable the clock out.
  354. //
  355. AM_REG(CLKGEN, CLKOUT) = 0;
  356. }
  357. //*****************************************************************************
  358. //
  359. //! @brief Enable UART system clock.
  360. //!
  361. //! This function enables or disables the UART system clock.
  362. //!
  363. //! @param ui32Module is 0 or 1 for Apollo2.
  364. //! @param ui32UartEn is one of the following.
  365. //! AM_HAL_CLKGEN_UARTEN_DIS
  366. //! AM_HAL_CLKGEN_UARTEN_EN
  367. //! AM_HAL_CLKGEN_UARTEN_REDUCE_FREQ
  368. //! AM_HAL_CLKGEN_UARTEN_EN_POWER_SAV
  369. //!
  370. //! @return None.
  371. //
  372. //*****************************************************************************
  373. void
  374. am_hal_clkgen_uarten_set(uint32_t ui32Module, uint32_t ui32UartEn)
  375. {
  376. uint32_t ui32Mask;
  377. if ( (ui32Module >= AM_REG_UART_NUM_MODULES) ||
  378. (ui32UartEn > AM_HAL_CLKGEN_UARTEN_EN_POWER_SAV) )
  379. {
  380. return;
  381. }
  382. ui32UartEn <<= (ui32Module * AM_HAL_CLKGEN_UARTEN_UARTENn_S(ui32Module));
  383. ui32Mask = ~(AM_HAL_CLKGEN_UARTEN_UARTENn_M(ui32Module));
  384. //
  385. // Begin critical section.
  386. //
  387. AM_CRITICAL_BEGIN_ASM
  388. //
  389. // Set the UART clock
  390. //
  391. AM_REG(CLKGEN, UARTEN) &= ui32Mask;
  392. AM_REG(CLKGEN, UARTEN) |= ui32UartEn;
  393. //
  394. // Begin critical section.
  395. //
  396. AM_CRITICAL_END_ASM
  397. }
  398. //*****************************************************************************
  399. //
  400. //! @brief Enables HFRC auto-adjustment at the specified interval.
  401. //!
  402. //! @param ui32Warmup - How long to give the HFRC to stabilize during each
  403. //! calibration attempt.
  404. //! @param ui32Frequency - How often the auto-adjustment should happen.
  405. //!
  406. //! This function enables HFRC auto-adjustment from an external crystal
  407. //! oscillator even when the crystal is not normally being used.
  408. //!
  409. //! ui32Warmup should be one of the following values:
  410. //!
  411. //! AM_REG_CLKGEN_HFADJ_HFWARMUP_1SEC
  412. //! AM_REG_CLKGEN_HFADJ_HFWARMUP_2SEC
  413. //!
  414. //! ui32Frequency should be one of the following values:
  415. //!
  416. //! AM_REG_CLKGEN_HFADJ_HFADJCK_4SEC
  417. //! AM_REG_CLKGEN_HFADJ_HFADJCK_16SEC
  418. //! AM_REG_CLKGEN_HFADJ_HFADJCK_32SEC
  419. //! AM_REG_CLKGEN_HFADJ_HFADJCK_64SEC
  420. //! AM_REG_CLKGEN_HFADJ_HFADJCK_128SEC
  421. //! AM_REG_CLKGEN_HFADJ_HFADJCK_256SEC
  422. //! AM_REG_CLKGEN_HFADJ_HFADJCK_512SEC
  423. //! AM_REG_CLKGEN_HFADJ_HFADJCK_1024SEC
  424. //!
  425. //! @return None.
  426. //
  427. //*****************************************************************************
  428. void
  429. am_hal_clkgen_hfrc_adjust_enable(uint32_t ui32Warmup, uint32_t ui32Frequency)
  430. {
  431. //
  432. // Set the HFRC Auto-adjust register for the user's chosen settings. Assume
  433. // that the HFRC should be calibrated to 48 MHz and that the crystal is
  434. // running at 32.768 kHz.
  435. //
  436. AM_REG(CLKGEN, HFADJ) =
  437. AM_REG_CLKGEN_HFADJ_HFADJ_GAIN_Gain_of_1_in_2 |
  438. ui32Warmup |
  439. AM_REG_CLKGEN_HFADJ_HFXTADJ(AM_REG_CLKGEN_HFADJ_HFXTADJ_DEFAULT) |
  440. ui32Frequency |
  441. AM_REG_CLKGEN_HFADJ_HFADJEN_EN;
  442. }
  443. //*****************************************************************************
  444. //
  445. //! @brief Disables HFRC auto-adjustment.
  446. //!
  447. //! This function disables HFRC auto-adjustment.
  448. //!
  449. //! @return None.
  450. //
  451. //*****************************************************************************
  452. void
  453. am_hal_clkgen_hfrc_adjust_disable(void)
  454. {
  455. //
  456. // Disable the clock out.
  457. //
  458. AM_REG(CLKGEN, HFADJ) =
  459. AM_REG_CLKGEN_HFADJ_HFADJ_GAIN_Gain_of_1_in_2 |
  460. AM_REG_CLKGEN_HFADJ_HFWARMUP_1SEC |
  461. AM_REG_CLKGEN_HFADJ_HFXTADJ(AM_REG_CLKGEN_HFADJ_HFXTADJ_DEFAULT) |
  462. AM_REG_CLKGEN_HFADJ_HFADJCK_4SEC |
  463. AM_REG_CLKGEN_HFADJ_HFADJEN_DIS;
  464. }
  465. //*****************************************************************************
  466. //
  467. // End Doxygen group.
  468. //! @}
  469. //
  470. //*****************************************************************************