am_hal_ctimer.c 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687
  1. //*****************************************************************************
  2. //
  3. // am_hal_ctimer.c
  4. //! @file
  5. //!
  6. //! @brief Functions for interfacing with the Counter/Timer module.
  7. //!
  8. //! @addtogroup ctimer2 Counter/Timer (CTIMER)
  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. // Address space distance between timer configuration registers.
  53. //
  54. //*****************************************************************************
  55. #define MAX_CTIMERS 4
  56. #define TIMER_OFFSET (AM_REG_CTIMER_TMR1_O - AM_REG_CTIMER_TMR0_O)
  57. #define CTIMER_CMPR_OFFSET (AM_REG_CTIMER_CMPRB0_O - AM_REG_CTIMER_CMPRA0_O)
  58. //*****************************************************************************
  59. //
  60. // Adjacency check
  61. //
  62. // This is related to the timer read workaround. This macro checks to see if
  63. // the two supplied count values are within one "tick" of eachother. It should
  64. // still pass in the event of a timer rollover.
  65. //
  66. //*****************************************************************************
  67. #define adjacent(A, B) (((A) == (B)) || (((A) + 1) == (B)) || ((B) == 0))
  68. //*****************************************************************************
  69. //
  70. // Array of function pointers for handling CTimer interrupts.
  71. //
  72. //*****************************************************************************
  73. am_hal_ctimer_handler_t am_hal_ctimer_ppfnHandlers[16];
  74. //*****************************************************************************
  75. //
  76. // Static function for reading the timer value.
  77. //
  78. //*****************************************************************************
  79. #if defined(__GNUC_STDC_INLINE__)
  80. __attribute__((naked))
  81. static
  82. void
  83. back2back_reads(uint32_t u32TimerAddr, uint32_t u32Data[])
  84. {
  85. // u32TimerAddr = address of the timer to be read.
  86. // u32Data[] is a pointer to a 3 word data array provided by the caller.
  87. __asm
  88. (
  89. // Do 3 back-to-back reads of the register
  90. " push {r4}\n" // Save r4
  91. " push {r1}\n" // Save the data array ptr for later
  92. " mov r2, r0\n" // Get Timer Addr
  93. " mrs r4, PRIMASK\n" // Save PRIMASK
  94. " cpsid i\n" // __disable_irq()
  95. " nop\n" // Give the disable a cycle to take affect (but almost certainly not really needed)
  96. " ldr r0, [r2, #0]\n" // Get TMRn register value
  97. " ldr r1, [r2, #0]\n" // Get TMRn register value again
  98. " ldr r3, [r2, #0]\n" // Get TMRn register value for a third time
  99. " msr PRIMASK, r4\n" // Restore PRIMASK
  100. " pop {r2}\n" // Get the array ptr
  101. " str r0, [r2, #0]\n" // Store register value to variable
  102. " str r1, [r2, #4]\n" // Store register value to variable
  103. " str r3, [r2, #8]\n" // Store register value to variable
  104. " pop {r4}\n" // restore r4
  105. " bx lr\n"
  106. );
  107. }
  108. #elif defined(__ARMCC_VERSION)
  109. __asm static uint32_t
  110. back2back_reads( uint32_t u32TimerAddr, uint32_t u32Data[])
  111. {
  112. push {r4} // Save r4
  113. push {r1} // Save the data array ptr for later
  114. mov r2, r0 // Get Timer Addr
  115. mrs r4, PRIMASK // Save PRIMASK
  116. cpsid i // __disable_irq()
  117. nop // Give the disable a cycle to take affect (but almost certainly not really needed)
  118. ldr r0, [r2, #0] // Get TMRn register value
  119. ldr r1, [r2, #0] // Get TMRn register value again
  120. ldr r3, [r2, #0] // Get TMRn register value for a third time
  121. msr PRIMASK, r4 // Restore PRIMASK
  122. pop {r2} // Get the array ptr
  123. str r0, [r2, #0] // Store register value to variable
  124. str r1, [r2, #4] // Store register value to variable
  125. str r3, [r2, #8] // Store register value to variable
  126. pop {r4} // Restore r4
  127. bx lr
  128. }
  129. #elif defined(__IAR_SYSTEMS_ICC__)
  130. #pragma diag_suppress = Pe940 // Suppress IAR compiler warning about missing
  131. // return statement on a non-void function
  132. __stackless static uint32_t
  133. back2back_reads( uint32_t u32TimerAddr, uint32_t u32Data[])
  134. {
  135. __asm(" push {r4}"); // Save r4
  136. __asm(" push {r1}"); // Save the data array ptr for later
  137. __asm(" mov r2, r0"); // Get Timer Addr
  138. __asm(" mrs r4, PRIMASK"); // Save PRIMASK"
  139. __asm(" cpsid i"); // __disable_irq()
  140. __asm(" nop"); // Give the disable a cycle to take affect (but almost certainly not really needed)
  141. __asm(" ldr r0, [r2, #0]"); // Get TMRn register value
  142. __asm(" ldr r1, [r2, #0]"); // Get TMRn register value again
  143. __asm(" ldr r3, [r2, #0]"); // Get TMRn register value for a third time
  144. __asm(" msr PRIMASK, r4"); // Restore PRIMASK
  145. __asm(" pop {r2}"); // Get the array ptr
  146. __asm(" str r0, [r2, #0]"); // Store register value to variable
  147. __asm(" str r1, [r2, #4]"); // Store register value to variable
  148. __asm(" str r3, [r2, #8]"); // Store register value to variable
  149. __asm(" pop {r4}"); // Restore r4
  150. __asm(" bx lr");
  151. }
  152. #pragma diag_default = Pe940 // Restore IAR compiler warning
  153. #endif
  154. //*****************************************************************************
  155. //
  156. // @brief Check to see if the given CTimer is using the HFRC
  157. //
  158. // Note - Calls to this function should be from inside a critical section.
  159. //
  160. //! @return None.
  161. //
  162. //*****************************************************************************
  163. static bool
  164. ctimer_source_hfrc(uint32_t ui32CtimerNum)
  165. {
  166. uint32_t *pui32ConfigReg;
  167. uint32_t ui32TimerASrc, ui32TimerBSrc;
  168. //
  169. // Find the correct register to write.
  170. //
  171. pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
  172. (ui32CtimerNum * TIMER_OFFSET));
  173. //
  174. // Determine if this timer is using HFRC as the clock source.
  175. // The value we are looking for is HFRC_DIV4 to HFRC_DIV4K.
  176. // Get the clock sources and 0-base the extracted value.
  177. //
  178. ui32TimerASrc = AM_BFX(CTIMER, CTRL0, TMRA0CLK, *pui32ConfigReg) -
  179. AM_ENUMX(CTIMER, CTRL0, TMRA0CLK, HFRC_DIV4);
  180. ui32TimerBSrc = AM_BFX(CTIMER, CTRL0, TMRB0CLK, *pui32ConfigReg) -
  181. AM_ENUMX(CTIMER, CTRL0, TMRB0CLK, HFRC_DIV4);
  182. //
  183. // If the source value is 0 to (HFRC_DIV4K - HFRC_DIV4), then it's HFRC.
  184. //
  185. if ( (ui32TimerASrc <= (AM_ENUMX(CTIMER, CTRL0, TMRA0CLK, HFRC_DIV4K) -
  186. AM_ENUMX(CTIMER, CTRL0, TMRA0CLK, HFRC_DIV4))) ||
  187. (ui32TimerBSrc <= (AM_ENUMX(CTIMER, CTRL0, TMRB0CLK, HFRC_DIV4K) -
  188. AM_ENUMX(CTIMER, CTRL0, TMRB0CLK, HFRC_DIV4))) )
  189. {
  190. return true;
  191. }
  192. else
  193. {
  194. return false;
  195. }
  196. } // ctimer_source_hfrc()
  197. //*****************************************************************************
  198. //
  199. // @brief Check to see if any of the CTimers or STimer are using the HFRC.
  200. //
  201. // This function should be used to check if the HFRC is being used in order
  202. // to correctly establish power related settings.
  203. //
  204. // Note - Calls to this function should be from inside a critical section.
  205. //
  206. //! @return None.
  207. //
  208. //*****************************************************************************
  209. static bool
  210. timers_use_hfrc(void)
  211. {
  212. uint32_t ui32TimerASrc, ui32CtimerNum;
  213. //
  214. // Check STimer to see if it is using HFRC.
  215. //
  216. ui32TimerASrc = AM_BFR(CTIMER, STCFG, CLKSEL);
  217. if ( (ui32TimerASrc == AM_REG_CTIMER_STCFG_CLKSEL_HFRC_DIV16) ||
  218. (ui32TimerASrc == AM_REG_CTIMER_STCFG_CLKSEL_HFRC_DIV256) )
  219. {
  220. return true;
  221. }
  222. //
  223. // Check the CTimers to see if any are using HFRC as their clock source.
  224. //
  225. for ( ui32CtimerNum = 0; ui32CtimerNum < MAX_CTIMERS; ui32CtimerNum++ )
  226. {
  227. if ( ctimer_source_hfrc(ui32CtimerNum) )
  228. {
  229. return true;
  230. }
  231. }
  232. return false;
  233. } // timers_use_hfrc()
  234. //*****************************************************************************
  235. //
  236. //! @brief Convenience function for responding to CTimer interrupts.
  237. //!
  238. //! @param ui32Status is the interrupt status as returned by
  239. //! am_hal_ctimer_int_status_get()
  240. //!
  241. //! This function may be called from am_ctimer_isr() to read the status of
  242. //! the CTimer interrupts, determine which source caused the most recent
  243. //! interrupt, and call an interrupt handler function to respond. The interrupt
  244. //! handler to be called must be first registered with the
  245. //! am_hal_ctimer_int_register() function.
  246. //!
  247. //! In the event that multiple sources are active, the corresponding
  248. //! interrupt handlers will be called in numerical order based on interrupt def.
  249. //!
  250. //! @return None.
  251. //
  252. //*****************************************************************************
  253. void
  254. am_hal_ctimer_int_service(uint32_t ui32Status)
  255. {
  256. uint32_t ui32Clz;
  257. am_hal_ctimer_handler_t pfnHandler;
  258. ui32Status &= 0xFFFF;
  259. while ( ui32Status )
  260. {
  261. //
  262. // Pick one of any remaining active interrupt bits
  263. //
  264. #ifdef __IAR_SYSTEMS_ICC__
  265. ui32Clz = __CLZ(ui32Status);
  266. #else
  267. ui32Clz = __builtin_clz(ui32Status);
  268. #endif
  269. //
  270. // Turn off the bit we picked in the working copy
  271. //
  272. ui32Status &= ~(0x80000000 >> ui32Clz);
  273. //
  274. // Check the bit handler table to see if there is an interrupt handler
  275. // registered for this particular bit.
  276. //
  277. pfnHandler = am_hal_ctimer_ppfnHandlers[31 - ui32Clz];
  278. if ( pfnHandler )
  279. {
  280. //
  281. // If we found an interrupt handler routine, call it now.
  282. //
  283. pfnHandler();
  284. }
  285. }
  286. } // am_hal_ctimer_int_service()
  287. //*****************************************************************************
  288. //
  289. //! @brief Register an interrupt handler for CTimer.
  290. //!
  291. //! @param ui32Interrupt - interrupt number to assign this interrupt handler to.
  292. //! @param pfnHandler - Function to call when this interrupt is received.
  293. //!
  294. //! This function allows the caller to specify a function that should be called
  295. //! any time a Ctimer interrupt is received. Registering an
  296. //! interrupt handler using this function adds the function pointer to an array
  297. //! in SRAM. This interrupt handler will be called by am_hal_ctimer_int_service()
  298. //! whenever the ui32Status parameter indicates that the corresponding interrupt.
  299. //!
  300. //! To remove an interrupt handler that has already been registered, the
  301. //! pfnHandler parameter may be set to zero.
  302. //!
  303. //! @note This function will not have any effect unless the
  304. //! am_hal_ctimer_int_service() function is being used.
  305. //!
  306. //! @return None.
  307. //
  308. //*****************************************************************************
  309. void
  310. am_hal_ctimer_int_register(uint32_t ui32Interrupt,
  311. am_hal_ctimer_handler_t pfnHandler)
  312. {
  313. uint32_t intIdx = 0;
  314. //
  315. // Check to make sure the interrupt number is valid. (Debug builds only)
  316. //
  317. switch (ui32Interrupt)
  318. {
  319. case AM_REG_CTIMER_INTEN_CTMRA0C0INT_M:
  320. intIdx = AM_REG_CTIMER_INTEN_CTMRA0C0INT_S;
  321. break;
  322. case AM_REG_CTIMER_INTEN_CTMRB0C0INT_M:
  323. intIdx = AM_REG_CTIMER_INTEN_CTMRB0C0INT_S;
  324. break;
  325. case AM_REG_CTIMER_INTEN_CTMRA1C0INT_M:
  326. intIdx = AM_REG_CTIMER_INTEN_CTMRA1C0INT_S;
  327. break;
  328. case AM_REG_CTIMER_INTEN_CTMRB1C0INT_M:
  329. intIdx = AM_REG_CTIMER_INTEN_CTMRB1C0INT_S;
  330. break;
  331. case AM_REG_CTIMER_INTEN_CTMRA2C0INT_M:
  332. intIdx = AM_REG_CTIMER_INTEN_CTMRA2C0INT_S;
  333. break;
  334. case AM_REG_CTIMER_INTEN_CTMRB2C0INT_M:
  335. intIdx = AM_REG_CTIMER_INTEN_CTMRB2C0INT_S;
  336. break;
  337. case AM_REG_CTIMER_INTEN_CTMRA3C0INT_M:
  338. intIdx = AM_REG_CTIMER_INTEN_CTMRA3C0INT_S;
  339. break;
  340. case AM_REG_CTIMER_INTEN_CTMRB3C0INT_M:
  341. intIdx = AM_REG_CTIMER_INTEN_CTMRB3C0INT_S;
  342. break;
  343. case AM_REG_CTIMER_INTEN_CTMRA0C1INT_M:
  344. intIdx = AM_REG_CTIMER_INTEN_CTMRA0C1INT_S;
  345. break;
  346. case AM_REG_CTIMER_INTEN_CTMRB0C1INT_M:
  347. intIdx = AM_REG_CTIMER_INTEN_CTMRB0C1INT_S;
  348. break;
  349. case AM_REG_CTIMER_INTEN_CTMRA1C1INT_M:
  350. intIdx = AM_REG_CTIMER_INTEN_CTMRA1C1INT_S;
  351. break;
  352. case AM_REG_CTIMER_INTEN_CTMRB1C1INT_M:
  353. intIdx = AM_REG_CTIMER_INTEN_CTMRB1C1INT_S;
  354. break;
  355. case AM_REG_CTIMER_INTEN_CTMRA2C1INT_M:
  356. intIdx = AM_REG_CTIMER_INTEN_CTMRA2C1INT_S;
  357. break;
  358. case AM_REG_CTIMER_INTEN_CTMRB2C1INT_M:
  359. intIdx = AM_REG_CTIMER_INTEN_CTMRB2C1INT_S;
  360. break;
  361. case AM_REG_CTIMER_INTEN_CTMRA3C1INT_M:
  362. intIdx = AM_REG_CTIMER_INTEN_CTMRA3C1INT_S;
  363. break;
  364. case AM_REG_CTIMER_INTEN_CTMRB3C1INT_M:
  365. intIdx = AM_REG_CTIMER_INTEN_CTMRB3C1INT_S;
  366. break;
  367. default:
  368. am_hal_debug_assert_msg(false, "CTimer interrupt number out of range.");
  369. }
  370. am_hal_ctimer_ppfnHandlers[intIdx] = pfnHandler;
  371. } // am_hal_ctimer_int_register()
  372. //*****************************************************************************
  373. //
  374. //! @brief Set up the counter/timer.
  375. //!
  376. //! @param ui32TimerNumber is the number of the Timer that should be
  377. //! configured.
  378. //!
  379. //! @param psConfig is a pointer to a structure that holds important settings
  380. //! for the timer.
  381. //!
  382. //! This function should be used to perform the initial set-up of the
  383. //! counter-timer.
  384. //!
  385. //! @note This function will eventually be replaced by
  386. //! am_hal_ctimer_config_single(), which performs the same configuration
  387. //! without requiring a structure. Please use am_hal_ctimer_config_single() for
  388. //! new development.
  389. //!
  390. //! @return None.
  391. //
  392. //*****************************************************************************
  393. void
  394. am_hal_ctimer_config(uint32_t ui32TimerNumber,
  395. am_hal_ctimer_config_t *psConfig)
  396. {
  397. uint32_t *pui32ConfigReg;
  398. uint32_t ui32ConfigVal;
  399. //
  400. // Start preparing the configuration word for this timer. The configuration
  401. // values for Timer A and Timer B provided in the config structure should
  402. // match the register definitions already, so we will mostly just need to
  403. // OR them together.
  404. //
  405. ui32ConfigVal = ( (psConfig->ui32TimerAConfig) |
  406. (psConfig->ui32TimerBConfig << 16) );
  407. //
  408. // OR in the Link bit if the timers need to be linked.
  409. //
  410. ui32ConfigVal |= psConfig->ui32Link ? AM_HAL_CTIMER_LINK : 0;
  411. //
  412. // Begin critical section while config registers are read and modified.
  413. //
  414. AM_CRITICAL_BEGIN_ASM
  415. //
  416. // Find the correct register to write.
  417. //
  418. pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
  419. (ui32TimerNumber * TIMER_OFFSET));
  420. //
  421. // Write our configuration value.
  422. //
  423. AM_REGVAL(pui32ConfigReg) = ui32ConfigVal;
  424. //
  425. // If all of the clock sources are not HRFC disable LDO when sleeping if timers are enabled.
  426. //
  427. if ( timers_use_hfrc() )
  428. {
  429. AM_BFW(PWRCTRL, MISCOPT, DIS_LDOLPMODE_TIMERS, 0);
  430. }
  431. else
  432. {
  433. AM_BFW(PWRCTRL, MISCOPT, DIS_LDOLPMODE_TIMERS, 1);
  434. }
  435. //
  436. // Done with critical section.
  437. //
  438. AM_CRITICAL_END_ASM
  439. } // am_hal_ctimer_config()
  440. //*****************************************************************************
  441. //
  442. //! @brief Set up the counter/timer.
  443. //!
  444. //! @param ui32TimerNumber is the number of the Timer that should be
  445. //! configured.
  446. //!
  447. //! @param ui32TimerSegment specifies which segment of the timer should be
  448. //! enabled.
  449. //!
  450. //! @param ui32Configval specifies the configuration options for the selected
  451. //! timer.
  452. //!
  453. //! This function should be used to perform the initial set-up of the
  454. //! counter-timer. It can be used to configure either a 16-bit timer (A or B) or a
  455. //! 32-bit timer using the BOTH option.
  456. //!
  457. //! Valid values for ui32TimerSegment are:
  458. //!
  459. //! AM_HAL_CTIMER_TIMERA
  460. //! AM_HAL_CTIMER_TIMERB
  461. //! AM_HAL_CTIMER_BOTH
  462. //!
  463. //! The timer's clock source, mode, interrupt, and external pin behavior are
  464. //! all controlled through the \e ui32Configval parameter. The valid options
  465. //! for ui32ConfigVal include any ORed together combination of the following:
  466. //!
  467. //! Clock configuration macros:
  468. //!
  469. //! AM_HAL_CTIMER_HFRC_24MHZ
  470. //! AM_HAL_CTIMER_LFRC_512HZ
  471. //! ... etc. (See am_hal_ctimer.h for the full set of options.)
  472. //!
  473. //! Mode selection macros:
  474. //!
  475. //! AM_HAL_CTIMER_FN_ONCE
  476. //! AM_HAL_CTIMER_FN_REPEAT
  477. //! AM_HAL_CTIMER_FN_PWM_ONCE
  478. //! AM_HAL_CTIMER_FN_PWM_REPEAT
  479. //! AM_HAL_CTIMER_FN_CONTINUOUS
  480. //!
  481. //! Interrupt control:
  482. //!
  483. //! AM_HAL_CTIMER_INT_ENABLE
  484. //!
  485. //! Pin control:
  486. //!
  487. //! AM_HAL_CTIMER_PIN_ENABLE
  488. //! AM_HAL_CTIMER_PIN_INVERT
  489. //!
  490. //! ADC trigger (Timer 3 only):
  491. //!
  492. //! AM_HAL_CTIMER_ADC_TRIG
  493. //!
  494. //! @return None.
  495. //
  496. //*****************************************************************************
  497. void
  498. am_hal_ctimer_config_single(uint32_t ui32TimerNumber,
  499. uint32_t ui32TimerSegment,
  500. uint32_t ui32ConfigVal)
  501. {
  502. volatile uint32_t *pui32ConfigReg;
  503. uint32_t ui32WriteVal;
  504. //
  505. // Find the correct register to write based on the timer number.
  506. //
  507. pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
  508. (ui32TimerNumber * TIMER_OFFSET));
  509. //
  510. // Begin critical section while config registers are read and modified.
  511. //
  512. AM_CRITICAL_BEGIN_ASM
  513. //
  514. // Save the value that's already in the register.
  515. //
  516. ui32WriteVal = AM_REGVAL(pui32ConfigReg);
  517. //
  518. // If we're working with TIMERB, we need to shift our configuration value
  519. // up by 16 bits.
  520. //
  521. if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
  522. {
  523. ui32ConfigVal = ((ui32ConfigVal & 0xFFFF) << 16);
  524. }
  525. //
  526. // Replace part of the saved register value with the configuration value
  527. // from the caller.
  528. //
  529. ui32WriteVal = (ui32WriteVal & ~(ui32TimerSegment)) | ui32ConfigVal;
  530. //
  531. // If we're configuring both timers, we need to set the "link" bit.
  532. //
  533. if ( ui32TimerSegment == AM_HAL_CTIMER_BOTH )
  534. {
  535. ui32WriteVal |= AM_HAL_CTIMER_LINK;
  536. }
  537. //
  538. // Write our completed configuration value.
  539. //
  540. AM_REGVAL(pui32ConfigReg) = ui32WriteVal;
  541. //
  542. // If all of the clock sources are not HRFC disable LDO when sleeping if timers are enabled.
  543. //
  544. if ( timers_use_hfrc() )
  545. {
  546. AM_BFW(PWRCTRL, MISCOPT, DIS_LDOLPMODE_TIMERS, 0);
  547. }
  548. else
  549. {
  550. AM_BFW(PWRCTRL, MISCOPT, DIS_LDOLPMODE_TIMERS, 1);
  551. }
  552. //
  553. // Done with critical section.
  554. //
  555. AM_CRITICAL_END_ASM
  556. } // am_hal_ctimer_config_single()
  557. //*****************************************************************************
  558. //
  559. //! @brief Start a timer
  560. //!
  561. //! @param ui32TimerNumber is the number of the timer to enable
  562. //!
  563. //! @param ui32TimerSegment specifies which segment of the timer should be
  564. //! enabled. Valid values for ui32TimerSegment are:
  565. //! AM_HAL_CTIMER_TIMERA
  566. //! AM_HAL_CTIMER_TIMERB
  567. //! AM_HAL_CTIMER_BOTH
  568. //!
  569. //! This function will enable a timer to begin incrementing. The \e
  570. //! ui32TimerNumber parameter selects the timer that should be enabled, for
  571. //! example, a 0 would target TIMER0. The \e ui32TimerSegment parameter allows
  572. //! the caller to individually select a segment within a timer to be enabled,
  573. //! such as TIMER0A, TIMER0B, or both.
  574. //!
  575. //! @return None.
  576. //
  577. //*****************************************************************************
  578. void
  579. am_hal_ctimer_start(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
  580. {
  581. volatile uint32_t *pui32ConfigReg;
  582. uint32_t ui32ConfigVal;
  583. //
  584. // Find the correct control register.
  585. //
  586. pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
  587. (ui32TimerNumber * TIMER_OFFSET));
  588. //
  589. // Begin critical section while config registers are read and modified.
  590. //
  591. AM_CRITICAL_BEGIN_ASM
  592. //
  593. // Read the current value.
  594. //
  595. ui32ConfigVal = *pui32ConfigReg;
  596. //
  597. // Clear out the "clear" bit.
  598. //
  599. ui32ConfigVal &= ~(ui32TimerSegment & (AM_REG_CTIMER_CTRL0_TMRA0CLR_M |
  600. AM_REG_CTIMER_CTRL0_TMRB0CLR_M));
  601. //
  602. // Set the "enable bit"
  603. //
  604. ui32ConfigVal |= (ui32TimerSegment & (AM_REG_CTIMER_CTRL0_TMRA0EN_M |
  605. AM_REG_CTIMER_CTRL0_TMRB0EN_M));
  606. //
  607. // Write the value back to the register.
  608. //
  609. AM_REGVAL(pui32ConfigReg) = ui32ConfigVal;
  610. //
  611. // Done with critical section.
  612. //
  613. AM_CRITICAL_END_ASM
  614. } // am_hal_ctimer_start()
  615. //*****************************************************************************
  616. //
  617. //! @brief Stop a timer
  618. //!
  619. //! @param ui32TimerNumber is the number of the timer to disable.
  620. //!
  621. //! @param ui32TimerSegment specifies which segment of the timer should be
  622. //! disabled.
  623. //!
  624. //! This function will stop the selected timer from incrementing. The \e
  625. //! ui32TimerNumber parameter selects the timer that should be disabled, for
  626. //! example, a 0 would target TIMER0. The \e ui32TimerSegment parameter allows
  627. //! the caller to individually select a segment within a timer to be disabled,
  628. //! such as TIMER0A, TIMER0B, or both.
  629. //!
  630. //! This function will stop a counter/timer from counting, but does not return
  631. //! the count value to 'zero'. If you would like to reset the counter back to
  632. //! zero, try the am_hal_ctimer_clear() function instead.
  633. //!
  634. //! Valid values for ui32TimerSegment are:
  635. //!
  636. //! AM_HAL_CTIMER_TIMERA
  637. //! AM_HAL_CTIMER_TIMERB
  638. //! AM_HAL_CTIMER_BOTH
  639. //!
  640. //! @return None.
  641. //
  642. //*****************************************************************************
  643. void
  644. am_hal_ctimer_stop(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
  645. {
  646. volatile uint32_t *pui32ConfigReg;
  647. //
  648. // Find the correct control register.
  649. //
  650. pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
  651. (ui32TimerNumber * TIMER_OFFSET));
  652. //
  653. // Begin critical section.
  654. //
  655. AM_CRITICAL_BEGIN_ASM
  656. //
  657. // Clear the "enable" bit
  658. //
  659. AM_REGVAL(pui32ConfigReg) &= ~(ui32TimerSegment &
  660. (AM_REG_CTIMER_CTRL0_TMRA0EN_M |
  661. AM_REG_CTIMER_CTRL0_TMRB0EN_M));
  662. //
  663. // Done with critical section.
  664. //
  665. AM_CRITICAL_END_ASM
  666. } // am_hal_ctimer_stop()
  667. //*****************************************************************************
  668. //
  669. //! @brief Stops a timer and resets its value back to zero.
  670. //!
  671. //! @param ui32TimerNumber is the number of the timer to clear.
  672. //!
  673. //! @param ui32TimerSegment specifies which segment of the timer should be
  674. //! cleared.
  675. //!
  676. //! This function will stop a free-running counter-timer, reset its value to
  677. //! zero, and leave the timer disabled. When you would like to restart the
  678. //! counter, you will need to call am_hal_ctimer_start().
  679. //!
  680. //! The \e ui32TimerSegment parameter allows the caller to individually select
  681. //! a segment within, such as TIMER0A, TIMER0B, or both.
  682. //!
  683. //! Valid values for ui32TimerSegment are:
  684. //!
  685. //! AM_HAL_CTIMER_TIMERA
  686. //! AM_HAL_CTIMER_TIMERB
  687. //! AM_HAL_CTIMER_BOTH
  688. //!
  689. //! @return None.
  690. //
  691. //*****************************************************************************
  692. void
  693. am_hal_ctimer_clear(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
  694. {
  695. volatile uint32_t *pui32ConfigReg;
  696. //
  697. // Find the correct control register.
  698. //
  699. pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
  700. (ui32TimerNumber * TIMER_OFFSET));
  701. //
  702. // Begin critical section.
  703. //
  704. AM_CRITICAL_BEGIN_ASM
  705. //
  706. // Set the "clear" bit
  707. //
  708. AM_REGVAL(pui32ConfigReg) |= (ui32TimerSegment &
  709. (AM_REG_CTIMER_CTRL0_TMRA0CLR_M |
  710. AM_REG_CTIMER_CTRL0_TMRB0CLR_M));
  711. //
  712. // Done with critical section.
  713. //
  714. AM_CRITICAL_END_ASM
  715. } // am_hal_ctimer_clear()
  716. //*****************************************************************************
  717. //
  718. //! @brief Returns the current free-running value of the selected timer.
  719. //!
  720. //! @param ui32TimerNumber is the number of the timer to read.
  721. //! @param ui32TimerSegment specifies which segment of the timer should be
  722. //! read.
  723. //!
  724. //! This function returns the current free-running value of the selected timer.
  725. //!
  726. //! @note When reading from a linked timer, be sure to use AM_HAL_CTIMER both
  727. //! for the segment argument.
  728. //!
  729. //! Valid values for ui32TimerSegment are:
  730. //!
  731. //! AM_HAL_CTIMER_TIMERA
  732. //! AM_HAL_CTIMER_TIMERB
  733. //! AM_HAL_CTIMER_BOTH
  734. //!
  735. //! @return Current timer value.
  736. //
  737. //*****************************************************************************
  738. uint32_t
  739. am_hal_ctimer_read(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
  740. {
  741. volatile uint32_t ui32Value = 0;
  742. uint32_t ui32Values[3] = {0};
  743. uint32_t ui32TimerAddrTbl[4] =
  744. {
  745. REG_CTIMER_BASEADDR + AM_REG_CTIMER_TMR0_O,
  746. REG_CTIMER_BASEADDR + AM_REG_CTIMER_TMR1_O,
  747. REG_CTIMER_BASEADDR + AM_REG_CTIMER_TMR2_O,
  748. REG_CTIMER_BASEADDR + AM_REG_CTIMER_TMR3_O
  749. };
  750. //
  751. // Read the timer with back2back reads. This is a workaround for a clock
  752. // domain synchronization issue. Some timer bits may be slow to increment,
  753. // which means that the value in the timer register will sometimes be
  754. // wrong.
  755. //
  756. // The architecture guarantees that:
  757. //
  758. // 1) If the timer is running at a speed close to the core frequency, the
  759. // core and timer clock domains will be synchronized, and no "bad" reads
  760. // will happen.
  761. //
  762. // 2) Bad reads will only happen if the core reads the timer register while
  763. // the timer value is transitioning from one count to the next.
  764. //
  765. // 3) The timer will resolve to the correct value within one 24 MHz clock
  766. // cycle.
  767. //
  768. // If we read the timer three times in a row with back-to-back load
  769. // instructions, then we can guarantee that the timer will only have time
  770. // to increment once, and that only one of the three reads can be wrong.
  771. // This routine will perform the back-to-back reads and return all three
  772. // values. The rest of this fuction determines which value we should
  773. // actually use.
  774. //
  775. back2back_reads(ui32TimerAddrTbl[ui32TimerNumber], ui32Values);
  776. //
  777. // Shift or mask the values based on the given timer segment.
  778. //
  779. if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
  780. {
  781. ui32Values[0] >>= 16;
  782. ui32Values[1] >>= 16;
  783. ui32Values[2] >>= 16;
  784. }
  785. else if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERA )
  786. {
  787. ui32Values[0] &= 0xFFFF;
  788. ui32Values[1] &= 0xFFFF;
  789. ui32Values[2] &= 0xFFFF;
  790. }
  791. //
  792. // Now, we'll figure out which of the three values is the correct time.
  793. //
  794. if (ui32Values[0] == ui32Values[1])
  795. {
  796. //
  797. // If the first two values match, then neither one was a bad read.
  798. // We'll take this as the current time.
  799. //
  800. ui32Value = ui32Values[1];
  801. }
  802. else
  803. {
  804. //
  805. // If the first two values didn't match, then one of them might be bad.
  806. // If one of the first two values is bad, then the third one should
  807. // always be correct. We'll take the third value as the correct time.
  808. //
  809. ui32Value = ui32Values[2];
  810. //
  811. // If all of the statements about the architecture are true, the third
  812. // value should be correct, and it should always be within one count of
  813. // either the first or the second value.
  814. //
  815. // Just in case, we'll check against the previous two values to make
  816. // sure that our final answer was reasonable. If it isn't, we will
  817. // flag it as a "bad read", and fail this assert statement.
  818. //
  819. // This shouldn't ever happen, and it hasn't ever happened in any of
  820. // our tests so far.
  821. //
  822. am_hal_debug_assert_msg((adjacent(ui32Values[1], ui32Values[2]) ||
  823. adjacent(ui32Values[0], ui32Values[2])),
  824. "Bad CTIMER read");
  825. }
  826. return ui32Value;
  827. } // am_hal_ctimer_read()
  828. //*****************************************************************************
  829. //
  830. //! @brief Enable output to the timer pin
  831. //!
  832. //! @param ui32TimerNumber is the number of the timer to configure.
  833. //!
  834. //! @param ui32TimerSegment specifies which segment of the timer to use.
  835. //!
  836. //! This function will enable the output pin for the selected timer. The \e
  837. //! ui32TimerSegment parameter allows the caller to individually select a
  838. //! segment within, such as TIMER0A, TIMER0B, or both.
  839. //!
  840. //! Valid values for ui32TimerSegment are:
  841. //!
  842. //! AM_HAL_CTIMER_TIMERA
  843. //! AM_HAL_CTIMER_TIMERB
  844. //! AM_HAL_CTIMER_BOTH
  845. //!
  846. //! @return None.
  847. //
  848. //*****************************************************************************
  849. void
  850. am_hal_ctimer_pin_enable(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
  851. {
  852. volatile uint32_t *pui32ConfigReg;
  853. //
  854. // Find the correct control register.
  855. //
  856. pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
  857. (ui32TimerNumber * TIMER_OFFSET));
  858. //
  859. // Begin critical section.
  860. //
  861. AM_CRITICAL_BEGIN_ASM
  862. //
  863. // Set the pin enable bit
  864. //
  865. AM_REGVAL(pui32ConfigReg) |= (ui32TimerSegment &
  866. (AM_REG_CTIMER_CTRL0_TMRA0PE_M |
  867. AM_REG_CTIMER_CTRL0_TMRB0PE_M));
  868. //
  869. // Done with critical section.
  870. //
  871. AM_CRITICAL_END_ASM
  872. } // am_hal_ctimer_pin_enable()
  873. //*****************************************************************************
  874. //
  875. //! @brief Disable the output pin.
  876. //!
  877. //! @param ui32TimerNumber is the number of the timer to configure.
  878. //!
  879. //! @param ui32TimerSegment specifies which segment of the timer to use.
  880. //!
  881. //! This function will disable the output pin for the selected timer. The \e
  882. //! ui32TimerSegment parameter allows the caller to individually select a
  883. //! segment within, such as TIMER0A, TIMER0B, or both.
  884. //!
  885. //! Valid values for ui32TimerSegment are:
  886. //!
  887. //! AM_HAL_CTIMER_TIMERA
  888. //! AM_HAL_CTIMER_TIMERB
  889. //! AM_HAL_CTIMER_BOTH
  890. //!
  891. //! @return None.
  892. //
  893. //*****************************************************************************
  894. void
  895. am_hal_ctimer_pin_disable(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
  896. {
  897. volatile uint32_t *pui32ConfigReg;
  898. //
  899. // Find the correct control register.
  900. //
  901. pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
  902. (ui32TimerNumber * TIMER_OFFSET));
  903. //
  904. // Begin critical section.
  905. //
  906. AM_CRITICAL_BEGIN_ASM
  907. //
  908. // Clear the pin enable bit
  909. //
  910. AM_REGVAL(pui32ConfigReg) &= ~(ui32TimerSegment &
  911. (AM_REG_CTIMER_CTRL0_TMRA0PE_M |
  912. AM_REG_CTIMER_CTRL0_TMRB0PE_M));
  913. //
  914. // Done with critical section.
  915. //
  916. AM_CRITICAL_END_ASM
  917. } // am_hal_ctimer_pin_disable()
  918. //*****************************************************************************
  919. //
  920. //! @brief Set the polarity of the output pin.
  921. //!
  922. //! @param ui32TimerNumber is the number of the timer to configure.
  923. //!
  924. //! @param ui32TimerSegment specifies which segment of the timer to use.
  925. //!
  926. //! @param bInvertOutpt determines whether the output should be inverted. If
  927. //! true, the timer output pin for the selected timer segment will be
  928. //! inverted.
  929. //!
  930. //! This function will set the polarity of the the output pin for the selected
  931. //! timer. The \e ui32TimerSegment parameter allows the caller to individually
  932. //! select a segment within, such as TIMER0A, TIMER0B, or both.
  933. //!
  934. //! Valid values for ui32TimerSegment are:
  935. //!
  936. //! AM_HAL_CTIMER_TIMERA
  937. //! AM_HAL_CTIMER_TIMERB
  938. //! AM_HAL_CTIMER_BOTH
  939. //!
  940. //! @return None.
  941. //
  942. //*****************************************************************************
  943. void
  944. am_hal_ctimer_pin_invert(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment,
  945. bool bInvertOutput)
  946. {
  947. volatile uint32_t *pui32ConfigReg;
  948. //
  949. // Find the correct control register.
  950. //
  951. pui32ConfigReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
  952. (ui32TimerNumber * TIMER_OFFSET));
  953. //
  954. // Begin critical section.
  955. //
  956. AM_CRITICAL_BEGIN_ASM
  957. //
  958. // Figure out if we're supposed to be setting or clearing the polarity bit.
  959. //
  960. if ( bInvertOutput )
  961. {
  962. //
  963. // Set the polarity bit to invert the output.
  964. //
  965. AM_REGVAL(pui32ConfigReg) |= (ui32TimerSegment &
  966. (AM_REG_CTIMER_CTRL0_TMRA0POL_M |
  967. AM_REG_CTIMER_CTRL0_TMRB0POL_M));
  968. }
  969. else
  970. {
  971. //
  972. // Clear the polarity bit.
  973. //
  974. AM_REGVAL(pui32ConfigReg) &= ~(ui32TimerSegment &
  975. (AM_REG_CTIMER_CTRL0_TMRA0POL_M |
  976. AM_REG_CTIMER_CTRL0_TMRB0POL_M));
  977. }
  978. //
  979. // Done with critical section.
  980. //
  981. AM_CRITICAL_END_ASM
  982. } // am_hal_ctimer_pin_invert()
  983. //*****************************************************************************
  984. //
  985. //! @brief Set a compare register.
  986. //!
  987. //! @param ui32TimerNumber is the number of the timer to configure.
  988. //!
  989. //! @param ui32TimerSegment specifies which segment of the timer to use.
  990. //! Valid values for ui32TimerSegment are:
  991. //!
  992. //! AM_HAL_CTIMER_TIMERA
  993. //! AM_HAL_CTIMER_TIMERB
  994. //! AM_HAL_CTIMER_BOTH
  995. //!
  996. //! @param ui32CompareReg specifies which compare register should be set
  997. //! (either 0 or 1)
  998. //!
  999. //! @param ui32Value is the value that should be written to the compare
  1000. //! register.
  1001. //!
  1002. //! This function allows the caller to set the values in the compare registers
  1003. //! for a timer. These registers control the period and duty cycle of the
  1004. //! timers and their associated output pins. Please see the datasheet for
  1005. //! further information on the operation of the compare registers. The \e
  1006. //! ui32TimerSegment parameter allows the caller to individually select a
  1007. //! segment within, such as TIMER0A, TIMER0B, or both.
  1008. //!
  1009. //! @note For simple manipulations of period or duty cycle for timers and PWMs,
  1010. //! you may find it easier to use the am_hal_ctimer_period_set() function.
  1011. //!
  1012. //! @return None.
  1013. //
  1014. //*****************************************************************************
  1015. void
  1016. am_hal_ctimer_compare_set(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment,
  1017. uint32_t ui32CompareReg, uint32_t ui32Value)
  1018. {
  1019. volatile uint32_t *pui32CmprRegA, *pui32CmprRegB;
  1020. uint32_t ui32CmprRegA, ui32CmprRegB;
  1021. //
  1022. // Find the correct compare register to write.
  1023. // Assume A or BOTH. We'll change later if B.
  1024. //
  1025. pui32CmprRegA = (uint32_t *)(AM_REG_CTIMERn(0) +
  1026. AM_REG_CTIMER_CMPRA0_O +
  1027. (ui32TimerNumber * TIMER_OFFSET));
  1028. pui32CmprRegB = pui32CmprRegA + CTIMER_CMPR_OFFSET;
  1029. //
  1030. // Write the compare register with the selected value.
  1031. // Begin critical section while CMPR registers are modified.
  1032. //
  1033. AM_CRITICAL_BEGIN_ASM
  1034. ui32CmprRegA = *pui32CmprRegA;
  1035. ui32CmprRegB = *pui32CmprRegB;
  1036. if ( ui32CompareReg == 1 )
  1037. {
  1038. //
  1039. // CMPR reg 1
  1040. // Get the lower 16b (but may not be used if TIMERB).
  1041. //
  1042. ui32CmprRegA = ( (ui32CmprRegA & AM_REG_CTIMER_CMPRA0_CMPR0A0_M) |
  1043. AM_REG_CTIMER_CMPRA0_CMPR1A0(ui32Value & 0xFFFF) );
  1044. //
  1045. // Get the upper 16b (but may not be used if TIMERA)
  1046. //
  1047. ui32CmprRegB = ( (ui32CmprRegB & AM_REG_CTIMER_CMPRA0_CMPR0A0_M) |
  1048. AM_REG_CTIMER_CMPRA0_CMPR1A0(ui32Value >> 16) );
  1049. }
  1050. else
  1051. {
  1052. //
  1053. // CMPR reg 0
  1054. // Get the lower 16b (but may not be used if TIMERB)
  1055. //
  1056. ui32CmprRegA = ( (ui32CmprRegA & AM_REG_CTIMER_CMPRA0_CMPR1A0_M) |
  1057. AM_REG_CTIMER_CMPRA0_CMPR0A0(ui32Value & 0xFFFF) );
  1058. //
  1059. // Set the upper 16b (but may not be used if TIMERA)
  1060. //
  1061. ui32CmprRegB = ( (ui32CmprRegB & AM_REG_CTIMER_CMPRA0_CMPR1A0_M) |
  1062. AM_REG_CTIMER_CMPRA0_CMPR0A0(ui32Value >> 16) );
  1063. }
  1064. if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
  1065. {
  1066. *pui32CmprRegB = ui32CmprRegB;
  1067. }
  1068. else
  1069. {
  1070. //
  1071. // It's TIMERA or BOTH.
  1072. //
  1073. *pui32CmprRegA = ui32CmprRegA;
  1074. if ( ui32TimerSegment == AM_HAL_CTIMER_BOTH )
  1075. {
  1076. *pui32CmprRegB = ui32CmprRegB;
  1077. }
  1078. }
  1079. //
  1080. // Done with critical section.
  1081. //
  1082. AM_CRITICAL_END_ASM
  1083. } // am_hal_ctimer_compare_set()
  1084. //*****************************************************************************
  1085. //
  1086. //! @brief Set the period and duty cycle of a timer.
  1087. //!
  1088. //! @param ui32TimerNumber is the number of the timer to configure.
  1089. //!
  1090. //! @param ui32TimerSegment specifies which segment of the timer to use.
  1091. //!
  1092. //! @param ui32Period specifies the desired period. This parameter effectively
  1093. //! specifies the CTIMER CMPR field(s). The CMPR fields are handled in hardware
  1094. //! as (n+1) values, therefore ui32Period is actually specified as 1 less than
  1095. //! the desired period. Finally, as mentioned in the data sheet, the CMPR fields
  1096. //! cannot be 0 (a value of 1), so neither can ui32Period be 0.
  1097. //!
  1098. //! @param ui32OnTime set the number of clocks where the output signal is high.
  1099. //!
  1100. //! This function should be used for simple manipulations of the period and
  1101. //! duty cycle of a counter/timer. To set the period and/or duty cycle of a
  1102. //! linked timer pair, use AM_HAL_CTIMER_BOTH as the timer segment argument. If
  1103. //! you would like to set the period and/or duty cycle for both TIMERA and
  1104. //! TIMERB you will need to call this function twice: once for TIMERA, and once
  1105. //! for TIMERB.
  1106. //!
  1107. //! Valid values for ui32TimerSegment are:
  1108. //!
  1109. //! AM_HAL_CTIMER_TIMERA
  1110. //! AM_HAL_CTIMER_TIMERB
  1111. //! AM_HAL_CTIMER_BOTH
  1112. //!
  1113. //! @note The ui32OnTime parameter will only work if the timer is currently
  1114. //! operating in one of the PWM modes.
  1115. //!
  1116. //! @return None.
  1117. //
  1118. //*****************************************************************************
  1119. void
  1120. am_hal_ctimer_period_set(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment,
  1121. uint32_t ui32Period, uint32_t ui32OnTime)
  1122. {
  1123. volatile uint32_t *pui32ControlReg;
  1124. volatile uint32_t *pui32CompareRegA;
  1125. volatile uint32_t *pui32CompareRegB;
  1126. uint32_t ui32Mode, ui32Comp0, ui32Comp1;
  1127. //
  1128. // Find the correct control register to pull the function select field
  1129. // from.
  1130. //
  1131. pui32ControlReg = (uint32_t *)(AM_REG_CTIMERn(0) + AM_REG_CTIMER_CTRL0_O +
  1132. (ui32TimerNumber * TIMER_OFFSET));
  1133. //
  1134. // Find the correct compare registers to write.
  1135. //
  1136. pui32CompareRegA = (uint32_t *)(AM_REG_CTIMERn(0) +
  1137. AM_REG_CTIMER_CMPRA0_O +
  1138. (ui32TimerNumber * TIMER_OFFSET));
  1139. pui32CompareRegB = (uint32_t *)(AM_REG_CTIMERn(0) +
  1140. AM_REG_CTIMER_CMPRB0_O +
  1141. (ui32TimerNumber * TIMER_OFFSET));
  1142. //
  1143. // Begin critical section.
  1144. //
  1145. AM_CRITICAL_BEGIN_ASM
  1146. //
  1147. // Extract the timer mode from the register based on the ui32TimerSegment
  1148. // selected by the user.
  1149. //
  1150. ui32Mode = *pui32ControlReg;
  1151. if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
  1152. {
  1153. ui32Mode = ui32Mode >> 16;
  1154. }
  1155. //
  1156. // Mask to get to the bits we're interested in.
  1157. //
  1158. ui32Mode = ui32Mode & AM_REG_CTIMER_CTRL0_TMRA0FN_M;
  1159. //
  1160. // If the mode is a PWM mode, we'll need to calculate the correct CMPR0 and
  1161. // CMPR1 values here.
  1162. //
  1163. if (ui32Mode == AM_HAL_CTIMER_FN_PWM_ONCE ||
  1164. ui32Mode == AM_HAL_CTIMER_FN_PWM_REPEAT)
  1165. {
  1166. ui32Comp0 = ui32Period - ui32OnTime;
  1167. ui32Comp1 = ui32Period;
  1168. }
  1169. else
  1170. {
  1171. ui32Comp0 = ui32Period;
  1172. ui32Comp1 = 0;
  1173. }
  1174. //
  1175. // Based on the timer segment argument, write the calculated Compare 0 and
  1176. // Compare 1 values to the correct halves of the correct registers.
  1177. //
  1178. if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERA )
  1179. {
  1180. //
  1181. // For timer A, write the values to the TIMERA compare register.
  1182. //
  1183. *pui32CompareRegA = (AM_REG_CTIMER_CMPRA0_CMPR0A0(ui32Comp0) |
  1184. AM_REG_CTIMER_CMPRA0_CMPR1A0(ui32Comp1));
  1185. }
  1186. else if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
  1187. {
  1188. //
  1189. // For timer B, write the values to the TIMERA compare register.
  1190. //
  1191. *pui32CompareRegB = (AM_REG_CTIMER_CMPRA0_CMPR0A0(ui32Comp0) |
  1192. AM_REG_CTIMER_CMPRA0_CMPR1A0(ui32Comp1));
  1193. }
  1194. else
  1195. {
  1196. //
  1197. // For the linked case, write the lower halves of the values to the
  1198. // TIMERA compare register, and the upper halves to the TIMERB compare
  1199. // register.
  1200. //
  1201. *pui32CompareRegA = (AM_REG_CTIMER_CMPRA0_CMPR0A0(ui32Comp0) |
  1202. AM_REG_CTIMER_CMPRA0_CMPR1A0(ui32Comp1));
  1203. *pui32CompareRegB = (AM_REG_CTIMER_CMPRA0_CMPR0A0(ui32Comp0 >> 16) |
  1204. AM_REG_CTIMER_CMPRA0_CMPR1A0(ui32Comp1 >> 16));
  1205. }
  1206. //
  1207. // Done with critical section.
  1208. //
  1209. AM_CRITICAL_END_ASM
  1210. } // am_hal_ctimer_period_set()
  1211. //*****************************************************************************
  1212. //
  1213. //! @brief Enable the TIMERA3 ADC trigger
  1214. //!
  1215. //! This function enables the ADC trigger within TIMERA3.
  1216. //!
  1217. //! @return None.
  1218. //
  1219. //*****************************************************************************
  1220. void
  1221. am_hal_ctimer_adc_trigger_enable(void)
  1222. {
  1223. //
  1224. // Begin critical section.
  1225. //
  1226. AM_CRITICAL_BEGIN_ASM
  1227. //
  1228. // Enable the ADC trigger.
  1229. //
  1230. AM_REGn(CTIMER, 0, CTRL3) |= AM_REG_CTIMER_CTRL3_ADCEN_M;
  1231. //
  1232. // Done with critical section.
  1233. //
  1234. AM_CRITICAL_END_ASM
  1235. } // am_hal_ctimer_adc_trigger_enable()
  1236. //*****************************************************************************
  1237. //
  1238. //! @brief Disable the TIMERA3 ADC trigger
  1239. //!
  1240. //! This function disables the ADC trigger within TIMERA3.
  1241. //!
  1242. //! @return None.
  1243. //
  1244. //*****************************************************************************
  1245. void
  1246. am_hal_ctimer_adc_trigger_disable(void)
  1247. {
  1248. //
  1249. // Begin critical section.
  1250. //
  1251. AM_CRITICAL_BEGIN_ASM
  1252. //
  1253. // Disable the ADC trigger.
  1254. //
  1255. AM_REGn(CTIMER, 0, CTRL3) &= ~AM_REG_CTIMER_CTRL3_ADCEN_M;
  1256. //
  1257. // Done with critical section.
  1258. //
  1259. AM_CRITICAL_END_ASM
  1260. } // am_hal_ctimer_adc_trigger_disable()
  1261. //*****************************************************************************
  1262. //
  1263. //! @brief Enables the selected timer interrupt.
  1264. //!
  1265. //! @param ui32Interrupt is the interrupt to be used.
  1266. //!
  1267. //! This function will enable the selected interrupts in the main CTIMER
  1268. //! interrupt enable register. In order to receive an interrupt from a timer,
  1269. //! you will need to enable the interrupt for that timer in this main register,
  1270. //! as well as in the timer control register (accessible though
  1271. //! am_hal_ctimer_config()), and in the NVIC.
  1272. //!
  1273. //! ui32Interrupt should be the logical OR of one or more of the following
  1274. //! values:
  1275. //!
  1276. //! AM_HAL_CTIMER_INT_TIMERA0C0
  1277. //! AM_HAL_CTIMER_INT_TIMERA0C1
  1278. //! AM_HAL_CTIMER_INT_TIMERB0C0
  1279. //! AM_HAL_CTIMER_INT_TIMERB0C1
  1280. //! AM_HAL_CTIMER_INT_TIMERA1C0
  1281. //! AM_HAL_CTIMER_INT_TIMERA1C1
  1282. //! AM_HAL_CTIMER_INT_TIMERB1C0
  1283. //! AM_HAL_CTIMER_INT_TIMERB1C1
  1284. //! AM_HAL_CTIMER_INT_TIMERA2C0
  1285. //! AM_HAL_CTIMER_INT_TIMERA2C1
  1286. //! AM_HAL_CTIMER_INT_TIMERB2C0
  1287. //! AM_HAL_CTIMER_INT_TIMERB2C1
  1288. //! AM_HAL_CTIMER_INT_TIMERA3C0
  1289. //! AM_HAL_CTIMER_INT_TIMERA3C1
  1290. //! AM_HAL_CTIMER_INT_TIMERB3C0
  1291. //! AM_HAL_CTIMER_INT_TIMERB3C1
  1292. //!
  1293. //! @return None.
  1294. //
  1295. //*****************************************************************************
  1296. void
  1297. am_hal_ctimer_int_enable(uint32_t ui32Interrupt)
  1298. {
  1299. //
  1300. // Begin critical section.
  1301. //
  1302. AM_CRITICAL_BEGIN_ASM
  1303. //
  1304. // Enable the interrupt at the module level.
  1305. //
  1306. AM_REGn(CTIMER, 0, INTEN) |= ui32Interrupt;
  1307. //
  1308. // Done with critical section.
  1309. //
  1310. AM_CRITICAL_END_ASM
  1311. } // am_hal_ctimer_int_enable()
  1312. //*****************************************************************************
  1313. //
  1314. //! @brief Return the enabled timer interrupts.
  1315. //!
  1316. //! This function will return all enabled interrupts in the main CTIMER
  1317. //! interrupt enable register.
  1318. //!
  1319. //! @return return enabled interrupts. This will be a logical or of:
  1320. //!
  1321. //! AM_HAL_CTIMER_INT_TIMERA0C0
  1322. //! AM_HAL_CTIMER_INT_TIMERA0C1
  1323. //! AM_HAL_CTIMER_INT_TIMERB0C0
  1324. //! AM_HAL_CTIMER_INT_TIMERB0C1
  1325. //! AM_HAL_CTIMER_INT_TIMERA1C0
  1326. //! AM_HAL_CTIMER_INT_TIMERA1C1
  1327. //! AM_HAL_CTIMER_INT_TIMERB1C0
  1328. //! AM_HAL_CTIMER_INT_TIMERB1C1
  1329. //! AM_HAL_CTIMER_INT_TIMERA2C0
  1330. //! AM_HAL_CTIMER_INT_TIMERA2C1
  1331. //! AM_HAL_CTIMER_INT_TIMERB2C0
  1332. //! AM_HAL_CTIMER_INT_TIMERB2C1
  1333. //! AM_HAL_CTIMER_INT_TIMERA3C0
  1334. //! AM_HAL_CTIMER_INT_TIMERA3C1
  1335. //! AM_HAL_CTIMER_INT_TIMERB3C0
  1336. //! AM_HAL_CTIMER_INT_TIMERB3C1
  1337. //!
  1338. //! @return Return the enabled timer interrupts.
  1339. //
  1340. //*****************************************************************************
  1341. uint32_t
  1342. am_hal_ctimer_int_enable_get(void)
  1343. {
  1344. //
  1345. // Return enabled interrupts.
  1346. //
  1347. return AM_REGn(CTIMER, 0, INTEN);
  1348. } // am_hal_ctimer_int_enable_get()
  1349. //*****************************************************************************
  1350. //
  1351. //! @brief Disables the selected timer interrupt.
  1352. //!
  1353. //! @param ui32Interrupt is the interrupt to be used.
  1354. //!
  1355. //! This function will disable the selected interrupts in the main CTIMER
  1356. //! interrupt register.
  1357. //!
  1358. //! ui32Interrupt should be the logical OR of one or more of the following
  1359. //! values:
  1360. //!
  1361. //! AM_HAL_CTIMER_INT_TIMERA0C0
  1362. //! AM_HAL_CTIMER_INT_TIMERA0C1
  1363. //! AM_HAL_CTIMER_INT_TIMERB0C0
  1364. //! AM_HAL_CTIMER_INT_TIMERB0C1
  1365. //! AM_HAL_CTIMER_INT_TIMERA1C0
  1366. //! AM_HAL_CTIMER_INT_TIMERA1C1
  1367. //! AM_HAL_CTIMER_INT_TIMERB1C0
  1368. //! AM_HAL_CTIMER_INT_TIMERB1C1
  1369. //! AM_HAL_CTIMER_INT_TIMERA2C0
  1370. //! AM_HAL_CTIMER_INT_TIMERA2C1
  1371. //! AM_HAL_CTIMER_INT_TIMERB2C0
  1372. //! AM_HAL_CTIMER_INT_TIMERB2C1
  1373. //! AM_HAL_CTIMER_INT_TIMERA3C0
  1374. //! AM_HAL_CTIMER_INT_TIMERA3C1
  1375. //! AM_HAL_CTIMER_INT_TIMERB3C0
  1376. //! AM_HAL_CTIMER_INT_TIMERB3C1
  1377. //!
  1378. //! @return None.
  1379. //
  1380. //*****************************************************************************
  1381. void
  1382. am_hal_ctimer_int_disable(uint32_t ui32Interrupt)
  1383. {
  1384. //
  1385. // Begin critical section.
  1386. //
  1387. AM_CRITICAL_BEGIN_ASM
  1388. //
  1389. // Disable the interrupt at the module level.
  1390. //
  1391. AM_REGn(CTIMER, 0, INTEN) &= ~ui32Interrupt;
  1392. //
  1393. // Done with critical section.
  1394. //
  1395. AM_CRITICAL_END_ASM
  1396. } // am_hal_ctimer_int_disable()
  1397. //*****************************************************************************
  1398. //
  1399. //! @brief Clears the selected timer interrupt.
  1400. //!
  1401. //! @param ui32Interrupt is the interrupt to be used.
  1402. //!
  1403. //! This function will clear the selected interrupts in the main CTIMER
  1404. //! interrupt register.
  1405. //!
  1406. //! ui32Interrupt should be the logical OR of one or more of the following
  1407. //! values:
  1408. //!
  1409. //! AM_HAL_CTIMER_INT_TIMERA0C0
  1410. //! AM_HAL_CTIMER_INT_TIMERA0C1
  1411. //! AM_HAL_CTIMER_INT_TIMERB0C0
  1412. //! AM_HAL_CTIMER_INT_TIMERB0C1
  1413. //! AM_HAL_CTIMER_INT_TIMERA1C0
  1414. //! AM_HAL_CTIMER_INT_TIMERA1C1
  1415. //! AM_HAL_CTIMER_INT_TIMERB1C0
  1416. //! AM_HAL_CTIMER_INT_TIMERB1C1
  1417. //! AM_HAL_CTIMER_INT_TIMERA2C0
  1418. //! AM_HAL_CTIMER_INT_TIMERA2C1
  1419. //! AM_HAL_CTIMER_INT_TIMERB2C0
  1420. //! AM_HAL_CTIMER_INT_TIMERB2C1
  1421. //! AM_HAL_CTIMER_INT_TIMERA3C0
  1422. //! AM_HAL_CTIMER_INT_TIMERA3C1
  1423. //! AM_HAL_CTIMER_INT_TIMERB3C0
  1424. //! AM_HAL_CTIMER_INT_TIMERB3C1
  1425. //!
  1426. //! @return None.
  1427. //
  1428. //*****************************************************************************
  1429. void
  1430. am_hal_ctimer_int_clear(uint32_t ui32Interrupt)
  1431. {
  1432. //
  1433. // Disable the interrupt at the module level.
  1434. //
  1435. AM_REGn(CTIMER, 0, INTCLR) = ui32Interrupt;
  1436. } // am_hal_ctimer_int_clear()
  1437. //*****************************************************************************
  1438. //
  1439. //! @brief Sets the selected timer interrupt.
  1440. //!
  1441. //! @param ui32Interrupt is the interrupt to be used.
  1442. //!
  1443. //! This function will set the selected interrupts in the main CTIMER
  1444. //! interrupt register.
  1445. //!
  1446. //! ui32Interrupt should be the logical OR of one or more of the following
  1447. //! values:
  1448. //!
  1449. //! AM_HAL_CTIMER_INT_TIMERA0C0
  1450. //! AM_HAL_CTIMER_INT_TIMERA0C1
  1451. //! AM_HAL_CTIMER_INT_TIMERB0C0
  1452. //! AM_HAL_CTIMER_INT_TIMERB0C1
  1453. //! AM_HAL_CTIMER_INT_TIMERA1C0
  1454. //! AM_HAL_CTIMER_INT_TIMERA1C1
  1455. //! AM_HAL_CTIMER_INT_TIMERB1C0
  1456. //! AM_HAL_CTIMER_INT_TIMERB1C1
  1457. //! AM_HAL_CTIMER_INT_TIMERA2C0
  1458. //! AM_HAL_CTIMER_INT_TIMERA2C1
  1459. //! AM_HAL_CTIMER_INT_TIMERB2C0
  1460. //! AM_HAL_CTIMER_INT_TIMERB2C1
  1461. //! AM_HAL_CTIMER_INT_TIMERA3C0
  1462. //! AM_HAL_CTIMER_INT_TIMERA3C1
  1463. //! AM_HAL_CTIMER_INT_TIMERB3C0
  1464. //! AM_HAL_CTIMER_INT_TIMERB3C1
  1465. //!
  1466. //! @return None.
  1467. //
  1468. //*****************************************************************************
  1469. void
  1470. am_hal_ctimer_int_set(uint32_t ui32Interrupt)
  1471. {
  1472. //
  1473. // Set the interrupts.
  1474. //
  1475. AM_REGn(CTIMER, 0, INTSET) = ui32Interrupt;
  1476. } // am_hal_ctimer_int_set()
  1477. //*****************************************************************************
  1478. //
  1479. //! @brief Returns either the enabled or raw timer interrupt status.
  1480. //!
  1481. //! This function will return the timer interrupt status.
  1482. //!
  1483. //! @return bEnabledOnly if true returns the status of the enabled interrupts
  1484. //! only.
  1485. //!
  1486. //! The return value will be the logical OR of one or more of the following
  1487. //! values:
  1488. //!
  1489. //! AM_HAL_CTIMER_INT_TIMERA0C0
  1490. //! AM_HAL_CTIMER_INT_TIMERA0C1
  1491. //! AM_HAL_CTIMER_INT_TIMERB0C0
  1492. //! AM_HAL_CTIMER_INT_TIMERB0C1
  1493. //! AM_HAL_CTIMER_INT_TIMERA1C0
  1494. //! AM_HAL_CTIMER_INT_TIMERA1C1
  1495. //! AM_HAL_CTIMER_INT_TIMERB1C0
  1496. //! AM_HAL_CTIMER_INT_TIMERB1C1
  1497. //! AM_HAL_CTIMER_INT_TIMERA2C0
  1498. //! AM_HAL_CTIMER_INT_TIMERA2C1
  1499. //! AM_HAL_CTIMER_INT_TIMERB2C0
  1500. //! AM_HAL_CTIMER_INT_TIMERB2C1
  1501. //! AM_HAL_CTIMER_INT_TIMERA3C0
  1502. //! AM_HAL_CTIMER_INT_TIMERA3C1
  1503. //! AM_HAL_CTIMER_INT_TIMERB3C0
  1504. //! AM_HAL_CTIMER_INT_TIMERB3C1
  1505. //!
  1506. //! @return Returns either the timer interrupt status.
  1507. //
  1508. //*****************************************************************************
  1509. uint32_t
  1510. am_hal_ctimer_int_status_get(bool bEnabledOnly)
  1511. {
  1512. //
  1513. // Return the desired status.
  1514. //
  1515. if ( bEnabledOnly )
  1516. {
  1517. uint32_t u32RetVal;
  1518. //
  1519. // Begin critical section.
  1520. //
  1521. AM_CRITICAL_BEGIN_ASM
  1522. u32RetVal = AM_REGn(CTIMER, 0, INTSTAT);
  1523. u32RetVal &= AM_REGn(CTIMER, 0, INTEN);
  1524. //
  1525. // Done with critical section.
  1526. //
  1527. AM_CRITICAL_END_ASM
  1528. return u32RetVal;
  1529. }
  1530. else
  1531. {
  1532. return AM_REGn(CTIMER, 0, INTSTAT);
  1533. }
  1534. } // am_hal_ctimer_int_status_get()
  1535. //*****************************************************************************
  1536. //
  1537. // End Doxygen group.
  1538. //! @}
  1539. //
  1540. //*****************************************************************************