1 /******************************************************************************
2 *  Filename:       timer.c
3 *  Revised:        2017-04-26 18:27:45 +0200 (Wed, 26 Apr 2017)
4 *  Revision:       48852
5 *
6 *  Description:    Driver for the General Purpose Timer
7 *
8 *  Copyright (c) 2015 - 2020, 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 "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     // Loop through the table that maps timer base addresses to interrupt
84     // numbers.
85     switch(ui32Base)
86     {
87     case GPT0_BASE :
88         ui32Int = INT_GPT0A;
89         break;
90     case GPT1_BASE :
91         ui32Int = INT_GPT1A;
92         break;
93     case GPT2_BASE :
94         ui32Int = INT_GPT2A;
95         break;
96     case GPT3_BASE :
97         ui32Int = INT_GPT3A;
98         break;
99     default :
100         ui32Int = 0x0;
101     }
102 
103     // Return the interrupt number or (-1) if not base address is not matched.
104     return (ui32Int);
105 }
106 
107 //*****************************************************************************
108 //
109 // Configures the timer(s)
110 //
111 //*****************************************************************************
112 void
TimerConfigure(uint32_t ui32Base,uint32_t ui32Config)113 TimerConfigure(uint32_t ui32Base, uint32_t ui32Config)
114 {
115     // Check the arguments.
116     ASSERT(TimerBaseValid(ui32Base));
117     ASSERT((ui32Config == TIMER_CFG_ONE_SHOT) ||
118            (ui32Config == TIMER_CFG_ONE_SHOT_UP) ||
119            (ui32Config == TIMER_CFG_PERIODIC) ||
120            (ui32Config == TIMER_CFG_PERIODIC_UP) ||
121            ((ui32Config & 0xFF000000) == TIMER_CFG_SPLIT_PAIR));
122     ASSERT(((ui32Config & 0xFF000000) != TIMER_CFG_SPLIT_PAIR) ||
123            ((((ui32Config & 0x000000FF) == TIMER_CFG_A_ONE_SHOT) ||
124              ((ui32Config & 0x000000FF) == TIMER_CFG_A_ONE_SHOT_UP) ||
125              ((ui32Config & 0x000000FF) == TIMER_CFG_A_PERIODIC) ||
126              ((ui32Config & 0x000000FF) == TIMER_CFG_A_PERIODIC_UP) ||
127              ((ui32Config & 0x000000FF) == TIMER_CFG_A_CAP_COUNT) ||
128              ((ui32Config & 0x000000FF) == TIMER_CFG_A_CAP_COUNT_UP) ||
129              ((ui32Config & 0x000000FF) == TIMER_CFG_A_CAP_TIME) ||
130              ((ui32Config & 0x000000FF) == TIMER_CFG_A_CAP_TIME_UP) ||
131              ((ui32Config & 0x000000FF) == TIMER_CFG_A_PWM)) &&
132             (((ui32Config & 0x0000FF00) == TIMER_CFG_B_ONE_SHOT) ||
133              ((ui32Config & 0x0000FF00) == TIMER_CFG_B_ONE_SHOT_UP) ||
134              ((ui32Config & 0x0000FF00) == TIMER_CFG_B_PERIODIC) ||
135              ((ui32Config & 0x0000FF00) == TIMER_CFG_B_PERIODIC_UP) ||
136              ((ui32Config & 0x0000FF00) == TIMER_CFG_B_CAP_COUNT) ||
137              ((ui32Config & 0x0000FF00) == TIMER_CFG_B_CAP_COUNT_UP) ||
138              ((ui32Config & 0x0000FF00) == TIMER_CFG_B_CAP_TIME) ||
139              ((ui32Config & 0x0000FF00) == TIMER_CFG_B_CAP_TIME_UP) ||
140              ((ui32Config & 0x0000FF00) == TIMER_CFG_B_PWM))));
141 
142     // Disable the timers.
143     HWREG(ui32Base + GPT_O_CTL) &= ~(GPT_CTL_TAEN | GPT_CTL_TBEN);
144 
145     // Set the global timer configuration.
146     HWREG(ui32Base + GPT_O_CFG) = ui32Config >> 24;
147 
148     // Set the configuration of the A and B timers. Note that the B timer
149     // configuration is ignored by the hardware in 32-bit modes.
150     HWREG(ui32Base + GPT_O_TAMR) = (ui32Config & 0xFF) | GPT_TAMR_TAPWMIE;
151     HWREG(ui32Base + GPT_O_TBMR) =
152         ((ui32Config >> 8) & 0xFF) | GPT_TBMR_TBPWMIE;
153 }
154 
155 //*****************************************************************************
156 //
157 // Controls the output level
158 //
159 //*****************************************************************************
160 void
TimerLevelControl(uint32_t ui32Base,uint32_t ui32Timer,bool bInvert)161 TimerLevelControl(uint32_t ui32Base, uint32_t ui32Timer, bool bInvert)
162 {
163     // Check the arguments.
164     ASSERT(TimerBaseValid(ui32Base));
165     ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) ||
166            (ui32Timer == TIMER_BOTH));
167 
168     // Set the output levels as requested.
169     ui32Timer &= GPT_CTL_TAPWML | GPT_CTL_TBPWML;
170     HWREG(ui32Base + GPT_O_CTL) = (bInvert ?
171                                    (HWREG(ui32Base + GPT_O_CTL) | ui32Timer) :
172                                    (HWREG(ui32Base + GPT_O_CTL) &
173                                    ~(ui32Timer)));
174 }
175 
176 //*****************************************************************************
177 //
178 // Controls the stall handling
179 //
180 //*****************************************************************************
181 void
TimerStallControl(uint32_t ui32Base,uint32_t ui32Timer,bool bStall)182 TimerStallControl(uint32_t ui32Base, uint32_t ui32Timer, bool bStall)
183 {
184     // Check the arguments.
185     ASSERT(TimerBaseValid(ui32Base));
186     ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) ||
187            (ui32Timer == TIMER_BOTH));
188 
189     // Set the stall mode.
190     ui32Timer &= GPT_CTL_TASTALL | GPT_CTL_TBSTALL;
191     HWREG(ui32Base + GPT_O_CTL) = (bStall ?
192                                    (HWREG(ui32Base + GPT_O_CTL) | ui32Timer) :
193                                    (HWREG(ui32Base + GPT_O_CTL) & ~(ui32Timer)));
194 }
195 
196 //*****************************************************************************
197 //
198 // Controls the wait on trigger handling
199 //
200 //*****************************************************************************
201 void
TimerWaitOnTriggerControl(uint32_t ui32Base,uint32_t ui32Timer,bool bWait)202 TimerWaitOnTriggerControl(uint32_t ui32Base, uint32_t ui32Timer, bool bWait)
203 {
204     // Check the arguments.
205     ASSERT(TimerBaseValid(ui32Base));
206     ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) ||
207            (ui32Timer == TIMER_BOTH));
208 
209     // Set the wait on trigger mode for timer A.
210     if(ui32Timer & TIMER_A)
211     {
212         if(bWait)
213         {
214             HWREG(ui32Base + GPT_O_TAMR) |= GPT_TAMR_TAWOT;
215         }
216         else
217         {
218             HWREG(ui32Base + GPT_O_TAMR) &= ~(GPT_TAMR_TAWOT);
219         }
220     }
221 
222     // Set the wait on trigger mode for timer B.
223     if(ui32Timer & TIMER_B)
224     {
225         if(bWait)
226         {
227             HWREG(ui32Base + GPT_O_TBMR) |= GPT_TBMR_TBWOT;
228         }
229         else
230         {
231             HWREG(ui32Base + GPT_O_TBMR) &= ~(GPT_TBMR_TBWOT);
232         }
233     }
234 }
235 
236 //*****************************************************************************
237 //
238 // Registers an interrupt handler for the timer interrupt
239 //
240 //*****************************************************************************
241 void
TimerIntRegister(uint32_t ui32Base,uint32_t ui32Timer,void (* pfnHandler)(void))242 TimerIntRegister(uint32_t ui32Base, uint32_t ui32Timer, void (*pfnHandler)(void))
243 {
244     uint32_t ui32Int;
245 
246     // Check the arguments.
247     ASSERT(TimerBaseValid(ui32Base));
248     ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) ||
249            (ui32Timer == TIMER_BOTH));
250 
251     // Get the interrupt number for this timer module.
252     ui32Int = TimerIntNumberGet(ui32Base);
253 
254     // Register an interrupt handler for timer A if requested.
255     if(ui32Timer & TIMER_A)
256     {
257         // Register the interrupt handler.
258         IntRegister(ui32Int, pfnHandler);
259 
260         // Enable the interrupt.
261         IntEnable(ui32Int);
262     }
263 
264     // Register an interrupt handler for timer B if requested.
265     if(ui32Timer & TIMER_B)
266     {
267         // Register the interrupt handler.
268         IntRegister(ui32Int + 1, pfnHandler);
269 
270         // Enable the interrupt.
271         IntEnable(ui32Int + 1);
272     }
273 }
274 
275 //*****************************************************************************
276 //
277 // Unregisters an interrupt handler for the timer interrupt
278 //
279 //*****************************************************************************
280 void
TimerIntUnregister(uint32_t ui32Base,uint32_t ui32Timer)281 TimerIntUnregister(uint32_t ui32Base, uint32_t ui32Timer)
282 {
283     uint32_t ui32Int;
284 
285     // Check the arguments.
286     ASSERT(TimerBaseValid(ui32Base));
287     ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) ||
288            (ui32Timer == TIMER_BOTH));
289 
290     // Get the interrupt number for this timer module.
291     ui32Int = TimerIntNumberGet(ui32Base);
292 
293     // Unregister the interrupt handler for timer A if requested.
294     if(ui32Timer & TIMER_A)
295     {
296         // Disable the interrupt.
297         IntDisable(ui32Int);
298 
299         // Unregister the interrupt handler.
300         IntUnregister(ui32Int);
301     }
302 
303     // Unregister the interrupt handler for timer B if requested.
304     if(ui32Timer & TIMER_B)
305     {
306         // Disable the interrupt.
307         IntDisable(ui32Int + 1);
308 
309         // Unregister the interrupt handler.
310         IntUnregister(ui32Int + 1);
311     }
312 }
313 
314 //*****************************************************************************
315 //
316 // Sets the Match Register Update mode
317 //
318 //*****************************************************************************
319 void
TimerMatchUpdateMode(uint32_t ui32Base,uint32_t ui32Timer,uint32_t ui32Mode)320 TimerMatchUpdateMode(uint32_t ui32Base, uint32_t ui32Timer, uint32_t ui32Mode)
321 {
322     // Check the arguments
323     ASSERT(TimerBaseValid(ui32Base));
324     ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) || (ui32Timer == TIMER_BOTH));
325     ASSERT((ui32Mode == TIMER_MATCHUPDATE_NEXTCYCLE) || (ui32Mode == TIMER_MATCHUPDATE_TIMEOUT));
326 
327     // Set mode for timer A
328     if(ui32Timer & TIMER_A)
329     {
330         if(ui32Mode == TIMER_MATCHUPDATE_NEXTCYCLE)
331         {
332             HWREG(ui32Base + GPT_O_TAMR) &= ~(GPT_TAMR_TAMRSU);
333         }
334         else
335         {
336             HWREG(ui32Base + GPT_O_TAMR) |= GPT_TAMR_TAMRSU;
337         }
338     }
339 
340     // Set mode for timer B
341     if(ui32Timer & TIMER_B)
342     {
343         if(ui32Mode == TIMER_MATCHUPDATE_NEXTCYCLE)
344         {
345             HWREG(ui32Base + GPT_O_TBMR) &= ~(GPT_TBMR_TBMRSU);
346         }
347         else
348         {
349             HWREG(ui32Base + GPT_O_TBMR) |= GPT_TBMR_TBMRSU;
350         }
351     }
352 }
353 
354 //*****************************************************************************
355 //
356 // Sets the Interval Load mode
357 //
358 //*****************************************************************************
359 void
TimerIntervalLoadMode(uint32_t ui32Base,uint32_t ui32Timer,uint32_t ui32Mode)360 TimerIntervalLoadMode(uint32_t ui32Base, uint32_t ui32Timer, uint32_t ui32Mode)
361 {
362     // Check the arguments
363     ASSERT(TimerBaseValid(ui32Base));
364     ASSERT((ui32Timer == TIMER_A) || (ui32Timer == TIMER_B) || (ui32Timer == TIMER_BOTH));
365     ASSERT((ui32Mode == TIMER_INTERVALLOAD_NEXTCYCLE) || (ui32Mode == TIMER_INTERVALLOAD_TIMEOUT));
366 
367     // Set mode for timer A
368     if(ui32Timer & TIMER_A)
369     {
370         if(ui32Mode == TIMER_INTERVALLOAD_NEXTCYCLE)
371         {
372             HWREG(ui32Base + GPT_O_TAMR) &= ~(GPT_TAMR_TAILD);
373         }
374         else
375         {
376             HWREG(ui32Base + GPT_O_TAMR) |= GPT_TAMR_TAILD;
377         }
378     }
379 
380     // Set mode for timer B
381     if(ui32Timer & TIMER_B)
382     {
383         if(ui32Mode == TIMER_INTERVALLOAD_NEXTCYCLE)
384         {
385             HWREG(ui32Base + GPT_O_TBMR) &= ~(GPT_TBMR_TBILD);
386         }
387         else
388         {
389             HWREG(ui32Base + GPT_O_TBMR) |= GPT_TBMR_TBILD;
390         }
391     }
392 }
393