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