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