1 /**
2 * @file timer.c
3 *
4 * @brief
5 * The file implements the TIMER module.
6 *
7 * \par
8 * NOTE:
9 * (C) Copyright 2008, Texas Instruments, Inc.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 *
18 * Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the
21 * distribution.
22 *
23 * Neither the name of Texas Instruments Incorporated nor the names of
24 * its contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 *
39 * \par
40 */
41 #include "types.h"
42 #include "iblloc.h"
43 #include "timer.h"
44 #include "devtimer.h"
45 #include "iblcfg.h"
46 #include "timer_osal.h"
47 #include <string.h>
50 /**********************************************************************
51 *************************** LOCAL Structures *************************
52 **********************************************************************/
54 /**
55 * @brief
56 * The structure describes the Timer blocks.
57 *
58 * @details
59 * Each timer in the system is associated with a timer
60 * block.
61 */
62 typedef struct TIMER_BLOCK
63 {
64 /**
65 * @brief Expiration Routine which is called once the timer
66 * expires.
67 */
68 void (*expiry)(void);
70 /**
71 * @brief This is the original expiration time in milli-seconds.
72 */
73 Uint32 org_timeout;
75 /**
76 * @brief This is the expiration time in milli-seconds. This is
77 * decremented by the timer module.
78 */
79 Uint32 timeout;
80 }TIMER_BLOCK;
82 /**
83 * @brief
84 * The structure describes the Timer Master Control Block.
85 *
86 * @details
87 * The structure contains information about the Timer Master Control
88 * block which stores information about the Timer Module.
89 */
90 typedef struct TIMER_MCB
91 {
92 /**
93 * @brief This keeps track of all timers which can exist in the
94 * System.
95 */
96 TIMER_BLOCK timer[MAX_TIMER_BLOCKS];
98 /**
99 * @brief This is the number of active timers in the system.
100 */
101 Uint32 num_active_timers;
102 }TIMER_MCB;
104 /**********************************************************************
105 *************************** GLOBAL Variables *************************
106 **********************************************************************/
108 /**
109 * @brief This global variable keeps track of all the timer which are
110 * currently active in the system.
111 */
112 TIMER_MCB timermcb;
114 /**********************************************************************
115 *************************** TIMER Functions **************************
116 **********************************************************************/
118 /**
119 * @b Description
120 * @n
121 * The function initializes the Timer module.
122 *
123 * @retval
124 * Not Applicable.
125 */
126 void timer_init (void)
127 {
128 /* Initialize the Timer Master Control Block. */
129 timerMemset (&timermcb, 0, sizeof(TIMER_MCB));
130 return;
131 }
133 /**
134 * @b Description
135 * @n
136 * The function creates a timer.
137 *
138 * @param[in] timeout
139 * This is the timeout specified in milli-seconds after which the timer
140 * will expire.
141 * @param[in] expiry
142 * Expiration routine which is called to indicate that the timer block
143 * has expired.
144 *
145 * @retval
146 * Success - Handle to the timer block
147 * @retval
148 * Error - <0
149 */
150 Int32 timer_add (Uint32 timeout, void (*expiry)(void))
151 {
152 Uint16 index;
154 /* Basic Validations: Ensure parameters passed are valid. */
155 if ((timeout == 0) || (expiry == NULL))
156 return -1;
158 /* Cycle through and find a free timer block. */
159 for (index = 0; index < MAX_TIMER_BLOCKS; index++)
160 {
161 /* Free timers can be identified using the expiry routine. NULL indicates
162 * that the timer block is free. */
163 if (timermcb.timer[index].expiry == NULL)
164 {
165 /* Found a free slot. Is this the first timer being created? */
166 if (timermcb.num_active_timers == 0)
167 {
168 /* YES. We need to start the device timer. */
169 if (dev_create_timer() < 0)
170 {
171 /* Device layer timer creation failed. We will not be able
172 * to get the timers operational without this API. So we
173 * might as well fail also. */
174 return -1;
175 }
176 }
178 /* Populate the timer block structure. */
179 timermcb.timer[index].expiry = expiry;
180 timermcb.timer[index].timeout = timeout;
181 timermcb.timer[index].org_timeout = timeout;
183 /* Increment the number of timers in the system */
184 timermcb.num_active_timers++;
186 /* Return the handle to the timer block. */
187 return index;
188 }
189 }
191 /* Control comes here indicating that there were no free timer slots. */
192 return -1;
193 }
195 /**
196 * @b Description
197 * @n
198 * The function deletes a timer which was previously created.
199 *
200 * @param[in] handle
201 * This is the handle to the timer block to be deleted.
202 *
203 * @retval
204 * Not Applicable.
205 */
206 void timer_delete (Int32 handle)
207 {
208 /* Basic Validations: Ensure paramter is valid. */
209 if ((handle < 0) || (handle > MAX_TIMER_BLOCKS))
210 return;
212 /* Make sure there is at least one timer which is active; */
213 if (timermcb.num_active_timers > 0)
214 {
215 /* Simply reset the memory contents */
216 timerMemset ((void *)&timermcb.timer[handle], 0, sizeof(TIMER_BLOCK));
218 /* Decrement the number of active timers in the system */
219 timermcb.num_active_timers--;
221 /* Check if there are any active timers in the system? */
222 if (timermcb.num_active_timers == 0)
223 {
224 /* No more active timers; we can delete the timer in the device layer. */
225 dev_delete_timer ();
226 }
227 }
228 return;
229 }
231 /**
232 * @b Description
233 * @n
234 * The function runs the timer scheduler. This API is required to be
235 * called by the boot modules and this in turn will decrement the various
236 * timer registered in the system and will call the appropriate
237 * expiration routines. If the boot modules fail to call this API then
238 * the timers will never expire.
239 *
240 * @retval
241 * Not Applicable.
242 */
243 void timer_run (void)
244 {
245 Uint16 index;
247 /* Check if there are any active timers in the System or not?
248 * If none are present; then we dont need to run the scheduler. */
249 if (timermcb.num_active_timers == 0)
250 return;
252 /* Check if the device timer has expired or not?
253 * If the timer has not expired there is no management to be done. */
254 if (dev_check_timer() == FALSE)
255 return;
257 /* Cycle through all the timer blocks and update them. */
258 for (index = 0; index < MAX_TIMER_BLOCKS; index++)
259 {
260 /* Is this an active timer? */
261 if (timermcb.timer[index].expiry != NULL)
262 {
263 /* YES. Decrement the timeout. */
264 timermcb.timer[index].timeout = timermcb.timer[index].timeout - 100;
266 /* Has the timer expired? */
267 if (timermcb.timer[index].timeout == 0)
268 {
269 /* Reset the timeouts */
270 timermcb.timer[index].timeout = timermcb.timer[index].org_timeout;
272 /* Call the expiration routine. */
273 timermcb.timer[index].expiry();
274 }
276 }
277 }
278 return;
279 }