am_hal_stimer.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. //*****************************************************************************
  2. //
  3. // am_hal_stimer.c
  4. //! @file
  5. //!
  6. //! @brief Functions for interfacing with the system timer (STIMER).
  7. //!
  8. //! @addtogroup stimer2 System Timer (STIMER)
  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. //! @brief Set up the stimer.
  53. //!
  54. //! @param ui32STimerConfig is the value to load into the configuration reg.
  55. //!
  56. //! This function should be used to perform the initial set-up of the
  57. //! stimer.
  58. //!
  59. //! @return The 32-bit current config of the STimer Config register
  60. //
  61. //*****************************************************************************
  62. uint32_t
  63. am_hal_stimer_config(uint32_t ui32STimerConfig)
  64. {
  65. uint32_t ui32CurrVal;
  66. //
  67. // Read the current config
  68. //
  69. ui32CurrVal = AM_REG(CTIMER, STCFG);
  70. //
  71. // Write our configuration value.
  72. //
  73. AM_REG(CTIMER, STCFG) = ui32STimerConfig;
  74. //
  75. // If all of the clock sources are not HFRC, disable LDO when sleeping if timers are enabled.
  76. //
  77. if ( (AM_BFR(CTIMER, STCFG, CLKSEL) == AM_REG_CTIMER_STCFG_CLKSEL_HFRC_DIV16) ||
  78. (AM_BFR(CTIMER, STCFG, CLKSEL) == AM_REG_CTIMER_STCFG_CLKSEL_HFRC_DIV256) )
  79. {
  80. AM_BFW(PWRCTRL, MISCOPT, DIS_LDOLPMODE_TIMERS, 0);
  81. }
  82. else
  83. {
  84. AM_BFW(PWRCTRL, MISCOPT, DIS_LDOLPMODE_TIMERS, 1);
  85. }
  86. return ui32CurrVal;
  87. }
  88. //*****************************************************************************
  89. //
  90. //! @brief Get the current stimer value.
  91. //!
  92. //! This function can be used to read, uninvasively, the value in the stimer.
  93. //!
  94. //! @return The 32-bit value from the STimer counter register.
  95. //
  96. //*****************************************************************************
  97. uint32_t
  98. am_hal_stimer_counter_get(void)
  99. {
  100. return AM_REG(CTIMER, STTMR);
  101. }
  102. //*****************************************************************************
  103. //
  104. //! @brief Clear the stimer counter.
  105. //!
  106. //! This function clears the STimer Counter and leaves the stimer running.
  107. //!
  108. //! @return None.
  109. //
  110. //*****************************************************************************
  111. void
  112. am_hal_stimer_counter_clear(void)
  113. {
  114. //
  115. // Set the clear bit
  116. //
  117. AM_REG(CTIMER, STCFG) |= AM_REG_CTIMER_STCFG_CLEAR_M;
  118. //
  119. // Reset the clear bit
  120. //
  121. AM_REG(CTIMER, STCFG) &= ~AM_REG_CTIMER_STCFG_CLEAR_M;
  122. }
  123. //*****************************************************************************
  124. //
  125. //! @brief Set the compare value.
  126. //!
  127. //! @param ui32CmprInstance is the compare register instance number (0-7).
  128. //! @param ui32Delta is the value to add to the STimer counter and load into
  129. //! the comparator register. It should be > 1
  130. //!
  131. //! NOTE: There is no way to set an absolute value into a comparator register.
  132. //! Only deltas added to the STimer counter can be written to the compare
  133. //! registers.
  134. //! CAUTION: The HAL implementation requires temporarily disabling the
  135. //! comparison. To avoid the remote possibility of losing an interrupt
  136. //! during that time, delta should always be set to a value greater than 1
  137. //!
  138. //! @return None.
  139. //
  140. //*****************************************************************************
  141. void
  142. am_hal_stimer_compare_delta_set(uint32_t ui32CmprInstance, uint32_t ui32Delta)
  143. {
  144. uint32_t cfgVal;
  145. uint32_t ui32Critical = 0;
  146. if ( ui32CmprInstance > 7 )
  147. {
  148. return;
  149. }
  150. cfgVal = AM_REG(CTIMER, STCFG);
  151. // We need to disable the compare temporarily while setting the delta value
  152. // That leaves a corner case where we could miss the trigger if setting a very
  153. // small delta. To avoid this, we take critical section, and we should ensure
  154. // that delta value is at least > 1
  155. // Disable the compare if already enabled, when setting the new value
  156. AM_REG(CTIMER, STCFG) &= ~((AM_HAL_STIMER_CFG_COMPARE_A_ENABLE << ui32CmprInstance));
  157. //
  158. // Start a critical section.
  159. //
  160. ui32Critical = am_hal_interrupt_master_disable();
  161. AM_REGVAL(AM_REG_STIMER_COMPARE(0, ui32CmprInstance)) = ui32Delta;
  162. // Restore Compare Enable bit
  163. AM_REG(CTIMER, STCFG) |= cfgVal & (AM_HAL_STIMER_CFG_COMPARE_A_ENABLE << ui32CmprInstance);
  164. //
  165. // End the critical section.
  166. //
  167. am_hal_interrupt_master_set(ui32Critical);
  168. }
  169. //*****************************************************************************
  170. //
  171. //! @brief Get the current stimer compare register value.
  172. //!
  173. //! @param ui32CmprInstance is the compare register instance number (0-7).
  174. //!
  175. //! This function can be used to read the value in an stimer compare register.
  176. //!
  177. //!
  178. //! @return None.
  179. //
  180. //*****************************************************************************
  181. uint32_t
  182. am_hal_stimer_compare_get(uint32_t ui32CmprInstance)
  183. {
  184. if ( ui32CmprInstance > 7 )
  185. {
  186. return 0;
  187. }
  188. return AM_REGVAL(AM_REG_STIMER_COMPARE(0, ui32CmprInstance));
  189. }
  190. //*****************************************************************************
  191. //
  192. //! @brief Start capturing data with the specified capture register.
  193. //!
  194. //! @param ui32CaptureNum is the Capture Register Number to read (0-3).
  195. //! ui32GPIONumber is the pin number.
  196. //! bPolarity: false (0) = Capture on low to high transition.
  197. //! true (1) = Capture on high to low transition.
  198. //!
  199. //! Use this function to start capturing.
  200. //!
  201. //! @return None.
  202. //
  203. //*****************************************************************************
  204. void
  205. am_hal_stimer_capture_start(uint32_t ui32CaptureNum,
  206. uint32_t ui32GPIONumber,
  207. bool bPolarity)
  208. {
  209. uint32_t ui32CapCtrl;
  210. if ( ui32GPIONumber > (AM_HAL_GPIO_MAX_PADS-1) )
  211. {
  212. return;
  213. }
  214. //
  215. // Set the polarity and pin selection in the GPIO block.
  216. //
  217. switch (ui32CaptureNum)
  218. {
  219. case 0:
  220. AM_BFW(GPIO, STMRCAP, STPOL0, bPolarity);
  221. AM_BFW(GPIO, STMRCAP, STSEL0, ui32GPIONumber);
  222. ui32CapCtrl = AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_A_M;
  223. break;
  224. case 1:
  225. AM_BFW(GPIO, STMRCAP, STPOL1, bPolarity);
  226. AM_BFW(GPIO, STMRCAP, STSEL1, ui32GPIONumber);
  227. ui32CapCtrl = AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_B_M;
  228. break;
  229. case 2:
  230. AM_BFW(GPIO, STMRCAP, STPOL2, bPolarity);
  231. AM_BFW(GPIO, STMRCAP, STSEL2, ui32GPIONumber);
  232. ui32CapCtrl = AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_C_M;
  233. break;
  234. case 3:
  235. AM_BFW(GPIO, STMRCAP, STPOL3, bPolarity);
  236. AM_BFW(GPIO, STMRCAP, STSEL3, ui32GPIONumber);
  237. ui32CapCtrl = AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_D_M;
  238. break;
  239. default:
  240. return; // error concealment.
  241. }
  242. //
  243. // Enable it in the CTIMER Block
  244. //
  245. AM_REG(CTIMER, CAPTURE_CONTROL) |= ui32CapCtrl;
  246. }
  247. //*****************************************************************************
  248. //
  249. //! @brief Start capturing data with the specified capture register.
  250. //!
  251. //! @param ui32CaptureNum is the Capture Register Number to read.
  252. //!
  253. //! Use this function to start capturing.
  254. //!
  255. //! @return None.
  256. //
  257. //*****************************************************************************
  258. void am_hal_stimer_capture_stop(uint32_t ui32CaptureNum)
  259. {
  260. //
  261. // Disable it in the CTIMER block.
  262. //
  263. AM_REG(CTIMER, CAPTURE_CONTROL) &=
  264. ~(AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_A_M <<
  265. ((AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_B_S -
  266. AM_REG_CTIMER_CAPTURE_CONTROL_CAPTURE_A_S) * ui32CaptureNum));
  267. }
  268. //*****************************************************************************
  269. //
  270. //! @brief Get the current stimer capture register value.
  271. //!
  272. //! @param ui32CaptureNum is the Capture Register Number to read.
  273. //!
  274. //! This function can be used to read the value in an stimer capture register.
  275. //!
  276. //!
  277. //! @return None.
  278. //
  279. //*****************************************************************************
  280. uint32_t am_hal_stimer_capture_get(uint32_t ui32CaptureNum)
  281. {
  282. if ( ui32CaptureNum > 7 )
  283. {
  284. return 0;
  285. }
  286. return AM_REGVAL(AM_REG_STIMER_CAPTURE(0, ui32CaptureNum));
  287. }
  288. //*****************************************************************************
  289. //
  290. //! @brief Enables the selected system timer interrupt.
  291. //!
  292. //! @param ui32Interrupt is the interrupt to be used.
  293. //!
  294. //! This function will enable the selected interrupts in the STIMER interrupt
  295. //! enable register. In order to receive an interrupt from an stimer component,
  296. //! you will need to enable the interrupt for that component in this main
  297. //! register, as well as in the stimer configuration register (accessible though
  298. //! am_hal_stimer_config()), and in the NVIC.
  299. //!
  300. //! ui32Interrupt should be the logical OR of one or more of the following
  301. //! values:
  302. //!
  303. //! AM_HAL_STIMER_INT_COMPAREA
  304. //! AM_HAL_STIMER_INT_COMPAREB
  305. //! AM_HAL_STIMER_INT_COMPAREC
  306. //! AM_HAL_STIMER_INT_COMPARED
  307. //! AM_HAL_STIMER_INT_COMPAREE
  308. //! AM_HAL_STIMER_INT_COMPAREF
  309. //! AM_HAL_STIMER_INT_COMPAREG
  310. //! AM_HAL_STIMER_INT_COMPAREH
  311. //!
  312. //! AM_HAL_STIMER_INT_OVERFLOW
  313. //!
  314. //! AM_HAL_STIMER_INT_CAPTUREA
  315. //! AM_HAL_STIMER_INT_CAPTUREB
  316. //! AM_HAL_STIMER_INT_CAPTUREC
  317. //! AM_HAL_STIMER_INT_CAPTURED
  318. //!
  319. //! @return None.
  320. //
  321. //*****************************************************************************
  322. void
  323. am_hal_stimer_int_enable(uint32_t ui32Interrupt)
  324. {
  325. //
  326. // Enable the interrupt at the module level.
  327. //
  328. AM_REGn(CTIMER, 0, STMINTEN) |= ui32Interrupt;
  329. }
  330. //*****************************************************************************
  331. //
  332. //! @brief Return the enabled stimer interrupts.
  333. //!
  334. //! This function will return all enabled interrupts in the STIMER
  335. //! interrupt enable register.
  336. //!
  337. //! @return return enabled interrupts. This will be a logical or of:
  338. //!
  339. //! AM_HAL_STIMER_INT_COMPAREA
  340. //! AM_HAL_STIMER_INT_COMPAREB
  341. //! AM_HAL_STIMER_INT_COMPAREC
  342. //! AM_HAL_STIMER_INT_COMPARED
  343. //! AM_HAL_STIMER_INT_COMPAREE
  344. //! AM_HAL_STIMER_INT_COMPAREF
  345. //! AM_HAL_STIMER_INT_COMPAREG
  346. //! AM_HAL_STIMER_INT_COMPAREH
  347. //!
  348. //! AM_HAL_STIMER_INT_OVERFLOW
  349. //!
  350. //! AM_HAL_STIMER_INT_CAPTUREA
  351. //! AM_HAL_STIMER_INT_CAPTUREB
  352. //! AM_HAL_STIMER_INT_CAPTUREC
  353. //! AM_HAL_STIMER_INT_CAPTURED
  354. //!
  355. //! @return Return the enabled timer interrupts.
  356. //
  357. //*****************************************************************************
  358. uint32_t
  359. am_hal_stimer_int_enable_get(void)
  360. {
  361. //
  362. // Return enabled interrupts.
  363. //
  364. return AM_REGn(CTIMER, 0, STMINTEN);
  365. }
  366. //*****************************************************************************
  367. //
  368. //! @brief Disables the selected stimer interrupt.
  369. //!
  370. //! @param ui32Interrupt is the interrupt to be used.
  371. //!
  372. //! This function will disable the selected interrupts in the STIMER
  373. //! interrupt register.
  374. //!
  375. //! ui32Interrupt should be the logical OR of one or more of the following
  376. //! values:
  377. //!
  378. //! AM_HAL_STIMER_INT_COMPAREA
  379. //! AM_HAL_STIMER_INT_COMPAREB
  380. //! AM_HAL_STIMER_INT_COMPAREC
  381. //! AM_HAL_STIMER_INT_COMPARED
  382. //! AM_HAL_STIMER_INT_COMPAREE
  383. //! AM_HAL_STIMER_INT_COMPAREF
  384. //! AM_HAL_STIMER_INT_COMPAREG
  385. //! AM_HAL_STIMER_INT_COMPAREH
  386. //!
  387. //! AM_HAL_STIMER_INT_OVERFLOW
  388. //!
  389. //! AM_HAL_STIMER_INT_CAPTUREA
  390. //! AM_HAL_STIMER_INT_CAPTUREB
  391. //! AM_HAL_STIMER_INT_CAPTUREC
  392. //! AM_HAL_STIMER_INT_CAPTURED
  393. //!
  394. //! @return None.
  395. //
  396. //*****************************************************************************
  397. void
  398. am_hal_stimer_int_disable(uint32_t ui32Interrupt)
  399. {
  400. //
  401. // Disable the interrupt at the module level.
  402. //
  403. AM_REGn(CTIMER, 0, STMINTEN) &= ~ui32Interrupt;
  404. }
  405. //*****************************************************************************
  406. //
  407. //! @brief Sets the selected stimer interrupt.
  408. //!
  409. //! @param ui32Interrupt is the interrupt to be used.
  410. //!
  411. //! This function will set the selected interrupts in the STIMER
  412. //! interrupt register.
  413. //!
  414. //! ui32Interrupt should be the logical OR of one or more of the following
  415. //! values:
  416. //!
  417. //! AM_HAL_STIMER_INT_COMPAREA
  418. //! AM_HAL_STIMER_INT_COMPAREB
  419. //! AM_HAL_STIMER_INT_COMPAREC
  420. //! AM_HAL_STIMER_INT_COMPARED
  421. //! AM_HAL_STIMER_INT_COMPAREE
  422. //! AM_HAL_STIMER_INT_COMPAREF
  423. //! AM_HAL_STIMER_INT_COMPAREG
  424. //! AM_HAL_STIMER_INT_COMPAREH
  425. //!
  426. //! AM_HAL_STIMER_INT_OVERFLOW
  427. //!
  428. //! AM_HAL_STIMER_INT_CAPTUREA
  429. //! AM_HAL_STIMER_INT_CAPTUREB
  430. //! AM_HAL_STIMER_INT_CAPTUREC
  431. //! AM_HAL_STIMER_INT_CAPTURED
  432. //!
  433. //! @return None.
  434. //
  435. //*****************************************************************************
  436. void
  437. am_hal_stimer_int_set(uint32_t ui32Interrupt)
  438. {
  439. //
  440. // Set the interrupts.
  441. //
  442. AM_REGn(CTIMER, 0, STMINTSET) = ui32Interrupt;
  443. }
  444. //*****************************************************************************
  445. //
  446. //! @brief Clears the selected stimer interrupt.
  447. //!
  448. //! @param ui32Interrupt is the interrupt to be used.
  449. //!
  450. //! This function will clear the selected interrupts in the STIMER
  451. //! interrupt register.
  452. //!
  453. //! ui32Interrupt should be the logical OR of one or more of the following
  454. //! values:
  455. //!
  456. //! AM_HAL_STIMER_INT_COMPAREA
  457. //! AM_HAL_STIMER_INT_COMPAREB
  458. //! AM_HAL_STIMER_INT_COMPAREC
  459. //! AM_HAL_STIMER_INT_COMPARED
  460. //! AM_HAL_STIMER_INT_COMPAREE
  461. //! AM_HAL_STIMER_INT_COMPAREF
  462. //! AM_HAL_STIMER_INT_COMPAREG
  463. //! AM_HAL_STIMER_INT_COMPAREH
  464. //!
  465. //! AM_HAL_STIMER_INT_OVERFLOW
  466. //!
  467. //! AM_HAL_STIMER_INT_CAPTUREA
  468. //! AM_HAL_STIMER_INT_CAPTUREB
  469. //! AM_HAL_STIMER_INT_CAPTUREC
  470. //! AM_HAL_STIMER_INT_CAPTURED
  471. //!
  472. //! @return None.
  473. //
  474. //*****************************************************************************
  475. void
  476. am_hal_stimer_int_clear(uint32_t ui32Interrupt)
  477. {
  478. //
  479. // Disable the interrupt at the module level.
  480. //
  481. AM_REGn(CTIMER, 0, STMINTCLR) = ui32Interrupt;
  482. }
  483. //*****************************************************************************
  484. //
  485. //! @brief Returns either the enabled or raw stimer interrupt status.
  486. //!
  487. //! This function will return the stimer interrupt status.
  488. //!
  489. //! @bEnabledOnly if true returns the status of the enabled interrupts
  490. //! only.
  491. //!
  492. //! The return value will be the logical OR of one or more of the following
  493. //! values:
  494. //!
  495. //!
  496. //! @return Returns the stimer interrupt status.
  497. //
  498. //*****************************************************************************
  499. uint32_t
  500. am_hal_stimer_int_status_get(bool bEnabledOnly)
  501. {
  502. //
  503. // Return the desired status.
  504. //
  505. uint32_t ui32RetVal = AM_REGn(CTIMER, 0, STMINTSTAT);
  506. if ( bEnabledOnly )
  507. {
  508. ui32RetVal &= AM_REGn(CTIMER, 0, STMINTEN);
  509. }
  510. return ui32RetVal;
  511. }
  512. //*****************************************************************************
  513. //
  514. // End Doxygen group.
  515. //! @}
  516. //
  517. //*****************************************************************************