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