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