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 * \par
12 */
13 #include "types.h"
14 #include "iblloc.h"
15 #include "timer.h"
16 #include "devtimer.h"
17 #include "iblcfg.h"
18 #include <string.h>
21 /**********************************************************************
22 *************************** LOCAL Structures *************************
23 **********************************************************************/
25 /**
26 * @brief
27 * The structure describes the Timer blocks.
28 *
29 * @details
30 * Each timer in the system is associated with a timer
31 * block.
32 */
33 typedef struct TIMER_BLOCK
34 {
35 /**
36 * @brief Expiration Routine which is called once the timer
37 * expires.
38 */
39 void (*expiry)(void);
41 /**
42 * @brief This is the original expiration time in milli-seconds.
43 */
44 Uint32 org_timeout;
46 /**
47 * @brief This is the expiration time in milli-seconds. This is
48 * decremented by the timer module.
49 */
50 Uint32 timeout;
51 }TIMER_BLOCK;
53 /**
54 * @brief
55 * The structure describes the Timer Master Control Block.
56 *
57 * @details
58 * The structure contains information about the Timer Master Control
59 * block which stores information about the Timer Module.
60 */
61 typedef struct TIMER_MCB
62 {
63 /**
64 * @brief This keeps track of all timers which can exist in the
65 * System.
66 */
67 TIMER_BLOCK timer[MAX_TIMER_BLOCKS];
69 /**
70 * @brief This is the number of active timers in the system.
71 */
72 Uint32 num_active_timers;
73 }TIMER_MCB;
75 /**********************************************************************
76 *************************** GLOBAL Variables *************************
77 **********************************************************************/
79 /**
80 * @brief This global variable keeps track of all the timer which are
81 * currently active in the system.
82 */
83 TIMER_MCB timermcb;
85 /**********************************************************************
86 *************************** TIMER Functions **************************
87 **********************************************************************/
89 /**
90 * @b Description
91 * @n
92 * The function initializes the Timer module.
93 *
94 * @retval
95 * Not Applicable.
96 */
97 void timer_init (void)
98 {
99 /* Initialize the Timer Master Control Block. */
100 memset (&timermcb, 0, sizeof(TIMER_MCB));
101 return;
102 }
104 /**
105 * @b Description
106 * @n
107 * The function creates a timer.
108 *
109 * @param[in] timeout
110 * This is the timeout specified in milli-seconds after which the timer
111 * will expire.
112 * @param[in] expiry
113 * Expiration routine which is called to indicate that the timer block
114 * has expired.
115 *
116 * @retval
117 * Success - Handle to the timer block
118 * @retval
119 * Error - <0
120 */
121 Int32 timer_add (Uint32 timeout, void (*expiry)(void))
122 {
123 Uint16 index;
125 /* Basic Validations: Ensure parameters passed are valid. */
126 if ((timeout == 0) || (expiry == NULL))
127 return -1;
129 /* Cycle through and find a free timer block. */
130 for (index = 0; index < MAX_TIMER_BLOCKS; index++)
131 {
132 /* Free timers can be identified using the expiry routine. NULL indicates
133 * that the timer block is free. */
134 if (timermcb.timer[index].expiry == NULL)
135 {
136 /* Found a free slot. Is this the first timer being created? */
137 if (timermcb.num_active_timers == 0)
138 {
139 /* YES. We need to start the device timer. */
140 if (dev_create_timer() < 0)
141 {
142 /* Device layer timer creation failed. We will not be able
143 * to get the timers operational without this API. So we
144 * might as well fail also. */
145 return -1;
146 }
147 }
149 /* Populate the timer block structure. */
150 timermcb.timer[index].expiry = expiry;
151 timermcb.timer[index].timeout = timeout;
152 timermcb.timer[index].org_timeout = timeout;
154 /* Increment the number of timers in the system */
155 timermcb.num_active_timers++;
157 /* Return the handle to the timer block. */
158 return index;
159 }
160 }
162 /* Control comes here indicating that there were no free timer slots. */
163 return -1;
164 }
166 /**
167 * @b Description
168 * @n
169 * The function deletes a timer which was previously created.
170 *
171 * @param[in] handle
172 * This is the handle to the timer block to be deleted.
173 *
174 * @retval
175 * Not Applicable.
176 */
177 void timer_delete (Int32 handle)
178 {
179 /* Basic Validations: Ensure paramter is valid. */
180 if ((handle < 0) || (handle > MAX_TIMER_BLOCKS))
181 return;
183 /* Make sure there is at least one timer which is active; */
184 if (timermcb.num_active_timers > 0)
185 {
186 /* Simply reset the memory contents */
187 memset ((void *)&timermcb.timer[handle], 0, sizeof(TIMER_BLOCK));
189 /* Decrement the number of active timers in the system */
190 timermcb.num_active_timers--;
192 /* Check if there are any active timers in the system? */
193 if (timermcb.num_active_timers == 0)
194 {
195 /* No more active timers; we can delete the timer in the device layer. */
196 dev_delete_timer ();
197 }
198 }
199 return;
200 }
202 /**
203 * @b Description
204 * @n
205 * The function runs the timer scheduler. This API is required to be
206 * called by the boot modules and this in turn will decrement the various
207 * timer registered in the system and will call the appropriate
208 * expiration routines. If the boot modules fail to call this API then
209 * the timers will never expire.
210 *
211 * @retval
212 * Not Applicable.
213 */
214 void timer_run (void)
215 {
216 Uint16 index;
218 /* Check if there are any active timers in the System or not?
219 * If none are present; then we dont need to run the scheduler. */
220 if (timermcb.num_active_timers == 0)
221 return;
223 /* Check if the device timer has expired or not?
224 * If the timer has not expired there is no management to be done. */
225 if (dev_check_timer() == FALSE)
226 return;
228 /* Cycle through all the timer blocks and update them. */
229 for (index = 0; index < MAX_TIMER_BLOCKS; index++)
230 {
231 /* Is this an active timer? */
232 if (timermcb.timer[index].expiry != NULL)
233 {
234 /* YES. Decrement the timeout. */
235 timermcb.timer[index].timeout = timermcb.timer[index].timeout - 100;
237 /* Has the timer expired? */
238 if (timermcb.timer[index].timeout == 0)
239 {
240 /* Reset the timeouts */
241 timermcb.timer[index].timeout = timermcb.timer[index].org_timeout;
243 /* Call the expiration routine. */
244 timermcb.timer[index].expiry();
245 }
247 }
248 }
249 return;
250 }