1 /******************************************************************************
2 * Filename: timer.c
3 *
4 * Description: Driver for the General Purpose Timer
5 *
6 * Copyright (c) 2015 - 2022, Texas Instruments Incorporated
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 * 1) Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * 2) Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * 3) Neither the name of the ORGANIZATION nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 ******************************************************************************/
36
37 #include "timer.h"
38
39 //*****************************************************************************
40 //
41 // Handle support for DriverLib in ROM:
42 // This section will undo prototype renaming made in the header file
43 //
44 //*****************************************************************************
45 #if !defined(DOXYGEN)
46 #undef TimerConfigure
47 #define TimerConfigure NOROM_TimerConfigure
48 #undef TimerLevelControl
49 #define TimerLevelControl NOROM_TimerLevelControl
50 #undef TimerStallControl
51 #define TimerStallControl NOROM_TimerStallControl
52 #undef TimerWaitOnTriggerControl
53 #define TimerWaitOnTriggerControl NOROM_TimerWaitOnTriggerControl
54 #undef TimerIntRegister
55 #define TimerIntRegister NOROM_TimerIntRegister
56 #undef TimerIntUnregister
57 #define TimerIntUnregister NOROM_TimerIntUnregister
58 #undef TimerMatchUpdateMode
59 #define TimerMatchUpdateMode NOROM_TimerMatchUpdateMode
60 #undef TimerIntervalLoadMode
61 #define TimerIntervalLoadMode NOROM_TimerIntervalLoadMode
62 #endif
63
64 //*****************************************************************************
65 //
66 //! \brief Gets the timer interrupt number.
67 //!
68 //! Given a timer base address, this function returns the corresponding
69 //! interrupt number.
70 //!
71 //! \param ui32Base is the base address of the timer module.
72 //!
73 //! \return Returns a timer interrupt number, or -1 if \c ui32Base is invalid.
74 //
75 //*****************************************************************************
76 static uint32_t
TimerIntNumberGet(uint32_t ui32Base)77 TimerIntNumberGet(uint32_t ui32Base)
78 {
79 uint32_t ui32Int;
80
81 // Loop through the table that maps timer base addresses to interrupt
82 // numbers.
83 switch(ui32Base)
84 {
85 case GPT0_BASE :
86 ui32Int = INT_GPT0A;
87 break;
88 case GPT1_BASE :
89 ui32Int = INT_GPT1A;
90 break;
91 case GPT2_BASE :
92 ui32Int = INT_GPT2A;
93 break;
94 case GPT3_BASE :
95 ui32Int = INT_GPT3A;
96 break;
97 default :
98 ui32Int = 0x0;
99 }
100
101 // Return the interrupt number or (-1) if not base address is not matched.
102 return (ui32Int);
103 }
104
105 //*****************************************************************************
106 //
107 // Configures the timer(s)
108 //
109 //*****************************************************************************
110 void
TimerConfigure(uint32_t ui32Base,uint32_t ui32Config)111 TimerConfigure(uint32_t ui32Base, uint32_t ui32Config)
112 {
113 // Check the arguments.
114 ASSERT(TimerBaseValid(ui32Base));
115 ASSERT((ui32Config == TIMER_CFG_ONE_SHOT) ||
116 (ui32Config == TIMER_CFG_ONE_SHOT_UP) ||
117 (ui32Config == TIMER_CFG_PERIODIC) ||
118 (ui32Config == TIMER_CFG_PERIODIC_UP) ||
119 ((ui32Config & 0xFF000000) == TIMER_CFG_SPLIT_PAIR));
120 ASSERT(((ui32Config & 0xFF000000) != TIMER_CFG_SPLIT_PAIR) ||
121 ((((ui32Config & 0x000000FF) == TIMER_CFG_A_ONE_SHOT) ||
122 ((ui32Config & 0x000000FF) == TIMER_CFG_A_ONE_SHOT_UP) ||
123 ((ui32Config & 0x000000FF) == TIMER_CFG_A_PERIODIC) ||
124 ((ui32Config & 0x000000FF) == TIMER_CFG_A_PERIODIC_UP) ||
125 ((ui32Config & 0x000000FF) == TIMER_CFG_A_CAP_COUNT) ||
126 ((ui32Config & 0x000000FF) == TIMER_CFG_A_CAP_COUNT_UP) ||
127 ((ui32Config & 0x000000FF) == TIMER_CFG_A_CAP_TIME) ||
128 ((ui32Config & 0x000000FF) == TIMER_CFG_A_CAP_TIME_UP) ||
129 ((ui32Config & 0x000000FF) == TIMER_CFG_A_PWM)) &&
130 (((ui32Config & 0x0000FF00) == TIMER_CFG_B_ONE_SHOT) ||
131 ((ui32Config & 0x0000FF00) == TIMER_CFG_B_ONE_SHOT_UP) ||
132 ((ui32Config & 0x0000FF00) == TIMER_CFG_B_PERIODIC) ||
133 ((ui32Config & 0x0000FF00) == TIMER_CFG_B_PERIODIC_UP) ||
134 ((ui32Config & 0x0000FF00) == TIMER_CFG_B_CAP_COUNT) ||
135 ((ui32Config & 0x0000FF00) == TIMER_CFG_B_CAP_COUNT_UP) ||
136 ((ui32Config & 0x0000FF00) == TIMER_CFG_B_CAP_TIME) ||
137 ((ui32Config & 0x0000FF00) == TIMER_CFG_B_CAP_TIME_UP) ||
138 ((ui32Config & 0x0000FF00) == TIMER_CFG_B_PWM))));
139
140 // Disable the timers.
141 HWREG(ui32Base + GPT_O_CTL) &= ~(GPT_CTL_TAEN | GPT_CTL_TBEN);
142
143 // Set the global timer configuration.
144 HWREG(ui32Base + GPT_O_CFG) = ui32Config >> 24;
145
146 // Set the configuration of the A and B timers. Note that the B timer
147 // configuration is ignored by the hardware in 32-bit modes.
148 HWREG(ui32Base + GPT_O_TAMR) = (ui32Config & 0xFF) | GPT_TAMR_TAPWMIE;
149 HWREG(ui32Base + GPT_O_TBMR) =
150 ((ui32Config >> 8) & 0xFF) | GPT_TBMR_TBPWMIE;
151 }
152
153 //*****************************************************************************
154 //
155 // Controls the output level
156 //
157 //*****************************************************************************
158 void
TimerLevelControl(uint32_t ui32Base,uint32_t ui32Timer,bool bInvert)159 TimerLevelControl(uint32_t ui32Base, uint32_t ui32Timer, bool bInvert)
160 {
161 // Check the arguments.
162 ASSERT(TimerBaseValid(ui32Base));
163 ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) ||
164 (ui32Timer == TIMER_BOTH));
165
166 // Set the output levels as requested.
167 ui32Timer &= GPT_CTL_TAPWML | GPT_CTL_TBPWML;
168 HWREG(ui32Base + GPT_O_CTL) = (bInvert ?
169 (HWREG(ui32Base + GPT_O_CTL) | ui32Timer) :
170 (HWREG(ui32Base + GPT_O_CTL) &
171 ~(ui32Timer)));
172 }
173
174 //*****************************************************************************
175 //
176 // Controls the stall handling
177 //
178 //*****************************************************************************
179 void
TimerStallControl(uint32_t ui32Base,uint32_t ui32Timer,bool bStall)180 TimerStallControl(uint32_t ui32Base, uint32_t ui32Timer, bool bStall)
181 {
182 // Check the arguments.
183 ASSERT(TimerBaseValid(ui32Base));
184 ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) ||
185 (ui32Timer == TIMER_BOTH));
186
187 // Set the stall mode.
188 ui32Timer &= GPT_CTL_TASTALL | GPT_CTL_TBSTALL;
189 HWREG(ui32Base + GPT_O_CTL) = (bStall ?
190 (HWREG(ui32Base + GPT_O_CTL) | ui32Timer) :
191 (HWREG(ui32Base + GPT_O_CTL) & ~(ui32Timer)));
192 }
193
194 //*****************************************************************************
195 //
196 // Controls the wait on trigger handling
197 //
198 //*****************************************************************************
199 void
TimerWaitOnTriggerControl(uint32_t ui32Base,uint32_t ui32Timer,bool bWait)200 TimerWaitOnTriggerControl(uint32_t ui32Base, uint32_t ui32Timer, bool bWait)
201 {
202 // Check the arguments.
203 ASSERT(TimerBaseValid(ui32Base));
204 ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) ||
205 (ui32Timer == TIMER_BOTH));
206
207 // Set the wait on trigger mode for timer A.
208 if(ui32Timer & TIMER_A)
209 {
210 if(bWait)
211 {
212 HWREG(ui32Base + GPT_O_TAMR) |= GPT_TAMR_TAWOT;
213 }
214 else
215 {
216 HWREG(ui32Base + GPT_O_TAMR) &= ~(GPT_TAMR_TAWOT);
217 }
218 }
219
220 // Set the wait on trigger mode for timer B.
221 if(ui32Timer & TIMER_B)
222 {
223 if(bWait)
224 {
225 HWREG(ui32Base + GPT_O_TBMR) |= GPT_TBMR_TBWOT;
226 }
227 else
228 {
229 HWREG(ui32Base + GPT_O_TBMR) &= ~(GPT_TBMR_TBWOT);
230 }
231 }
232 }
233
234 //*****************************************************************************
235 //
236 // Registers an interrupt handler for the timer interrupt
237 //
238 //*****************************************************************************
239 void
TimerIntRegister(uint32_t ui32Base,uint32_t ui32Timer,void (* pfnHandler)(void))240 TimerIntRegister(uint32_t ui32Base, uint32_t ui32Timer, void (*pfnHandler)(void))
241 {
242 uint32_t ui32Int;
243
244 // Check the arguments.
245 ASSERT(TimerBaseValid(ui32Base));
246 ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) ||
247 (ui32Timer == TIMER_BOTH));
248
249 // Get the interrupt number for this timer module.
250 ui32Int = TimerIntNumberGet(ui32Base);
251
252 // Register an interrupt handler for timer A if requested.
253 if(ui32Timer & TIMER_A)
254 {
255 // Register the interrupt handler.
256 IntRegister(ui32Int, pfnHandler);
257
258 // Enable the interrupt.
259 IntEnable(ui32Int);
260 }
261
262 // Register an interrupt handler for timer B if requested.
263 if(ui32Timer & TIMER_B)
264 {
265 // Register the interrupt handler.
266 IntRegister(ui32Int + 1, pfnHandler);
267
268 // Enable the interrupt.
269 IntEnable(ui32Int + 1);
270 }
271 }
272
273 //*****************************************************************************
274 //
275 // Unregisters an interrupt handler for the timer interrupt
276 //
277 //*****************************************************************************
278 void
TimerIntUnregister(uint32_t ui32Base,uint32_t ui32Timer)279 TimerIntUnregister(uint32_t ui32Base, uint32_t ui32Timer)
280 {
281 uint32_t ui32Int;
282
283 // Check the arguments.
284 ASSERT(TimerBaseValid(ui32Base));
285 ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) ||
286 (ui32Timer == TIMER_BOTH));
287
288 // Get the interrupt number for this timer module.
289 ui32Int = TimerIntNumberGet(ui32Base);
290
291 // Unregister the interrupt handler for timer A if requested.
292 if(ui32Timer & TIMER_A)
293 {
294 // Disable the interrupt.
295 IntDisable(ui32Int);
296
297 // Unregister the interrupt handler.
298 IntUnregister(ui32Int);
299 }
300
301 // Unregister the interrupt handler for timer B if requested.
302 if(ui32Timer & TIMER_B)
303 {
304 // Disable the interrupt.
305 IntDisable(ui32Int + 1);
306
307 // Unregister the interrupt handler.
308 IntUnregister(ui32Int + 1);
309 }
310 }
311
312 //*****************************************************************************
313 //
314 // Sets the Match Register Update mode
315 //
316 //*****************************************************************************
317 void
TimerMatchUpdateMode(uint32_t ui32Base,uint32_t ui32Timer,uint32_t ui32Mode)318 TimerMatchUpdateMode(uint32_t ui32Base, uint32_t ui32Timer, uint32_t ui32Mode)
319 {
320 // Check the arguments
321 ASSERT(TimerBaseValid(ui32Base));
322 ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) || (ui32Timer == TIMER_BOTH));
323 ASSERT((ui32Mode == TIMER_MATCHUPDATE_NEXTCYCLE) || (ui32Mode == TIMER_MATCHUPDATE_TIMEOUT));
324
325 // Set mode for timer A
326 if(ui32Timer & TIMER_A)
327 {
328 if(ui32Mode == TIMER_MATCHUPDATE_NEXTCYCLE)
329 {
330 HWREG(ui32Base + GPT_O_TAMR) &= ~(GPT_TAMR_TAMRSU);
331 }
332 else
333 {
334 HWREG(ui32Base + GPT_O_TAMR) |= GPT_TAMR_TAMRSU;
335 }
336 }
337
338 // Set mode for timer B
339 if(ui32Timer & TIMER_B)
340 {
341 if(ui32Mode == TIMER_MATCHUPDATE_NEXTCYCLE)
342 {
343 HWREG(ui32Base + GPT_O_TBMR) &= ~(GPT_TBMR_TBMRSU);
344 }
345 else
346 {
347 HWREG(ui32Base + GPT_O_TBMR) |= GPT_TBMR_TBMRSU;
348 }
349 }
350 }
351
352 //*****************************************************************************
353 //
354 // Sets the Interval Load mode
355 //
356 //*****************************************************************************
357 void
TimerIntervalLoadMode(uint32_t ui32Base,uint32_t ui32Timer,uint32_t ui32Mode)358 TimerIntervalLoadMode(uint32_t ui32Base, uint32_t ui32Timer, uint32_t ui32Mode)
359 {
360 // Check the arguments
361 ASSERT(TimerBaseValid(ui32Base));
362 ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) || (ui32Timer == TIMER_BOTH));
363 ASSERT((ui32Mode == TIMER_INTERVALLOAD_NEXTCYCLE) || (ui32Mode == TIMER_INTERVALLOAD_TIMEOUT));
364
365 // Set mode for timer A
366 if(ui32Timer & TIMER_A)
367 {
368 if(ui32Mode == TIMER_INTERVALLOAD_NEXTCYCLE)
369 {
370 HWREG(ui32Base + GPT_O_TAMR) &= ~(GPT_TAMR_TAILD);
371 }
372 else
373 {
374 HWREG(ui32Base + GPT_O_TAMR) |= GPT_TAMR_TAILD;
375 }
376 }
377
378 // Set mode for timer B
379 if(ui32Timer & TIMER_B)
380 {
381 if(ui32Mode == TIMER_INTERVALLOAD_NEXTCYCLE)
382 {
383 HWREG(ui32Base + GPT_O_TBMR) &= ~(GPT_TBMR_TBILD);
384 }
385 else
386 {
387 HWREG(ui32Base + GPT_O_TBMR) |= GPT_TBMR_TBILD;
388 }
389 }
390 }
391