1 //*****************************************************************************
2 //
3 //! @file am_hal_ctimer.c
4 //!
5 //! @brief Functions for Interfacing with the Counter/Timer Module.
6 //!
7 //! @addtogroup ctimer3p CTimer - Counter/Timer
8 //! @ingroup apollo3p_hal
9 //! @{
10 //
11 //*****************************************************************************
12 
13 //*****************************************************************************
14 //
15 // Copyright (c) 2024, Ambiq Micro, Inc.
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 release_sdk_3_2_0-dd5f40c14b of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47 
48 #include <stdint.h>
49 #include <stdbool.h>
50 #include "am_mcu_apollo.h"
51 
52 //*****************************************************************************
53 //
54 // Adjacency check
55 //
56 // This is related to the timer read workaround. This macro checks to see if
57 // the two supplied count values are within one "tick" of eachother. It should
58 // still pass in the event of a timer rollover.
59 //
60 //*****************************************************************************
61 //! Timer read workaround: Do count values differ by one tick or less.
62 #define adjacent(A, B)      (((A) == (B)) || (((A) + 1) == (B)) || ((B) == 0))
63 
64 //*****************************************************************************
65 //
66 //! Array of function pointers for handling CTimer interrupts.
67 //
68 //*****************************************************************************
69 static am_hal_ctimer_handler_t g_am_hal_ctimer_ppfnHandlers[32];
70 
71 //
72 // Store the timer clock source value depending on segment.
73 // Getting the source clock everytime from the CTRL register will incur bus
74 // latency.  This table is maintained to minimize the read latency when
75 // attempting to retrieve the CLKSRC.
76 // CLKSRC is 5 bits, so uint8_t is adequate for the table.
77 //
78 static uint8_t
79 g_ui8ClkSrc[AM_HAL_CTIMER_TIMERS_NUM][2] =
80 {
81     {0xFF, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF},
82     {0xFF, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF}, {0xFF, 0xFF}
83 };
84 
85 //
86 // Table of TMR register addresses.
87 //
88 static const uint32_t
89 g_ui32TMRAddrTbl[AM_HAL_CTIMER_TIMERS_NUM] =
90 {
91     AM_REGADDR(CTIMER,TMR0), AM_REGADDR(CTIMER,TMR1), AM_REGADDR(CTIMER,TMR2),
92     AM_REGADDR(CTIMER,TMR3), AM_REGADDR(CTIMER,TMR4), AM_REGADDR(CTIMER,TMR5),
93     AM_REGADDR(CTIMER,TMR6), AM_REGADDR(CTIMER,TMR7)
94 };
95 
96 //
97 // Given the 5-bit clock source value as an index, this lookup table returns the
98 // number of LSbs to be masked off for the back2back reads.
99 //
100 static const uint8_t
101 g_ui8TmrClkSrcMask[32] =  // 5-bit field = 32 table entries
102 {
103     0x0F,       //  0: CTIMER_CTRL0_TMRA0CLK_TMRPIN     (CLK_PIN)
104     0x0F,       //  1: CTIMER_CTRL0_TMRA0CLK_HFRC_DIV4  (HFRC_12MHZ)
105     0x03,       //  2: CTIMER_CTRL0_TMRA0CLK_HFRC_DIV16 (HFRC_3MHZ)
106     0x01,       //  3: CTIMER_CTRL0_TMRA0CLK_HFRC_DIV256  (HFRC_187_5KHZ)
107     0x01,       //  4: CTIMER_CTRL0_TMRA0CLK_HFRC_DIV1024 (HFRC_47KHZ)
108     0x01,       //  5: CTIMER_CTRL0_TMRA0CLK_HFRC_DIV4K (HFRC_12KHZ)
109     0x00,       //  6: CTIMER_CTRL0_TMRA0CLK_XT         (XT_32_768KHZ)
110     0x00,       //  7: CTIMER_CTRL0_TMRA0CLK_XT_DIV2    (XT_16_384KHZ)
111     0x00,       //  8: CTIMER_CTRL0_TMRA0CLK_XT_DIV16   (XT_2_048KHZ)
112     0x00,       //  9: CTIMER_CTRL0_TMRA0CLK_XT_DIV128  (XT_256HZ)
113     0x00,       // 10: CTIMER_CTRL0_TMRA0CLK_LFRC_DIV2  (LFRC_512HZ)
114     0x00,       // 11: CTIMER_CTRL0_TMRA0CLK_LFRC_DIV32 (LFRC_32HZ)
115     0x00,       // 12: CTIMER_CTRL0_TMRA0CLK_LFRC_DIV1K (LFRC_1HZ)
116     0x00,       // 13: CTIMER_CTRL0_TMRA0CLK_LFRC       (LFRC_1_16HZ)
117     0x00,       // 14: CTIMER_CTRL0_TMRA0CLK_RTC_100HZ  (RTC_100HZ)
118     0x00,       // 15: CTIMER_CTRL0_TMRA0CLK_HCLK_DIV4  (HCLK_DIV4)
119     0x00,       // 16: CTIMER_CTRL0_TMRA0CLK_XT_DIV4    (XT_DIV4)
120     0x00,       // 17: CTIMER_CTRL0_TMRA0CLK_XT_DIV8    (XT_DIV8)
121     0x00,       // 18: CTIMER_CTRL0_TMRA0CLK_XT_DIV32   (XT_DIV32)
122     0x00,       // 19: Reserved
123     0x0F,       // 20: CTIMERxx OUT
124     0x0F,       // 21:  "
125     0x0F,       // 22:  "
126     0x0F,       // 23:  "
127     0x0F,       // 24:  "
128     0x0F,       // 25:  "
129     0x0F,       // 26:  "
130     0x0F,       // 27:  "
131     0x0F,       // 28:  "
132     0x00,       // 29: CTIMER_CTRL0_TMRA0CLK_BUCKBLE
133     0x00,       // 30: CTIMER_CTRL0_TMRA0CLK_BUCKB
134     0x00        // 31: CTIMER_CTRL0_TMRA0CLK_BUCKA
135 };
136 
137 //*****************************************************************************
138 //
139 // Lookup tables used by am_hal_ctimer_output_config().
140 //
141 //  CTx_tbl[] relates the padnum and pad funcsel based on a given CTx.
142 //  Valid pads for CTx are: 4-7, 11-13, 18-19, 22-33, 35, 37, 39, 42-49.
143 //
144 //  outcfg_tbl[] contains attributes of the 4 output signal types for each
145 //  of the 32 CTx signals. Therefore it is indexed by CTnumber 0-31.
146 //  This table provides only the non-common OUTCFG attributes (2-5, other
147 //  settings are shown below).
148 //  OUTCFG 0 = Force output to 0.
149 //  OUTCFG 1 = Force output to 1.
150 //  OUTCFG 6 = A6OUT2.
151 //  OUTCFG 7 = A7OUT2.
152 //
153 //*****************************************************************************
154 #define CTXPADNUM(ctx, ctx_idx)  ((CTx_tbl[ctx][ctx_idx] >> 0) & 0x7f)
155 #define CTXPADFNC(ctx, ctx_idx)  ((CTx_tbl[ctx][ctx_idx] >> 8) & 0x7)
156 #define CTX(pad, fn)    ((fn << 8) | (pad << 0))
157 
158 static const uint16_t CTx_tbl[32][2] =
159 {
160     {CTX(12,2), CTX(50,2)},     // 0
161     {CTX(25,2), CTX(51,2)},     // 1
162     {CTX(13,2), CTX(52,2)},     // 2
163     {CTX(26,2), CTX(53,2)},     // 3
164     {CTX(18,2), CTX(54,2)},     // 4
165     {CTX(27,2), CTX(55,2)},     // 5
166     {CTX(19,2), CTX(56,2)},     // 6
167     {CTX(28,2), CTX(57,2)},     // 7
168     {CTX( 5,7), CTX(58,2)},     // 8
169     {CTX(29,2), CTX(59,2)},     // 9
170     {CTX( 6,5), CTX(60,2)},     // 10
171     {CTX(30,2), CTX(61,2)},     // 11
172     {CTX(22,2), CTX(62,2)},     // 12
173     {CTX(31,2), CTX(63,2)},     // 13
174     {CTX(23,2), CTX(64,2)},     // 14
175     {CTX(32,2), CTX(65,2)},     // 15
176     {CTX(42,2), CTX(66,2)},     // 16
177     {CTX( 4,6), CTX(67,2)},     // 17
178     {CTX(43,2), CTX(68,2)},     // 18
179     {CTX( 7,7), CTX(69,2)},     // 19
180     {CTX(44,2), CTX(70,2)},     // 20
181     {CTX(24,5), CTX(71,2)},     // 21
182     {CTX(45,2), CTX(72,2)},     // 22
183     {CTX(33,6), CTX(73,2)},     // 23
184     {CTX(46,2), 0xFFFF},        // 24
185     {CTX(39,2), 0xFFFF},        // 25
186     {CTX(47,2), 0xFFFF},        // 26
187     {CTX(35,5), 0xFFFF},        // 27
188     {CTX(48,2), 0xFFFF},        // 28
189     {CTX(37,7), 0xFFFF},        // 29
190     {CTX(49,2), 0xFFFF},        // 30
191     {CTX(11,2), 0xFFFF}         // 31
192 };
193 
194 #define OUTC(timB,timN,N2)      ((N2 << 4) | (timB << 3) | (timN << 0))
195 #define OUTCTIMN(ctx,n)         (outcfg_tbl[ctx][n] & (0x7 << 0))
196 #define OUTCTIMB(ctx,n)         (outcfg_tbl[ctx][n] & (0x1 << 3))
197 #define OUTCO2(ctx,n)           (outcfg_tbl[ctx][n] & (0x1 << 4))
198 static const uint8_t outcfg_tbl[32][4] =
199 {
200     {OUTC(0,0,0), OUTC(1,2,1), OUTC(0,5,1), OUTC(0,6,0)},     // CTX0:  A0OUT,  B2OUT2, A5OUT2, A6OUT
201     {OUTC(0,0,1), OUTC(0,0,0), OUTC(0,5,0), OUTC(1,7,1)},     // CTX1:  A0OUT2, A0OUT,  A5OUT,  B7OUT2
202     {OUTC(1,0,0), OUTC(1,1,1), OUTC(1,6,1), OUTC(0,7,0)},     // CTX2:  B0OUT,  B1OUT2, B6OUT2, A7OUT
203     {OUTC(1,0,1), OUTC(1,0,0), OUTC(0,1,0), OUTC(0,6,0)},     // CTX3:  B0OUT2, B0OUT,  A1OUT,  A6OUT
204     {OUTC(0,1,0), OUTC(0,2,1), OUTC(0,5,1), OUTC(1,5,0)},     // CTX4:  A1OUT,  A2OUT2, A5OUT2, B5OUT
205     {OUTC(0,1,1), OUTC(0,1,0), OUTC(1,6,0), OUTC(0,7,0)},     // CTX5:  A1OUT2, A1OUT,  B6OUT,  A7OUT
206     {OUTC(1,1,0), OUTC(0,1,0), OUTC(1,5,1), OUTC(1,7,0)},     // CTX6:  B1OUT,  A1OUT,  B5OUT2, B7OUT
207     {OUTC(1,1,1), OUTC(1,1,0), OUTC(1,5,0), OUTC(0,7,0)},     // CTX7:  B1OUT2, B1OUT,  B5OUT,  A7OUT
208     {OUTC(0,2,0), OUTC(0,3,1), OUTC(0,4,1), OUTC(1,6,0)},     // CTX8:  A2OUT,  A3OUT2, A4OUT2, B6OUT
209     {OUTC(0,2,1), OUTC(0,2,0), OUTC(0,4,0), OUTC(1,0,0)},     // CTX9:  A2OUT2, A2OUT,  A4OUT,  B0OUT
210     {OUTC(1,2,0), OUTC(1,3,1), OUTC(1,4,1), OUTC(0,6,0)},     // CTX10: B2OUT,  B3OUT2, B4OUT2, A6OUT
211     {OUTC(1,2,1), OUTC(1,2,0), OUTC(1,4,0), OUTC(1,5,1)},     // CTX11: B2OUT2, B2OUT,  B4OUT,  B5OUT2
212     {OUTC(0,3,0), OUTC(1,1,0), OUTC(1,0,1), OUTC(1,6,1)},     // CTX12: A3OUT,  B1OUT,  B0OUT2, B6OUT2
213     {OUTC(0,3,1), OUTC(0,3,0), OUTC(0,6,0), OUTC(1,4,1)},     // CTX13: A3OUT2, A3OUT,  A6OUT,  B4OUT2
214     {OUTC(1,3,0), OUTC(1,1,0), OUTC(1,7,1), OUTC(0,7,0)},     // CTX14: B3OUT,  B1OUT,  B7OUT2, A7OUT
215     {OUTC(1,3,1), OUTC(1,3,0), OUTC(0,7,0), OUTC(0,4,1)},     // CTX15: B3OUT2, B3OUT,  A7OUT,  A4OUT2
216     {OUTC(0,4,0), OUTC(0,0,0), OUTC(0,0,1), OUTC(1,3,1)},     // CTX16: A4OUT,  A0OUT,  A0OUT2, B3OUT2
217     {OUTC(0,4,1), OUTC(1,7,0), OUTC(0,4,0), OUTC(0,1,1)},     // CTX17: A4OUT2, B7OUT,  A4OUT,  A1OUT2
218     {OUTC(1,4,0), OUTC(1,0,0), OUTC(0,0,0), OUTC(0,3,1)},     // CTX18: B4OUT,  B0OUT,  A0OUT,  A3OUT2
219     {OUTC(1,4,1), OUTC(0,2,0), OUTC(1,4,0), OUTC(1,1,1)},     // CTX19: B4OUT2, A2OUT,  B4OUT,  B1OUT2
220     {OUTC(0,5,0), OUTC(0,1,0), OUTC(0,1,1), OUTC(1,2,1)},     // CTX20: A5OUT,  A1OUT,  A1OUT2, B2OUT2
221     {OUTC(0,5,1), OUTC(0,1,0), OUTC(1,5,0), OUTC(0,0,1)},     // CTX21: A5OUT2, A1OUT,  B5OUT,  A0OUT2
222     {OUTC(1,5,0), OUTC(0,6,0), OUTC(0,1,0), OUTC(0,2,1)},     // CTX22: B5OUT,  A6OUT,  A1OUT,  A2OUT2
223     {OUTC(1,5,1), OUTC(0,7,0), OUTC(0,5,0), OUTC(1,0,1)},     // CTX23: B5OUT2, A7OUT,  A5OUT,  B0OUT2
224     {OUTC(0,6,0), OUTC(0,2,0), OUTC(0,1,0), OUTC(1,1,1)},     // CTX24: A6OUT,  A2OUT,  A1OUT,  B1OUT2
225     {OUTC(1,4,1), OUTC(1,2,0), OUTC(0,6,0), OUTC(0,2,1)},     // CTX25: B4OUT2, B2OUT,  A6OUT,  A2OUT2
226     {OUTC(1,6,0), OUTC(1,2,0), OUTC(0,5,0), OUTC(0,1,1)},     // CTX26: B6OUT,  B2OUT,  A5OUT,  A1OUT2
227     {OUTC(1,6,1), OUTC(0,1,0), OUTC(1,6,0), OUTC(1,2,1)},     // CTX27: B6OUT2, A1OUT,  B6OUT,  B2OUT2
228     {OUTC(0,7,0), OUTC(0,3,0), OUTC(0,5,1), OUTC(1,0,1)},     // CTX28: A7OUT,  A3OUT,  A5OUT2, B0OUT2
229     {OUTC(1,5,1), OUTC(0,1,0), OUTC(0,7,0), OUTC(0,3,1)},     // CTX29: B5OUT2, A1OUT,  A7OUT,  A3OUT2
230     {OUTC(1,7,0), OUTC(1,3,0), OUTC(0,4,1), OUTC(0,0,1)},     // CTX30: B7OUT,  B3OUT,  A4OUT2, A0OUT2
231     {OUTC(1,7,1), OUTC(0,6,0), OUTC(1,7,0), OUTC(1,3,1)},     // CTX31: B7OUT2, A6OUT,  B7OUT,  B3OUT2
232 };
233 
234 
235 
236 //*****************************************************************************
237 //
238 // ctimer_clr()
239 //
240 // For the appropriate ctimer configuration register, set the CLR bit high
241 // in the appropriate timer segment (A, B, or both).
242 //
243 // The CLR bit is required to be set in order to completely initialize
244 // the timer at config time.  The timer clear occurs asynchrnously during the
245 // low-to-high transition of the CLR bit.
246 //
247 // This function only sets the CLR bit.  It is assumed that the actual timer
248 // configuration will occur following the call to this function and will clear
249 // the CLR bit at that time.
250 //
251 //*****************************************************************************
252 static void
ctimer_clr(uint32_t ui32TimerNumber,uint32_t ui32TimerSegment)253 ctimer_clr(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
254 {
255     //
256     // Find the address of the correct control register and set the CLR bit
257     // for the timer segment in that control register.
258     //
259     volatile uint32_t *pui32ConfigReg =
260         (uint32_t*)CTIMERADDRn(CTIMER, ui32TimerNumber, CTRL0);
261 
262     AM_CRITICAL_BEGIN
263     AM_REGVAL(pui32ConfigReg) |= (ui32TimerSegment &
264                                   (CTIMER_CTRL0_TMRA0CLR_Msk |
265                                    CTIMER_CTRL0_TMRB0CLR_Msk));
266     AM_CRITICAL_END
267 
268 } // ctimer_clr()
269 
270 //*****************************************************************************
271 //
272 // @brief Convenience function for responding to CTimer interrupts.
273 //
274 // @param ui32Status is the interrupt status as returned by
275 // am_hal_ctimer_int_status_get()
276 //
277 // This function may be called from am_ctimer_isr() to read the status of
278 // the CTimer interrupts, determine which source caused the most recent
279 // interrupt, and call an interrupt handler function to respond. The interrupt
280 // handler to be called must be first registered with the
281 // am_hal_ctimer_int_register() function.
282 //
283 // In the event that multiple sources are active, the corresponding
284 // interrupt handlers will be called in numerical order based on interrupt def.
285 //
286 //*****************************************************************************
287 void
am_hal_ctimer_int_service(uint32_t ui32Status)288 am_hal_ctimer_int_service(uint32_t ui32Status)
289 {
290 
291     am_hal_ctimer_handler_t pfnHandler;
292 
293     while ( ui32Status )
294     {
295         uint32_t ui32Clz;
296         //
297         // Pick one of any remaining active interrupt bits
298         //
299 #ifdef __IAR_SYSTEMS_ICC__
300         ui32Clz = __CLZ(ui32Status);
301 #else
302         ui32Clz = __builtin_clz(ui32Status);
303 #endif
304 
305         //
306         // Turn off the bit we picked in the working copy
307         //
308         ui32Status &= ~(0x80000000 >> ui32Clz);
309 
310         //
311         // Check the bit handler table to see if there is an interrupt handler
312         // registered for this particular bit.
313         //
314         pfnHandler = g_am_hal_ctimer_ppfnHandlers[31 - ui32Clz];
315         if ( pfnHandler )
316         {
317             //
318             // If we found an interrupt handler routine, call it now.
319             //
320             pfnHandler();
321         }
322     }
323 
324 } // am_hal_ctimer_int_service()
325 
326 //*****************************************************************************
327 //
328 // @brief Register an interrupt handler for CTimer.
329 //
330 // @param ui32Interrupt - interrupt number to assign this interrupt handler to.
331 // @param pfnHandler - Function to call when this interrupt is received.
332 //
333 // This function allows the caller to specify a function that should be called
334 // any time a Ctimer interrupt is received. Registering an
335 // interrupt handler using this function adds the function pointer to an array
336 // in SRAM. This interrupt handler will be called by am_hal_ctimer_int_service()
337 // whenever the ui32Status parameter indicates that the corresponding interrupt.
338 //
339 // To remove an interrupt handler that has already been registered, the
340 // pfnHandler parameter may be set to zero.
341 //
342 // @note This function will not have any effect unless the
343 // am_hal_ctimer_int_service() function is being used.
344 //
345 //*****************************************************************************
346 void
am_hal_ctimer_int_register(uint32_t ui32Interrupt,am_hal_ctimer_handler_t pfnHandler)347 am_hal_ctimer_int_register(uint32_t ui32Interrupt,
348                            am_hal_ctimer_handler_t pfnHandler)
349 {
350     uint32_t intIdx = 0;
351 
352     //
353     // Check to make sure the interrupt number is valid. (Debug builds only)
354     //
355     switch (ui32Interrupt)
356     {
357         case CTIMER_INTEN_CTMRA0C0INT_Msk:
358             intIdx = CTIMER_INTEN_CTMRA0C0INT_Pos;
359             break;
360 
361         case CTIMER_INTEN_CTMRB0C0INT_Msk:
362             intIdx = CTIMER_INTEN_CTMRB0C0INT_Pos;
363             break;
364 
365         case CTIMER_INTEN_CTMRA1C0INT_Msk:
366             intIdx = CTIMER_INTEN_CTMRA1C0INT_Pos;
367             break;
368 
369         case CTIMER_INTEN_CTMRB1C0INT_Msk:
370             intIdx = CTIMER_INTEN_CTMRB1C0INT_Pos;
371             break;
372 
373         case CTIMER_INTEN_CTMRA2C0INT_Msk:
374             intIdx = CTIMER_INTEN_CTMRA2C0INT_Pos;
375             break;
376 
377         case CTIMER_INTEN_CTMRB2C0INT_Msk:
378             intIdx = CTIMER_INTEN_CTMRB2C0INT_Pos;
379             break;
380 
381         case CTIMER_INTEN_CTMRA3C0INT_Msk:
382             intIdx = CTIMER_INTEN_CTMRA3C0INT_Pos;
383             break;
384 
385         case CTIMER_INTEN_CTMRB3C0INT_Msk:
386             intIdx = CTIMER_INTEN_CTMRB3C0INT_Pos;
387             break;
388 
389         case CTIMER_INTEN_CTMRA4C0INT_Msk:
390             intIdx = CTIMER_INTEN_CTMRA4C0INT_Pos;
391             break;
392 
393         case CTIMER_INTEN_CTMRB4C0INT_Msk:
394             intIdx = CTIMER_INTEN_CTMRB4C0INT_Pos;
395             break;
396 
397         case CTIMER_INTEN_CTMRA5C0INT_Msk:
398             intIdx = CTIMER_INTEN_CTMRA5C0INT_Pos;
399             break;
400 
401         case CTIMER_INTEN_CTMRB5C0INT_Msk:
402             intIdx = CTIMER_INTEN_CTMRB5C0INT_Pos;
403             break;
404 
405         case CTIMER_INTEN_CTMRA6C0INT_Msk:
406             intIdx = CTIMER_INTEN_CTMRA6C0INT_Pos;
407             break;
408 
409         case CTIMER_INTEN_CTMRB6C0INT_Msk:
410             intIdx = CTIMER_INTEN_CTMRB6C0INT_Pos;
411             break;
412 
413         case CTIMER_INTEN_CTMRA7C0INT_Msk:
414             intIdx = CTIMER_INTEN_CTMRA7C0INT_Pos;
415             break;
416 
417         case CTIMER_INTEN_CTMRB7C0INT_Msk:
418             intIdx = CTIMER_INTEN_CTMRB7C0INT_Pos;
419             break;
420 
421         // Counter/Timer A0 interrupt based on COMPR1.
422         case CTIMER_INTEN_CTMRA0C1INT_Msk:
423             intIdx = CTIMER_INTEN_CTMRA0C1INT_Pos;
424             break;
425 
426         case CTIMER_INTEN_CTMRB0C1INT_Msk:
427             intIdx = CTIMER_INTEN_CTMRB0C1INT_Pos;
428             break;
429 
430         case CTIMER_INTEN_CTMRA1C1INT_Msk:
431             intIdx = CTIMER_INTEN_CTMRA1C1INT_Pos;
432             break;
433 
434         case CTIMER_INTEN_CTMRB1C1INT_Msk:
435             intIdx = CTIMER_INTEN_CTMRB1C1INT_Pos;
436             break;
437 
438         case CTIMER_INTEN_CTMRA2C1INT_Msk:
439             intIdx = CTIMER_INTEN_CTMRA2C1INT_Pos;
440             break;
441 
442         case CTIMER_INTEN_CTMRB2C1INT_Msk:
443             intIdx = CTIMER_INTEN_CTMRB2C1INT_Pos;
444             break;
445 
446         case CTIMER_INTEN_CTMRA3C1INT_Msk:
447             intIdx = CTIMER_INTEN_CTMRA3C1INT_Pos;
448             break;
449 
450         case CTIMER_INTEN_CTMRB3C1INT_Msk:
451             intIdx = CTIMER_INTEN_CTMRB3C1INT_Pos;
452             break;
453 
454         case CTIMER_INTEN_CTMRA4C1INT_Msk:
455             intIdx = CTIMER_INTEN_CTMRA4C1INT_Pos;
456             break;
457 
458         case CTIMER_INTEN_CTMRB4C1INT_Msk:
459             intIdx = CTIMER_INTEN_CTMRB4C1INT_Pos;
460             break;
461         case CTIMER_INTEN_CTMRA5C1INT_Msk:
462             intIdx = CTIMER_INTEN_CTMRA5C1INT_Pos;
463             break;
464 
465         case CTIMER_INTEN_CTMRB5C1INT_Msk:
466             intIdx = CTIMER_INTEN_CTMRB5C1INT_Pos;
467             break;
468         case CTIMER_INTEN_CTMRA6C1INT_Msk:
469             intIdx = CTIMER_INTEN_CTMRA6C1INT_Pos;
470             break;
471 
472         case CTIMER_INTEN_CTMRB6C1INT_Msk:
473             intIdx = CTIMER_INTEN_CTMRB6C1INT_Pos;
474             break;
475         case CTIMER_INTEN_CTMRA7C1INT_Msk:
476             intIdx = CTIMER_INTEN_CTMRA7C1INT_Pos;
477             break;
478 
479         case CTIMER_INTEN_CTMRB7C1INT_Msk:
480             intIdx = CTIMER_INTEN_CTMRB7C1INT_Pos;
481             break;
482 
483         default:
484             am_hal_debug_assert_msg(false, "CTimer interrupt number out of range.");
485     }
486 
487     g_am_hal_ctimer_ppfnHandlers[intIdx] = pfnHandler;
488 
489 } // am_hal_ctimer_int_register()
490 
491 //*****************************************************************************
492 //
493 // @brief Set up the counter/timer.
494 //
495 // @param ui32ConfigVal is the value to set the global enable register.
496 //
497 // This function sets the global enable register inside a critical section.
498 //
499 //*****************************************************************************
500 void
am_hal_ctimer_globen(uint32_t ui32ConfigVal)501 am_hal_ctimer_globen(uint32_t ui32ConfigVal)
502 {
503     uint32_t *pui32ConfigReg;
504 
505     //
506     // Find the correct register to write.
507     //
508     pui32ConfigReg = (uint32_t *)(&CTIMERn(0)->GLOBEN);
509 
510     //
511     // Begin critical section while config registers are read and modified.
512     //
513     AM_CRITICAL_BEGIN
514 
515     //
516     // Write our configuration value.
517     //
518     AM_REGVAL(pui32ConfigReg) = ui32ConfigVal;
519 
520     //
521     // Done with critical section.
522     //
523     AM_CRITICAL_END
524 
525 } // am_hal_ctimer_globen()
526 
527 //*****************************************************************************
528 //
529 // @brief Set up the counter/timer.
530 //
531 // @param ui32TimerNumber is the number of the Timer that should be
532 // configured.
533 //
534 // @param psConfig is a pointer to a structure that holds important settings
535 // for the timer.
536 //
537 // This function should be used to perform the initial set-up of the
538 // counter-timer.
539 //
540 // @note This function is deprecated and will eventually be replaced by
541 // am_hal_ctimer_config_single(), which performs the same configuration
542 // without requiring a structure and without assuming both timer halves
543 // are being configured.
544 // Please use am_hal_ctimer_config_single() for new development.
545 //
546 // @note In order to initialize the given timer into a known state, this
547 // function asserts the CLR configuration bit. The CLR bit will be deasserted
548 // with the write of the configuration register. The CLR bit is also
549 // intentionally deasserted with a call to am_hal_ctimer_start().
550 //
551 //
552 //*****************************************************************************
553 void
am_hal_ctimer_config(uint32_t ui32TimerNumber,am_hal_ctimer_config_t * psConfig)554 am_hal_ctimer_config(uint32_t ui32TimerNumber,
555                      am_hal_ctimer_config_t *psConfig)
556 {
557     uint32_t ui32ConfigVal;
558     uint32_t ui32Seg, ui32ClkSrc;
559     uint32_t *pui32ConfigReg;
560 
561     //
562     // Make sure the timer is completely initialized on configuration by
563     // setting the CLR bit.
564     //
565     ctimer_clr(ui32TimerNumber, AM_HAL_CTIMER_BOTH);
566 
567     //
568     // Start preparing the configuration word for this timer. The configuration
569     // values for Timer A and Timer B provided in the config structure should
570     // match the register definitions already, so we will mostly just need to
571     // OR them together.
572     //
573     ui32ConfigVal = ( (psConfig->ui32TimerAConfig)  |
574                       (psConfig->ui32TimerBConfig << 16) );
575 
576     //
577     // OR in the Link bit if the timers need to be linked.
578     //
579     ui32ConfigVal |= psConfig->ui32Link ? AM_HAL_CTIMER_LINK : 0;
580 
581     //
582     // Find the correct register to write.
583     //
584     pui32ConfigReg = (uint32_t*)CTIMERADDRn(CTIMER, ui32TimerNumber, CTRL0);
585 
586     //
587     // Begin critical section while config registers are read and modified.
588     //
589     AM_CRITICAL_BEGIN
590 
591     //
592     // Write our configuration value.
593     //
594     AM_REGVAL(pui32ConfigReg) = ui32ConfigVal;
595 
596     //
597     // Done with critical section.
598     //
599     AM_CRITICAL_END
600 
601     //
602     // Save the clock source for this timer.
603     //
604     if ( ( psConfig->ui32TimerAConfig != 0 )  ||  psConfig->ui32Link )
605     {
606         ui32Seg = 0;
607         ui32ClkSrc = _FLD2VAL(CTIMER_CTRL0_TMRA0CLK, psConfig->ui32TimerAConfig);
608     }
609     else if ( psConfig->ui32TimerBConfig != 0)
610     {
611         ui32Seg = 1;
612         ui32ClkSrc = _FLD2VAL(CTIMER_CTRL0_TMRA0CLK, psConfig->ui32TimerBConfig);
613     }
614     else
615     {
616         return;
617     }
618 
619     //
620     // Save the clock source for this timer/segment.
621     //
622     g_ui8ClkSrc[ui32TimerNumber][ui32Seg] = ui32ClkSrc;
623 
624 } // am_hal_ctimer_config()
625 
626 //*****************************************************************************
627 //
628 // @brief Set up the counter/timer.
629 //
630 // @param ui32TimerNumber is the number of the Timer that should be
631 // configured.
632 //
633 // @param ui32TimerSegment specifies which segment of the timer should be
634 // enabled.
635 //
636 // @param ui32ConfigVal specifies the configuration options for the selected
637 // timer.
638 //
639 // This function should be used to perform the initial set-up of the
640 // counter-timer. It can be used to configure either a 16-bit timer (A or B) or a
641 // 32-bit timer using the BOTH option.
642 //
643 //
644 // Valid values for ui32TimerSegment are:
645 //
646 //     AM_HAL_CTIMER_TIMERA
647 //     AM_HAL_CTIMER_TIMERB
648 //     AM_HAL_CTIMER_BOTH
649 //
650 // The timer's clock source, mode, interrupt, and external pin behavior are
651 // all controlled through the \e ui32Configval parameter. The valid options
652 // for ui32ConfigVal include any ORed together combination of the following:
653 //
654 // Clock configuration macros:
655 //
656 //     AM_HAL_CTIMER_HFRC_24MHZ
657 //     AM_HAL_CTIMER_LFRC_512HZ
658 //     ... etc. (See am_hal_ctimer.h for the full set of options.)
659 //
660 // Mode selection macros:
661 //
662 //     AM_HAL_CTIMER_FN_ONCE
663 //     AM_HAL_CTIMER_FN_REPEAT
664 //     AM_HAL_CTIMER_FN_PWM_ONCE
665 //     AM_HAL_CTIMER_FN_PWM_REPEAT
666 //     AM_HAL_CTIMER_FN_CONTINUOUS
667 //
668 // Interrupt control:
669 //
670 //     AM_HAL_CTIMER_INT_ENABLE
671 //
672 // Pin control:
673 //
674 //     AM_HAL_CTIMER_PIN_ENABLE
675 //     AM_HAL_CTIMER_PIN_INVERT
676 //
677 // ADC trigger (Timer 3 only):
678 //
679 //     AM_HAL_CTIMER_ADC_TRIG
680 //
681 //
682 // @note In order to initialize the given timer into a known state, this
683 // function asserts the CLR configuration bit. The CLR bit will be deasserted
684 // with the write of the configuration register. The CLR bit is also
685 // intentionally deasserted with a call to am_hal_ctimer_start().
686 //
687 //
688 //*****************************************************************************
689 void
am_hal_ctimer_config_single(uint32_t ui32TimerNumber,uint32_t ui32TimerSegment,uint32_t ui32ConfigVal)690 am_hal_ctimer_config_single(uint32_t ui32TimerNumber,
691                             uint32_t ui32TimerSegment,
692                             uint32_t ui32ConfigVal)
693 {
694     volatile uint32_t *pui32ConfigReg;
695     uint32_t ui32Seg, ui32ClkSrc;
696 
697     //
698     // Make sure the timer is completely initialized on configuration by
699     // setting the CLR bit.
700     //
701     ctimer_clr(ui32TimerNumber, ui32TimerSegment);
702 
703     //
704     // Find the correct register to write based on the timer number.
705     //
706     pui32ConfigReg = (uint32_t*)CTIMERADDRn(CTIMER, ui32TimerNumber, CTRL0);
707 
708     //
709     // Begin critical section while config registers are read and modified.
710     //
711     AM_CRITICAL_BEGIN
712     uint32_t ui32WriteVal;
713 
714     //
715     // Save the value that's already in the register.
716     //
717     ui32WriteVal = AM_REGVAL(pui32ConfigReg);
718 
719     //
720     // If we're working with TIMERB, we need to shift our configuration value
721     // up by 16 bits.
722     //
723     if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
724     {
725         ui32ConfigVal = ((ui32ConfigVal & 0xFFFF) << 16);
726     }
727 
728     //
729     // Replace part of the saved register value with the configuration value
730     // from the caller.
731     //
732     ui32WriteVal = (ui32WriteVal & ~(ui32TimerSegment)) | ui32ConfigVal;
733 
734     //
735     // If we're configuring both timers, we need to set the "link" bit.
736     //
737     if ( ui32TimerSegment == AM_HAL_CTIMER_BOTH )
738     {
739         ui32WriteVal |= AM_HAL_CTIMER_LINK;
740     }
741 
742     //
743     // Write our completed configuration value.
744     //
745     AM_REGVAL(pui32ConfigReg) = ui32WriteVal;
746 
747     //
748     // Done with critical section.
749     //
750     AM_CRITICAL_END
751 
752     //
753     // Save the clock source for this timer.
754     //
755     switch ( ui32TimerSegment )
756     {
757         case AM_HAL_CTIMER_TIMERA:
758         case AM_HAL_CTIMER_BOTH:
759             ui32Seg = 0;
760             break;
761         case AM_HAL_CTIMER_TIMERB:
762             ui32Seg = 1;
763             break;
764         default:
765             return;
766     }
767 
768     ui32ClkSrc = _FLD2VAL(CTIMER_CTRL0_TMRA0CLK, ui32ConfigVal);
769 
770     //
771     // Save the clock source for this timer/segment.
772     //
773     g_ui8ClkSrc[ui32TimerNumber][ui32Seg] = (uint8_t)ui32ClkSrc;
774 
775 } // am_hal_ctimer_config_single()
776 
777 //*****************************************************************************
778 //
779 // @brief Set up the counter/timer trigger.
780 //
781 // @param ui32TimerNumber is the number of the Timer that should be
782 // configured.
783 //
784 // @param ui32TimerSegment specifies which segment of the timer should be
785 // enabled.
786 //
787 // @param ui32ConfigVal specifies the configuration options for the selected
788 // timer trigger AUXn register.
789 //
790 // This function should be used to perform the configuration of the trigger
791 // for the counter-timer (A or B).
792 //
793 // Valid values for ui32TimerSegment are:
794 //
795 //     AM_HAL_CTIMER_TIMERA
796 //     AM_HAL_CTIMER_TIMERB
797 //
798 // @note In order to initialize the given timer into a known state, this
799 // function asserts the CLR configuration bit. The CLR bit will be deasserted
800 // with the write of the configuration register. The CLR bit is also
801 // intentionally deasserted with a call to am_hal_ctimer_start().
802 //
803 //
804 //*****************************************************************************
805 void
am_hal_ctimer_config_trigger(uint32_t ui32TimerNumber,uint32_t ui32TimerSegment,uint32_t ui32ConfigVal)806 am_hal_ctimer_config_trigger(uint32_t ui32TimerNumber,
807                              uint32_t ui32TimerSegment,
808                              uint32_t ui32ConfigVal)
809 {
810     volatile uint32_t *pui32ConfigReg;
811 
812     //
813     // Find the correct register to write based on the timer number.
814     //
815     pui32ConfigReg = (uint32_t*)CTIMERADDRn(CTIMER, ui32TimerNumber, AUX0);
816 
817     //
818     // Begin critical section while config registers are read and modified.
819     //
820     AM_CRITICAL_BEGIN
821     uint32_t ui32WriteVal;
822 
823     //
824     // Save the value that's already in the register.
825     //
826     ui32WriteVal = AM_REGVAL(pui32ConfigReg);
827 
828     //
829     // If we're working with TIMERB, we need to shift our configuration value
830     // up by 16 bits.
831     //
832 
833     if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
834     {
835         ui32ConfigVal = ((ui32ConfigVal & 0xFFFF) << 16);
836     }
837 
838     //
839     // Replace part of the saved register value with the configuration value
840     // from the caller.
841     //
842     ui32WriteVal = (ui32WriteVal & ~(ui32TimerSegment)) | ui32ConfigVal;
843 
844     //
845     // Write our completed configuration value.
846     //
847     AM_REGVAL(pui32ConfigReg) = ui32WriteVal;
848 
849     //
850     // Done with critical section.
851     //
852     AM_CRITICAL_END
853 
854 } // am_hal_ctimer_config_trigger()
855 
856 //*****************************************************************************
857 //
858 // @brief Start a timer
859 //
860 // @param ui32TimerNumber is the number of the timer to enable
861 //
862 // @param ui32TimerSegment specifies which segment of the timer should be
863 // enabled.  Valid values for ui32TimerSegment are:
864 //     AM_HAL_CTIMER_TIMERA
865 //     AM_HAL_CTIMER_TIMERB
866 //     AM_HAL_CTIMER_BOTH
867 //
868 // This function will enable a timer to begin incrementing. The \e
869 // ui32TimerNumber parameter selects the timer that should be enabled, for
870 // example, a 0 would target TIMER0. The \e ui32TimerSegment parameter allows
871 // the caller to individually select a segment within a timer to be enabled,
872 // such as TIMER0A, TIMER0B, or both.
873 //
874 //*****************************************************************************
875 void
am_hal_ctimer_start(uint32_t ui32TimerNumber,uint32_t ui32TimerSegment)876 am_hal_ctimer_start(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
877 {
878     uint32_t ui32Seg, ui32ClkSrc;
879     volatile uint32_t *pui32ConfigReg;
880 
881     //
882     // Find the correct control register.
883     //
884     pui32ConfigReg = (uint32_t*)CTIMERADDRn(CTIMER, ui32TimerNumber, CTRL0);
885 
886     //
887     // Begin critical section while config registers are read and modified.
888     //
889     AM_CRITICAL_BEGIN
890 
891     //
892     // Read the current value.
893     //
894     uint32_t ui32ConfigVal = *pui32ConfigReg;
895 
896     //
897     // Clear out the "clear" bit.
898     //
899     ui32ConfigVal &= ~(ui32TimerSegment & (CTIMER_CTRL0_TMRA0CLR_Msk |
900                                            CTIMER_CTRL0_TMRB0CLR_Msk));
901 
902     //
903     // Set the "enable bit"
904     //
905     ui32ConfigVal |= (ui32TimerSegment & (CTIMER_CTRL0_TMRA0EN_Msk |
906                                           CTIMER_CTRL0_TMRB0EN_Msk));
907 
908     //
909     // While we already have the CTRL reg, get and save the CLKSRC.
910     //
911     if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
912     {
913         ui32Seg = 1;
914         ui32ClkSrc = _FLD2VAL(CTIMER_CTRL0_TMRB0CLK, ui32ConfigVal);
915     }
916     else
917     {
918         ui32Seg = 0;
919         ui32ClkSrc = _FLD2VAL(CTIMER_CTRL0_TMRA0CLK, ui32ConfigVal);
920     }
921 
922     //
923     // Save the clock source for this timer/segment.
924     //
925     g_ui8ClkSrc[ui32TimerNumber][ui32Seg] = ui32ClkSrc;
926 
927     //
928     // Write the configuration to start the timer.
929     //
930     AM_REGVAL(pui32ConfigReg) = ui32ConfigVal;
931 
932     //
933     // Done with critical section.
934     //
935     AM_CRITICAL_END
936 
937 } // am_hal_ctimer_start()
938 
939 //*****************************************************************************
940 //
941 // @brief Stop a timer
942 //
943 // @param ui32TimerNumber is the number of the timer to disable.
944 //
945 // @param ui32TimerSegment specifies which segment of the timer should be
946 // disabled.
947 //
948 // This function will stop the selected timer from incrementing. The \e
949 // ui32TimerNumber parameter selects the timer that should be disabled, for
950 // example, a 0 would target TIMER0. The \e ui32TimerSegment parameter allows
951 // the caller to individually select a segment within a timer to be disabled,
952 // such as TIMER0A, TIMER0B, or both.
953 //
954 // This function will stop a counter/timer from counting, but does not return
955 // the count value to 'zero'. If you would like to reset the counter back to
956 // zero, try the am_hal_ctimer_clear() function instead.
957 //
958 // Valid values for ui32TimerSegment are:
959 //
960 //     AM_HAL_CTIMER_TIMERA
961 //     AM_HAL_CTIMER_TIMERB
962 //     AM_HAL_CTIMER_BOTH
963 //
964 //*****************************************************************************
965 void
am_hal_ctimer_stop(uint32_t ui32TimerNumber,uint32_t ui32TimerSegment)966 am_hal_ctimer_stop(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
967 {
968     volatile uint32_t *pui32ConfigReg;
969 
970     //
971     // Find the correct control register.
972     //
973     pui32ConfigReg = (uint32_t*)CTIMERADDRn(CTIMER, ui32TimerNumber, CTRL0);
974 
975     //
976     // Begin critical section.
977     //
978     AM_CRITICAL_BEGIN
979 
980     //
981     // Clear the "enable" bit
982     //
983     AM_REGVAL(pui32ConfigReg) &= ~(ui32TimerSegment &
984                                    (CTIMER_CTRL0_TMRA0EN_Msk |
985                                     CTIMER_CTRL0_TMRB0EN_Msk));
986 
987     //
988     // Done with critical section.
989     //
990     AM_CRITICAL_END
991 
992 } // am_hal_ctimer_stop()
993 
994 //*****************************************************************************
995 //
996 // @brief Stops a timer and resets its value back to zero.
997 //
998 // @param ui32TimerNumber is the number of the timer to clear.
999 // @param ui32TimerSegment specifies which segment of the timer should be
1000 // cleared.
1001 //
1002 // This function will stop a free-running counter-timer, reset its value to
1003 // zero, and leave the timer disabled. When you would like to restart the
1004 // counter, you will need to call am_hal_ctimer_start().
1005 //
1006 // The \e ui32TimerSegment parameter allows the caller to individually select
1007 // a segment within, such as TIMER0A, TIMER0B, or both.
1008 //
1009 // Valid values for ui32TimerSegment are:
1010 //
1011 //     AM_HAL_CTIMER_TIMERA
1012 //     AM_HAL_CTIMER_TIMERB
1013 //     AM_HAL_CTIMER_BOTH
1014 //
1015 // @note Setting the CLR bit is necessary for completing timer initialization
1016 // including after MCU resets.
1017 //
1018 //
1019 //*****************************************************************************
1020 void
am_hal_ctimer_clear(uint32_t ui32TimerNumber,uint32_t ui32TimerSegment)1021 am_hal_ctimer_clear(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
1022 {
1023     volatile uint32_t *pui32ConfigReg;
1024 
1025     //
1026     // Find the correct control register.
1027     //
1028     pui32ConfigReg = (uint32_t*)CTIMERADDRn(CTIMER, ui32TimerNumber, CTRL0);
1029 
1030     //
1031     // Begin critical section.
1032     //
1033     AM_CRITICAL_BEGIN
1034 
1035     //
1036     // Set the "clear" bit
1037     //
1038     AM_REGVAL(pui32ConfigReg) |= (ui32TimerSegment &
1039                                   (CTIMER_CTRL0_TMRA0CLR_Msk |
1040                                    CTIMER_CTRL0_TMRB0CLR_Msk));
1041 
1042     //
1043     // Done with critical section.
1044     //
1045     AM_CRITICAL_END
1046 
1047 } // am_hal_ctimer_clear()
1048 
1049 //*****************************************************************************
1050 //
1051 // @brief Returns the current free-running value of the selected timer.
1052 //
1053 // @param ui32TimerNumber is the number of the timer to read.
1054 // @param ui32TimerSegment specifies which segment of the timer should be
1055 // read.
1056 //
1057 // This function returns the current free-running value of the selected timer.
1058 //
1059 // @note When reading from a linked timer, be sure to use AM_HAL_CTIMER both
1060 // for the segment argument.
1061 //
1062 // Valid values for ui32TimerSegment are:
1063 //
1064 //     AM_HAL_CTIMER_TIMERA
1065 //     AM_HAL_CTIMER_TIMERB
1066 //     AM_HAL_CTIMER_BOTH
1067 //
1068 // @return Current timer value.
1069 //
1070 //*****************************************************************************
1071 uint32_t
am_hal_ctimer_read(uint32_t ui32TimerNumber,uint32_t ui32TimerSegment)1072 am_hal_ctimer_read(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
1073 {
1074     uint32_t ui32RetVal = 0;
1075     uint32_t ui32ClkMsk, ui32Seg, ui32TmrAddr, ui32Ctrl;
1076     uint8_t  ui8ClkSrc;
1077     uint32_t ui32Values[3];
1078 
1079     //
1080     // Determine the timer segment.
1081     //
1082     ui32Seg = ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB ) ? 1 : 0;
1083 
1084     //
1085     // Get the address of the register for this timer.
1086     //
1087     ui32TmrAddr = g_ui32TMRAddrTbl[ui32TimerNumber];
1088 
1089     //
1090     // Get the clock source for this timer.
1091     //
1092     ui8ClkSrc = g_ui8ClkSrc[ui32TimerNumber][ui32Seg];
1093 
1094     if ( ui8ClkSrc == 0xFF )
1095     {
1096         //
1097         // If user did not configure using am_hal_ctimer_config_single() or
1098         // am_hal_ctimer_config(), read the register to get the clock source.
1099         // Note that this will incur bus latencies.
1100         //
1101         ui32Ctrl = AM_REGVAL(ui32TmrAddr + 0xC);
1102         if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
1103         {
1104             ui8ClkSrc = _FLD2VAL(CTIMER_CTRL0_TMRB0CLK, ui32Ctrl);
1105         }
1106         else
1107         {
1108             ui8ClkSrc = _FLD2VAL(CTIMER_CTRL0_TMRA0CLK, ui32Ctrl);
1109         }
1110 
1111         //
1112         // And save the clock source to the lookup table.
1113         //
1114         g_ui8ClkSrc[ui32TimerNumber][ui32Seg] = ui8ClkSrc;
1115     }
1116 
1117     //
1118     // Based on the source clock, mask off bits not needed for the comparison.
1119     //
1120     ui32ClkMsk = g_ui8TmrClkSrcMask[ui8ClkSrc & _FLD2VAL(CTIMER_CTRL0_TMRA0CLK, 0xFFFFFFFF)];
1121 
1122     if ( ui32ClkMsk != 0 )
1123     {
1124         if ( am_hal_burst_mode_status() == AM_HAL_BURST_MODE )
1125         {
1126             //
1127             // In burst mode, extend the mask by 1 bit.
1128             //
1129             ui32ClkMsk <<= 1;
1130             ui32ClkMsk |= 0x1;
1131         }
1132 
1133         //
1134         // Invert the mask so that the unneeded bits can be masked off.
1135         //
1136         ui32ClkMsk = ~ui32ClkMsk;
1137 
1138         //
1139         // Read the register into ui32Values[].
1140         //
1141         am_hal_triple_read(ui32TmrAddr, ui32Values);
1142 
1143         //
1144         // Now determine which of the three values is the correct value.
1145         // If the first 2 match, then the values are both correct and we're done.
1146         // Otherwise, the third value is taken to be the correct value.
1147         //
1148         if ( (ui32Values[0] & ui32ClkMsk)  == (ui32Values[1] & ui32ClkMsk) )
1149         {
1150             //
1151             // If the first two values match, then neither one was a bad read.
1152             // We'll take this as the current time.
1153             //
1154             ui32RetVal = ui32Values[1];
1155         }
1156         else
1157         {
1158             ui32RetVal = ui32Values[2];
1159         }
1160     }
1161     else
1162     {
1163         //
1164         // No need for the workaround.  Just read and return the register.
1165         //
1166         ui32RetVal = AM_REGVAL(ui32TmrAddr);
1167     }
1168 
1169     //
1170     // Get the correct return value
1171     //
1172     ui32RetVal &= ui32TimerSegment;
1173 
1174     if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
1175     {
1176         ui32RetVal >>= 16;
1177     }
1178 
1179     return ui32RetVal;
1180 
1181 } // am_hal_ctimer_read()
1182 
1183 //*****************************************************************************
1184 //
1185 // @brief Configure timer pin output.
1186 //
1187 // @param ui32TimerNumber   - the number of the timer to configure.
1188 // @param ui32TimerSegment  - specifies which segment of the timer to use.
1189 // @param ui32PadNum     - Pad number
1190 // @param eOutputType    - Output Configuration options
1191 // @param eDriveStrength - Drive strength
1192 //
1193 // This function will configure the output pin for the selected timer.
1194 //
1195 // ui32TimerNumber
1196 //     The timer number, 0-7.
1197 // ui32TimerSegment
1198 //     AM_HAL_CTIMER_TIMERA
1199 //     AM_HAL_CTIMER_TIMERB
1200 //     AM_HAL_CTIMER_BOTH
1201 // ui32PadNum
1202 //     Pad number to be used for the output signal.
1203 // eOutputType
1204 //     AM_HAL_CTIMER_OUTPUT_NORMAL
1205 //     AM_HAL_CTIMER_OUTPUT_SECONDARY
1206 //     AM_HAL_CTIMER_OUTPUT_FORCE0
1207 //     AM_HAL_CTIMER_OUTPUT_FORCE1
1208 // eDriveStrength
1209 //     AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA   = 0x0,
1210 //     AM_HAL_GPIO_PIN_DRIVESTRENGTH_4MA   = 0x1,
1211 //     AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA   = 0x2,
1212 //     AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA  = 0x3
1213 //
1214 // @return status (0 is Success).
1215 //
1216 //*****************************************************************************
1217 uint32_t
am_hal_ctimer_output_config(uint32_t ui32TimerNumber,uint32_t ui32TimerSegment,uint32_t ui32PadNum,uint32_t eOutputType,uint32_t eDriveStrength)1218 am_hal_ctimer_output_config(uint32_t ui32TimerNumber,
1219                             uint32_t ui32TimerSegment,
1220                             uint32_t ui32PadNum,
1221                             uint32_t eOutputType,
1222                             uint32_t eDriveStrength)
1223 {
1224     uint32_t ux, ui32Ctx, ui32CtxPadNum;
1225     uint32_t ui32CtxIdx;
1226     uint32_t ui32CtxOutcfgFnc, ui32CtxOutcfgMsk, ui32CfgShf;
1227     uint32_t ui32OutcfgValue;
1228 
1229     am_hal_gpio_pincfg_t sPinCfg = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1230 
1231     if ( (ui32PadNum > AM_HAL_GPIO_MAX_PADS)  ||  (ui32TimerNumber > 7)   ||
1232          (eOutputType > AM_HAL_CTIMER_OUTPUT_FORCE1)    ||
1233          ( (ui32TimerSegment != AM_HAL_CTIMER_TIMERA) &&
1234            (ui32TimerSegment != AM_HAL_CTIMER_TIMERB) &&
1235            (ui32TimerSegment != AM_HAL_CTIMER_BOTH) ) )
1236     {
1237         return AM_HAL_STATUS_INVALID_ARG;
1238     }
1239 
1240     //
1241     // Lookup the CTx number based on the given pad number.
1242     //
1243     for ( ux = 0; ux < 32; ux++ )
1244     {
1245         ui32CtxPadNum = CTXPADNUM(ux, 0);
1246         if ( ui32CtxPadNum == ui32PadNum )
1247         {
1248             ui32Ctx = ux;
1249             ui32CtxIdx = 0;
1250             break;
1251         }
1252 
1253         ui32CtxPadNum = CTXPADNUM(ux, 1);
1254         if ( ui32CtxPadNum == ui32PadNum )
1255         {
1256             ui32Ctx = ux;
1257             ui32CtxIdx = 1;
1258             break;
1259         }
1260 
1261         ui32CtxPadNum = 0xFF;
1262     }
1263 
1264     if ( ui32CtxPadNum >= AM_HAL_GPIO_MAX_PADS )
1265     {
1266         // No valid pad found.
1267         return AM_HAL_STATUS_OUT_OF_RANGE;
1268     }
1269 
1270     if ( ( ui32TimerNumber >= 6 )                               &&
1271          ( ui32TimerSegment == AM_HAL_CTIMER_TIMERA )           &&
1272          (eOutputType == AM_HAL_CTIMER_OUTPUT_SECONDARY) )
1273     {
1274         //
1275         // A6OUT2 is function 6 for every CTx.
1276         // A7OUT2 is function 7 for every CTx.
1277         // Set the function to either 6 or 7.
1278         //
1279         ui32CtxOutcfgFnc = ui32TimerNumber;
1280     }
1281     else if ( eOutputType >= AM_HAL_CTIMER_OUTPUT_FORCE0 )
1282     {
1283         // Set the function to 0 or 1.
1284         ui32CtxOutcfgFnc = eOutputType - AM_HAL_CTIMER_OUTPUT_FORCE0;
1285     }
1286     else
1287     {
1288         //
1289         // Now, scan outcfg_tbl[] to determine how to set the pin.
1290         //
1291         for ( ux = 0; ux < 4; ux++ )
1292         {
1293             if ( (OUTCTIMN(ui32Ctx, ux) == ui32TimerNumber) )
1294             {
1295                 bool bTimerB = OUTCTIMB(ui32Ctx, ux);
1296                 bool bO2 = OUTCO2(ui32Ctx, ux) ? true : false;
1297                 bool bOut2 = (eOutputType == AM_HAL_CTIMER_OUTPUT_SECONDARY);
1298                 if ( ( ui32TimerSegment == AM_HAL_CTIMER_TIMERA )   &&
1299                      (!bTimerB)                                     &&
1300                      (bO2 == bOut2) )
1301                 {
1302                     break;
1303                 }
1304 
1305                 if ( ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )   &&
1306                      (bTimerB)                                      &&
1307                      (bO2 == bOut2) )
1308                 {
1309                     break;
1310                 }
1311             }
1312         }
1313 
1314         if ( ux >= 4 )
1315         {
1316             return AM_HAL_STATUS_INVALID_OPERATION;
1317         }
1318 
1319         ui32CtxOutcfgFnc = ux + 2;
1320     }
1321 
1322     //
1323     // Looks like everything is valid.  Configure the pin.
1324     // Do the actual configuring inside a critical section.
1325     //
1326     ux = ui32Ctx % 10;
1327     ui32CfgShf = ux * 3;
1328     if ( ux > 4 )
1329     {
1330         ui32CfgShf += 1;
1331     }
1332     ui32CtxOutcfgMsk   = 0x7 << ui32CfgShf;
1333     ui32CtxOutcfgFnc <<= ui32CfgShf;
1334 
1335     //
1336     // Begin critical section.
1337     //
1338     AM_CRITICAL_BEGIN
1339 
1340     //
1341     // Note: It turns out that the offsets of the 4 OUTCFG registers are not
1342     // evenly spaced.  Therefore we purposely use this 'if' chain to program
1343     // them explicitly (as opposed to doing modulo math to compute an addr).
1344     //
1345     if ( ui32Ctx < 10 )
1346     {
1347         ui32OutcfgValue = CTIMER->OUTCFG0;
1348         ui32OutcfgValue &= ~ui32CtxOutcfgMsk;
1349         ui32OutcfgValue |=  ui32CtxOutcfgFnc;
1350         CTIMER->OUTCFG0 = ui32OutcfgValue;
1351     }
1352     else if ( ui32Ctx < 20 )
1353     {
1354         ui32OutcfgValue = CTIMER->OUTCFG1;
1355         ui32OutcfgValue &= ~ui32CtxOutcfgMsk;
1356         ui32OutcfgValue |=  ui32CtxOutcfgFnc;
1357         CTIMER->OUTCFG1 = ui32OutcfgValue;
1358     }
1359     else if ( ui32Ctx < 30 )
1360     {
1361         ui32OutcfgValue = CTIMER->OUTCFG2;
1362         ui32OutcfgValue &= ~ui32CtxOutcfgMsk;
1363         ui32OutcfgValue |=  ui32CtxOutcfgFnc;
1364         CTIMER->OUTCFG2 = ui32OutcfgValue;
1365     }
1366     else
1367     {
1368         ui32OutcfgValue = CTIMER->OUTCFG3;
1369         ui32OutcfgValue &= ~ui32CtxOutcfgMsk;
1370         ui32OutcfgValue |=  ui32CtxOutcfgFnc;
1371         CTIMER->OUTCFG3 = ui32OutcfgValue;
1372     }
1373 
1374     GPIO->CTENCFG &= ~(1 << ui32Ctx);
1375 
1376     //
1377     // Done with critical section.
1378     //
1379     AM_CRITICAL_END
1380 
1381     //
1382     // Configure the GPIO for the given pad.
1383     //
1384     sPinCfg.uFuncSel = CTXPADFNC(ui32Ctx, ui32CtxIdx);
1385     sPinCfg.eDriveStrength = eDriveStrength;
1386     am_hal_gpio_pinconfig(ui32CtxPadNum, sPinCfg);
1387 
1388     return AM_HAL_STATUS_SUCCESS;
1389 
1390 } // am_hal_ctimer_output_config()
1391 
1392 //*****************************************************************************
1393 //
1394 // @brief Configure timer inputs.
1395 //
1396 // @param ui32TimerNumber is the number of the timer to configure.
1397 //
1398 // @param ui32TimerSegment specifies which segment of the timer to use.
1399 //
1400 // @param ui32TimerInputConfig Input Configuration options.
1401 //
1402 // This function will configure the input pin for the selected timer.
1403 //
1404 // Valid values for ui32TimerSegment are:
1405 //     AM_HAL_CTIMER_TIMERA
1406 //     AM_HAL_CTIMER_TIMERB
1407 //     AM_HAL_CTIMER_BOTH
1408 //
1409 //*****************************************************************************
1410 void
am_hal_ctimer_input_config(uint32_t ui32TimerNumber,uint32_t ui32TimerSegment,uint32_t ui32TimerInputConfig)1411 am_hal_ctimer_input_config(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment,
1412                            uint32_t ui32TimerInputConfig)
1413 {
1414     //
1415     // Begin critical section.
1416     //
1417     AM_CRITICAL_BEGIN
1418 
1419     //
1420     // Done with critical section.
1421     //
1422     AM_CRITICAL_END
1423 
1424 } // am_hal_ctimer_input_config()
1425 
1426 //*****************************************************************************
1427 //
1428 // @brief Set a compare register.
1429 //
1430 // @param ui32TimerNumber is the number of the timer to configure.
1431 //
1432 // @param ui32TimerSegment specifies which segment of the timer to use.
1433 // Valid values for ui32TimerSegment are:
1434 //
1435 //     AM_HAL_CTIMER_TIMERA
1436 //     AM_HAL_CTIMER_TIMERB
1437 //     AM_HAL_CTIMER_BOTH
1438 //
1439 // @param ui32CompareReg specifies which compare register should be set
1440 // (either 0 or 1)
1441 //
1442 // @param ui32Value is the value that should be written to the compare
1443 // register.
1444 //
1445 // This function allows the caller to set the values in the compare registers
1446 // for a timer. These registers control the period and duty cycle of the
1447 // timers and their associated output pins. Please see the datasheet for
1448 // further information on the operation of the compare registers. The \e
1449 // ui32TimerSegment parameter allows the caller to individually select a
1450 // segment within, such as TIMER0A, TIMER0B, or both.
1451 //
1452 // @note For simple manipulations of period or duty cycle for timers and PWMs,
1453 // you may find it easier to use the am_hal_ctimer_period_set() function.
1454 //
1455 //*****************************************************************************
1456 void
am_hal_ctimer_compare_set(uint32_t ui32TimerNumber,uint32_t ui32TimerSegment,uint32_t ui32CompareReg,uint32_t ui32Value)1457 am_hal_ctimer_compare_set(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment,
1458                           uint32_t ui32CompareReg, uint32_t ui32Value)
1459 {
1460     volatile uint32_t *pui32CmprRegA, *pui32CmprRegB;
1461     uint32_t ui32CmprRegA, ui32CmprRegB, ui32ValB;
1462 
1463     //
1464     // Find the correct compare register to write.
1465     // Assume A or BOTH.  We'll change later if B.
1466     //
1467     pui32CmprRegA = (uint32_t *)CTIMERADDRn(CTIMER, ui32TimerNumber, CMPRA0);
1468     pui32CmprRegB = (uint32_t *)CTIMERADDRn(CTIMER, ui32TimerNumber, CMPRB0);
1469 
1470     ui32ValB = ( ui32TimerSegment == AM_HAL_CTIMER_BOTH ) ?
1471                ui32Value >> 16 : ui32Value & 0xFFFF;
1472 
1473     //
1474     // Write the compare register with the selected value.
1475     // Begin critical section while CMPR registers are modified.
1476     //
1477     AM_CRITICAL_BEGIN
1478 
1479     ui32CmprRegA = *pui32CmprRegA;
1480     ui32CmprRegB = *pui32CmprRegB;
1481 
1482     if ( ui32CompareReg == 1 )
1483     {
1484         //
1485         // CMPR reg 1
1486         // Get the lower 16b (but may not be used if TIMERB).
1487         //
1488         ui32CmprRegA = ( (ui32CmprRegA & CTIMER_CMPRA0_CMPR0A0_Msk) |
1489                           _VAL2FLD(CTIMER_CMPRA0_CMPR1A0, ui32Value & 0xFFFF) );
1490 
1491         //
1492         // Get the upper 16b (but may not be used if TIMERA)
1493         //
1494         ui32CmprRegB = ( (ui32CmprRegB & CTIMER_CMPRA0_CMPR0A0_Msk) |
1495                           _VAL2FLD(CTIMER_CMPRA0_CMPR1A0, ui32ValB) );
1496     }
1497     else
1498     {
1499         //
1500         // CMPR reg 0
1501         // Get the lower 16b (but may not be used if TIMERB)
1502         //
1503         ui32CmprRegA = ( (ui32CmprRegA & CTIMER_CMPRA0_CMPR1A0_Msk) |
1504                          _VAL2FLD(CTIMER_CMPRA0_CMPR0A0, ui32Value & 0xFFFF) );
1505 
1506         //
1507         // Set the upper 16b (but may not be used if TIMERA)
1508         //
1509         ui32CmprRegB = ( (ui32CmprRegB & CTIMER_CMPRA0_CMPR1A0_Msk) |
1510                          _VAL2FLD(CTIMER_CMPRA0_CMPR0A0, ui32ValB) );
1511     }
1512 
1513     if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
1514     {
1515         *pui32CmprRegB = ui32CmprRegB;
1516     }
1517     else
1518     {
1519         //
1520         // It's TIMERA or BOTH.
1521         //
1522         *pui32CmprRegA = ui32CmprRegA;
1523 
1524         if ( ui32TimerSegment == AM_HAL_CTIMER_BOTH )
1525         {
1526             *pui32CmprRegB = ui32CmprRegB;
1527         }
1528     }
1529 
1530     //
1531     // Done with critical section.
1532     //
1533     AM_CRITICAL_END
1534 
1535 } // am_hal_ctimer_compare_set()
1536 
1537 //*****************************************************************************
1538 //
1539 // @brief Set a compare register.
1540 //
1541 // @param ui32TimerNumber is the number of the timer to configure.
1542 //
1543 // @param ui32TimerSegment specifies which segment of the timer to use.
1544 // Valid values for ui32TimerSegment are:
1545 //
1546 //     AM_HAL_CTIMER_TIMERA
1547 //     AM_HAL_CTIMER_TIMERB
1548 //     AM_HAL_CTIMER_BOTH
1549 //
1550 // @param ui32CompareReg specifies which compare register should be set
1551 // (either 0 or 1)
1552 //
1553 // @param ui32Value is the value that should be written to the compare
1554 // register.
1555 //
1556 // This function allows the caller to set the values in the compare registers
1557 // for a timer. These registers control the period and duty cycle of the
1558 // timers and their associated output pins. Please see the datasheet for
1559 // further information on the operation of the compare registers. The \e
1560 // ui32TimerSegment parameter allows the caller to individually select a
1561 // segment within, such as TIMER0A, TIMER0B, or both.
1562 //
1563 // @note For simple manipulations of period or duty cycle for timers and PWMs,
1564 // you may find it easier to use the am_hal_ctimer_period_set() function.
1565 //
1566 //*****************************************************************************
1567 void
am_hal_ctimer_aux_compare_set(uint32_t ui32TimerNumber,uint32_t ui32TimerSegment,uint32_t ui32CompareReg,uint32_t ui32Value)1568 am_hal_ctimer_aux_compare_set(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment,
1569                               uint32_t ui32CompareReg, uint32_t ui32Value)
1570 {
1571     volatile uint32_t *pui32CmprRegA, *pui32CmprRegB;
1572     uint32_t ui32CmprRegA, ui32CmprRegB, ui32ValB;
1573 
1574     //
1575     // Find the correct compare register to write.
1576     // Assume A or BOTH.  We'll change later if B.
1577     //
1578     pui32CmprRegA = (uint32_t *)CTIMERADDRn(CTIMER, ui32TimerNumber, CMPRAUXA0);
1579     pui32CmprRegB = (uint32_t *)CTIMERADDRn(CTIMER, ui32TimerNumber, CMPRAUXB0);
1580 
1581     ui32ValB = ( ui32TimerSegment == AM_HAL_CTIMER_BOTH ) ?
1582                ui32Value >> 16 : ui32Value & 0xFFFF;
1583 
1584     //
1585     // Write the compare register with the selected value.
1586     // Begin critical section while CMPR registers are modified.
1587     //
1588     AM_CRITICAL_BEGIN
1589 
1590     ui32CmprRegA = *pui32CmprRegA;
1591     ui32CmprRegB = *pui32CmprRegB;
1592 
1593     if ( ui32CompareReg == 1 )
1594     {
1595         //
1596         // CMPR reg 1
1597         // Get the lower 16b (but may not be used if TIMERB).
1598         //
1599         ui32CmprRegA = ( (ui32CmprRegA & CTIMER_CMPRAUXA0_CMPR2A0_Msk) |
1600                           _VAL2FLD(CTIMER_CMPRAUXA0_CMPR3A0, ui32Value & 0xFFFF) );
1601 
1602         //
1603         // Get the upper 16b (but may not be used if TIMERA)
1604         //
1605         ui32CmprRegB = ( (ui32CmprRegB & CTIMER_CMPRAUXA0_CMPR2A0_Msk) |
1606                           _VAL2FLD(CTIMER_CMPRAUXA0_CMPR3A0, ui32ValB) );
1607     }
1608     else
1609     {
1610         //
1611         // CMPR reg 0
1612         // Get the lower 16b (but may not be used if TIMERB)
1613         //
1614         ui32CmprRegA = ( (ui32CmprRegA & CTIMER_CMPRAUXA0_CMPR3A0_Msk) |
1615                          _VAL2FLD(CTIMER_CMPRAUXA0_CMPR2A0, ui32Value & 0xFFFF) );
1616 
1617         //
1618         // Set the upper 16b (but may not be used if TIMERA)
1619         //
1620         ui32CmprRegB = ( (ui32CmprRegB & CTIMER_CMPRAUXA0_CMPR3A0_Msk) |
1621                          _VAL2FLD(CTIMER_CMPRAUXA0_CMPR2A0, ui32ValB) );
1622     }
1623 
1624     if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
1625     {
1626         *pui32CmprRegB = ui32CmprRegB;
1627     }
1628     else
1629     {
1630         //
1631         // It's TIMERA or BOTH.
1632         //
1633         *pui32CmprRegA = ui32CmprRegA;
1634 
1635         if ( ui32TimerSegment == AM_HAL_CTIMER_BOTH )
1636         {
1637             *pui32CmprRegB = ui32CmprRegB;
1638         }
1639     }
1640 
1641     //
1642     // Done with critical section.
1643     //
1644     AM_CRITICAL_END
1645 
1646 } // am_hal_ctimer_aux_compare_set()
1647 
1648 //*****************************************************************************
1649 //
1650 // @brief Set the period and duty cycle of a timer.
1651 //
1652 // @param ui32TimerNumber is the number of the timer to configure.
1653 //
1654 // @param ui32TimerSegment specifies which segment of the timer to use.
1655 //
1656 // @param ui32Period specifies the desired period.  This parameter effectively
1657 // specifies the CTIMER CMPR field(s). The CMPR fields are handled in hardware
1658 // as (n+1) values, therefore ui32Period is actually specified as 1 less than
1659 // the desired period. Finally, as mentioned in the data sheet, the CMPR fields
1660 // cannot be 0 (a value of 1), so neither can ui32Period be 0.
1661 //
1662 // @param ui32OnTime set the number of clocks where the output signal is high.
1663 //
1664 // This function should be used for simple manipulations of the period and
1665 // duty cycle of a counter/timer. To set the period and/or duty cycle of a
1666 // linked timer pair, use AM_HAL_CTIMER_BOTH as the timer segment argument. If
1667 // you would like to set the period and/or duty cycle for both TIMERA and
1668 // TIMERB you will need to call this function twice: once for TIMERA, and once
1669 // for TIMERB.
1670 //
1671 // Valid values for ui32TimerSegment are:
1672 //
1673 //     AM_HAL_CTIMER_TIMERA
1674 //     AM_HAL_CTIMER_TIMERB
1675 //     AM_HAL_CTIMER_BOTH
1676 //
1677 // @note The ui32OnTime parameter will only work if the timer is currently
1678 // operating in one of the PWM modes.
1679 //
1680 //*****************************************************************************
1681 void
am_hal_ctimer_period_set(uint32_t ui32TimerNumber,uint32_t ui32TimerSegment,uint32_t ui32Period,uint32_t ui32OnTime)1682 am_hal_ctimer_period_set(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment,
1683                          uint32_t ui32Period, uint32_t ui32OnTime)
1684 {
1685     volatile uint32_t *pui32ControlReg;
1686     volatile uint32_t *pui32CompareRegA;
1687     volatile uint32_t *pui32CompareRegB;
1688     uint32_t ui32Mode, ui32Comp0, ui32Comp1;
1689 
1690     //
1691     // Find the correct control register to pull the function select field
1692     // from.
1693     //
1694     pui32ControlReg = (uint32_t*)CTIMERADDRn(CTIMER, ui32TimerNumber, CTRL0);
1695 
1696     //
1697     // Find the correct compare registers to write.
1698     //
1699     pui32CompareRegA = (uint32_t*)CTIMERADDRn(CTIMER, ui32TimerNumber, CMPRA0);
1700 
1701     pui32CompareRegB = (uint32_t*)CTIMERADDRn(CTIMER, ui32TimerNumber, CMPRB0);
1702 
1703     //
1704     // Begin critical section.
1705     //
1706     AM_CRITICAL_BEGIN
1707 
1708     //
1709     // Extract the timer mode from the register based on the ui32TimerSegment
1710     // selected by the user.
1711     //
1712     ui32Mode = *pui32ControlReg;
1713     if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
1714     {
1715         ui32Mode = ui32Mode >> 16;
1716     }
1717 
1718     //
1719     // Mask to get to the bits we're interested in.
1720     //
1721     ui32Mode = ui32Mode & CTIMER_CTRL0_TMRA0FN_Msk;
1722 
1723     //
1724     // If the mode is a PWM mode, we'll need to calculate the correct CMPR0 and
1725     // CMPR1 values here.
1726     //
1727     if (ui32Mode == AM_HAL_CTIMER_FN_PWM_ONCE   ||
1728         ui32Mode == AM_HAL_CTIMER_FN_PWM_REPEAT)
1729     {
1730         ui32Comp0 = ui32Period - ui32OnTime;
1731         ui32Comp1 = ui32Period;
1732     }
1733     else
1734     {
1735         ui32Comp0 = ui32Period;
1736         ui32Comp1 = 0;
1737     }
1738 
1739     //
1740     // Based on the timer segment argument, write the calculated Compare 0 and
1741     // Compare 1 values to the correct halves of the correct registers.
1742     //
1743     if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERA )
1744     {
1745         //
1746         // For timer A, write the values to the TIMERA compare register.
1747         //
1748         *pui32CompareRegA = (_VAL2FLD(CTIMER_CMPRA0_CMPR0A0, ui32Comp0) |
1749                              _VAL2FLD(CTIMER_CMPRA0_CMPR1A0, ui32Comp1));
1750     }
1751     else if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
1752     {
1753         //
1754         // For timer B, write the values to the TIMERA compare register.
1755         //
1756         *pui32CompareRegB = (_VAL2FLD(CTIMER_CMPRA0_CMPR0A0, ui32Comp0) |
1757                              _VAL2FLD(CTIMER_CMPRA0_CMPR1A0, ui32Comp1));
1758     }
1759     else
1760     {
1761         //
1762         // For the linked case, write the lower halves of the values to the
1763         // TIMERA compare register, and the upper halves to the TIMERB compare
1764         // register.
1765         //
1766         *pui32CompareRegA = (_VAL2FLD(CTIMER_CMPRA0_CMPR0A0, ui32Comp0) |
1767                              _VAL2FLD(CTIMER_CMPRA0_CMPR1A0, ui32Comp1));
1768 
1769         *pui32CompareRegB = (_VAL2FLD(CTIMER_CMPRA0_CMPR0A0, ui32Comp0 >> 16) |
1770                              _VAL2FLD(CTIMER_CMPRA0_CMPR1A0, ui32Comp1 >> 16));
1771     }
1772 
1773     //
1774     // Done with critical section.
1775     //
1776     AM_CRITICAL_END
1777 
1778 } // am_hal_ctimer_period_set()
1779 
1780 //*****************************************************************************
1781 //
1782 // @brief Set the period and duty cycle of a timer.
1783 //
1784 // @param ui32TimerNumber is the number of the timer to configure.
1785 //
1786 // @param ui32TimerSegment specifies which segment of the timer to use.
1787 //
1788 // @param ui32Period specifies the desired period.  This parameter effectively
1789 // specifies the CTIMER CMPR field(s). The CMPR fields are handled in hardware
1790 // as (n+1) values, therefore ui32Period is actually specified as 1 less than
1791 // the desired period. Finally, as mentioned in the data sheet, the CMPR fields
1792 // cannot be 0 (a value of 1), so neither can ui32Period be 0.
1793 //
1794 // @param ui32OnTime set the number of clocks where the output signal is high.
1795 //
1796 // This function should be used for simple manipulations of the period and
1797 // duty cycle of a counter/timer. To set the period and/or duty cycle of a
1798 // linked timer pair, use AM_HAL_CTIMER_BOTH as the timer segment argument. If
1799 // you would like to set the period and/or duty cycle for both TIMERA and
1800 // TIMERB you will need to call this function twice: once for TIMERA, and once
1801 // for TIMERB.
1802 //
1803 // Valid values for ui32TimerSegment are:
1804 //
1805 //     AM_HAL_CTIMER_TIMERA
1806 //     AM_HAL_CTIMER_TIMERB
1807 //     AM_HAL_CTIMER_BOTH
1808 //
1809 // @note The ui32OnTime parameter will only work if the timer is currently
1810 // operating in one of the PWM modes.
1811 //
1812 //*****************************************************************************
1813 void
am_hal_ctimer_aux_period_set(uint32_t ui32TimerNumber,uint32_t ui32TimerSegment,uint32_t ui32Period,uint32_t ui32OnTime)1814 am_hal_ctimer_aux_period_set(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment,
1815                              uint32_t ui32Period, uint32_t ui32OnTime)
1816 {
1817     volatile uint32_t *pui32ControlReg;
1818     volatile uint32_t *pui32CompareRegA;
1819     volatile uint32_t *pui32CompareRegB;
1820     uint32_t ui32Mode, ui32Comp0, ui32Comp1;
1821 
1822     //
1823     // Find the correct control register to pull the function select field
1824     // from.
1825     //
1826     pui32ControlReg = (uint32_t*)CTIMERADDRn(CTIMER, ui32TimerNumber, CTRL0);
1827 
1828     //
1829     // Find the correct compare registers to write.
1830     //
1831     pui32CompareRegA = (uint32_t*)CTIMERADDRn(CTIMER, ui32TimerNumber, CMPRAUXA0);
1832 
1833     pui32CompareRegB = (uint32_t*)CTIMERADDRn(CTIMER, ui32TimerNumber, CMPRAUXB0);
1834 
1835     //
1836     // Begin critical section.
1837     //
1838     AM_CRITICAL_BEGIN
1839 
1840     //
1841     // Extract the timer mode from the register based on the ui32TimerSegment
1842     // selected by the user.
1843     //
1844     ui32Mode = *pui32ControlReg;
1845     if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
1846     {
1847         ui32Mode = ui32Mode >> 16;
1848     }
1849 
1850     //
1851     // Mask to get to the bits we're interested in.
1852     //
1853     ui32Mode = ui32Mode & CTIMER_CTRL0_TMRA0FN_Msk;
1854 
1855     //
1856     // If the mode is a PWM mode, we'll need to calculate the correct CMPR0 and
1857     // CMPR1 values here.
1858     //
1859     if (ui32Mode == AM_HAL_CTIMER_FN_PWM_ONCE   ||
1860         ui32Mode == AM_HAL_CTIMER_FN_PWM_REPEAT)
1861     {
1862         ui32Comp0 = ui32Period - ui32OnTime;
1863         ui32Comp1 = ui32Period;
1864     }
1865     else
1866     {
1867         ui32Comp0 = ui32Period;
1868         ui32Comp1 = 0;
1869     }
1870 
1871     //
1872     // Based on the timer segment argument, write the calculated Compare 0 and
1873     // Compare 1 values to the correct halves of the correct registers.
1874     //
1875     if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERA )
1876     {
1877         //
1878         // For timer A, write the values to the TIMERA compare register.
1879         //
1880         *pui32CompareRegA = (_VAL2FLD(CTIMER_CMPRAUXA0_CMPR2A0, ui32Comp0) |
1881                              _VAL2FLD(CTIMER_CMPRAUXA0_CMPR3A0, ui32Comp1));
1882     }
1883     else if ( ui32TimerSegment == AM_HAL_CTIMER_TIMERB )
1884     {
1885         //
1886         // For timer B, write the values to the TIMERA compare register.
1887         //
1888         *pui32CompareRegB = (_VAL2FLD(CTIMER_CMPRAUXA0_CMPR2A0, ui32Comp0) |
1889                              _VAL2FLD(CTIMER_CMPRAUXA0_CMPR3A0, ui32Comp1));
1890     }
1891     else
1892     {
1893         //
1894         // For the linked case, write the lower halves of the values to the
1895         // TIMERA compare register, and the upper halves to the TIMERB compare
1896         // register.
1897         //
1898         *pui32CompareRegA = (_VAL2FLD(CTIMER_CMPRAUXA0_CMPR2A0, ui32Comp0) |
1899                              _VAL2FLD(CTIMER_CMPRAUXA0_CMPR3A0, ui32Comp1));
1900 
1901         *pui32CompareRegB = (_VAL2FLD(CTIMER_CMPRAUXA0_CMPR2A0, ui32Comp0 >> 16) |
1902                              _VAL2FLD(CTIMER_CMPRAUXA0_CMPR3A0, ui32Comp1 >> 16));
1903     }
1904 
1905     //
1906     // Done with critical section.
1907     //
1908     AM_CRITICAL_END
1909 
1910 } // am_hal_ctimer_aux_period_set()
1911 
1912 //*****************************************************************************
1913 //
1914 // @brief Enable the TIMERA3 ADC trigger
1915 //
1916 // This function enables the ADC trigger within TIMERA3.
1917 //
1918 //*****************************************************************************
1919 void
am_hal_ctimer_adc_trigger_enable(void)1920 am_hal_ctimer_adc_trigger_enable(void)
1921 {
1922     //
1923     // Begin critical section.
1924     //
1925     AM_CRITICAL_BEGIN
1926 
1927     //
1928     // Enable the ADC trigger.
1929     //
1930     CTIMER->CTRL3_b.ADCEN = 1;
1931 
1932     //
1933     // Done with critical section.
1934     //
1935     AM_CRITICAL_END
1936 
1937 } // am_hal_ctimer_adc_trigger_enable()
1938 
1939 //*****************************************************************************
1940 //
1941 // @brief Disable the TIMERA3 ADC trigger
1942 //
1943 // This function disables the ADC trigger within TIMERA3.
1944 //
1945 //
1946 //*****************************************************************************
1947 void
am_hal_ctimer_adc_trigger_disable(void)1948 am_hal_ctimer_adc_trigger_disable(void)
1949 {
1950     //
1951     // Begin critical section.
1952     //
1953     AM_CRITICAL_BEGIN
1954 
1955     //
1956     // Disable the ADC trigger.
1957     //
1958     CTIMERn(0)->CTRL3 &= ~CTIMER_CTRL3_ADCEN_Msk;
1959 
1960     //
1961     // Done with critical section.
1962     //
1963     AM_CRITICAL_END
1964 
1965 } // am_hal_ctimer_adc_trigger_disable()
1966 
1967 //*****************************************************************************
1968 //
1969 // @brief Enables the selected timer interrupt.
1970 //
1971 // @param ui32Interrupt is the interrupt to be used.
1972 //
1973 // This function will enable the selected interrupts in the main CTIMER
1974 // interrupt enable register. In order to receive an interrupt from a timer,
1975 // you will need to enable the interrupt for that timer in this main register,
1976 // as well as in the timer control register (accessible though
1977 // am_hal_ctimer_config()), and in the NVIC.
1978 //
1979 // ui32Interrupt should be the logical OR of one or more of the following
1980 // values:
1981 //
1982 //     AM_HAL_CTIMER_INT_TIMERAxCx, AM_HAL_CTIMER_INT_TIMERAxCx,
1983 //
1984 // @note The AM_HAL_CTIMER_INT_TIMER defines were re-definitions of
1985 //       AM_REG_CTIMER_INTEN_CTMRAxCxINT_M register defines. They are
1986 //       dropped in this release to go back to a single source definition.
1987 //
1988 //
1989 //*****************************************************************************
1990 void
am_hal_ctimer_int_enable(uint32_t ui32Interrupt)1991 am_hal_ctimer_int_enable(uint32_t ui32Interrupt)
1992 {
1993     //
1994     // Begin critical section.
1995     //
1996     AM_CRITICAL_BEGIN
1997 
1998     //
1999     // Enable the interrupt at the module level.
2000     //
2001     CTIMERn(0)->INTEN |= ui32Interrupt;
2002 
2003     //
2004     // Done with critical section.
2005     //
2006     AM_CRITICAL_END
2007 
2008 } // am_hal_ctimer_int_enable()
2009 
2010 //*****************************************************************************
2011 //
2012 // @brief Return the enabled timer interrupts.
2013 //
2014 // This function will return all enabled interrupts in the main CTIMER
2015 // interrupt enable register.
2016 //
2017 // @return return enabled interrupts. This will be a logical or of:
2018 //
2019 //     AM_REG_CTIMER_INTEN_CTMRAxC0INT_M, AM_HAL_CTIMER_INT_TIMERAxC1,
2020 //
2021 // @return Return the enabled timer interrupts.
2022 //
2023 //*****************************************************************************
2024 uint32_t
am_hal_ctimer_int_enable_get(void)2025 am_hal_ctimer_int_enable_get(void)
2026 {
2027     //
2028     // Return enabled interrupts.
2029     //
2030     return CTIMERn(0)->INTEN;
2031 
2032 } // am_hal_ctimer_int_enable_get()
2033 
2034 //*****************************************************************************
2035 //
2036 // @brief Disables the selected timer interrupt.
2037 //
2038 // @param ui32Interrupt is the interrupt to be used.
2039 //
2040 // This function will disable the selected interrupts in the main CTIMER
2041 // interrupt register.
2042 //
2043 // ui32Interrupt should be the logical OR of one or more of the following
2044 // values:
2045 //
2046 //     AM_REG_CTIMER_INTEN_CTMRAxC0INT_M, AM_HAL_CTIMER_INT_TIMERAxC1,
2047 //
2048 //*****************************************************************************
2049 void
am_hal_ctimer_int_disable(uint32_t ui32Interrupt)2050 am_hal_ctimer_int_disable(uint32_t ui32Interrupt)
2051 {
2052     //
2053     // Begin critical section.
2054     //
2055     AM_CRITICAL_BEGIN
2056 
2057     //
2058     // Disable the interrupt at the module level.
2059     //
2060     CTIMERn(0)->INTEN &= ~ui32Interrupt;
2061 
2062     //
2063     // Done with critical section.
2064     //
2065     AM_CRITICAL_END
2066 
2067 } // am_hal_ctimer_int_disable()
2068 
2069 //*****************************************************************************
2070 //
2071 // @brief Clears the selected timer interrupt.
2072 //
2073 // @param ui32Interrupt is the interrupt to be used.
2074 //
2075 // This function will clear the selected interrupts in the main CTIMER
2076 // interrupt register.
2077 //
2078 // ui32Interrupt should be the logical OR of one or more of the following
2079 // values:
2080 //
2081 //     AM_REG_CTIMER_INTEN_CTMRAxC0INT_M, AM_HAL_CTIMER_INT_TIMERAxC1,
2082 //
2083 //*****************************************************************************
2084 void
am_hal_ctimer_int_clear(uint32_t ui32Interrupt)2085 am_hal_ctimer_int_clear(uint32_t ui32Interrupt)
2086 {
2087     //
2088     // Begin critical section.
2089     //
2090     AM_CRITICAL_BEGIN
2091 
2092     //
2093     // Disable the interrupt at the module level.
2094     //
2095     CTIMERn(0)->INTCLR = ui32Interrupt;
2096 
2097     //
2098     // Done with critical section.
2099     //
2100     AM_CRITICAL_END
2101 
2102 } // am_hal_ctimer_int_clear()
2103 
2104 //*****************************************************************************
2105 //
2106 // @brief Sets the selected timer interrupt.
2107 //
2108 // @param ui32Interrupt is the interrupt to be used.
2109 //
2110 // This function will set the selected interrupts in the main CTIMER
2111 // interrupt register.
2112 //
2113 // ui32Interrupt should be the logical OR of one or more of the following
2114 // values:
2115 //
2116 //     AM_REG_CTIMER_INTEN_CTMRAxC0INT_M, AM_HAL_CTIMER_INT_TIMERAxC1,
2117 //
2118 //*****************************************************************************
2119 void
am_hal_ctimer_int_set(uint32_t ui32Interrupt)2120 am_hal_ctimer_int_set(uint32_t ui32Interrupt)
2121 {
2122     //
2123     // Begin critical section.
2124     //
2125     AM_CRITICAL_BEGIN
2126 
2127     //
2128     // Set the interrupts.
2129     //
2130     CTIMERn(0)->INTSET = ui32Interrupt;
2131 
2132     //
2133     // Done with critical section.
2134     //
2135     AM_CRITICAL_END
2136 
2137 } // am_hal_ctimer_int_set()
2138 
2139 //*****************************************************************************
2140 //
2141 // @brief Returns either the enabled or raw timer interrupt status.
2142 //
2143 // This function will return the timer interrupt status.
2144 //
2145 // @param bEnabledOnly if true returns the status of the enabled interrupts
2146 // only.
2147 //
2148 // The return value will be the logical OR of one or more of the following
2149 // values:
2150 //
2151 //     AM_REG_CTIMER_INTEN_CTMRAxC0INT_M, AM_HAL_CTIMER_INT_TIMERAxC1,
2152 //
2153 // @return ui32RetVal either the timer interrupt status, or interrupt enabled.
2154 //
2155 //*****************************************************************************
2156 uint32_t
am_hal_ctimer_int_status_get(bool bEnabledOnly)2157 am_hal_ctimer_int_status_get(bool bEnabledOnly)
2158 {
2159     uint32_t ui32RetVal = 0;
2160 
2161     //
2162     // Begin critical section.
2163     //
2164     AM_CRITICAL_BEGIN
2165 
2166     //
2167     // Return the desired status.
2168     //
2169 
2170     if ( bEnabledOnly )
2171     {
2172         ui32RetVal  = CTIMERn(0)->INTSTAT;
2173         ui32RetVal &= CTIMERn(0)->INTEN;
2174     }
2175     else
2176     {
2177         ui32RetVal = CTIMERn(0)->INTSTAT;
2178     }
2179 
2180     //
2181     // Done with critical section.
2182     //
2183     AM_CRITICAL_END
2184 
2185     return ui32RetVal;
2186 
2187 } // am_hal_ctimer_int_status_get()
2188 //*****************************************************************************
2189 //
2190 // End Doxygen group.
2191 //! @}
2192 //
2193 //*****************************************************************************
2194