am_hal_ctimer.c 53 KB

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