Version 0.4 from Mike Line
[keystone-rtos/ibl.git] / src / driver / timer / timer.c
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;
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))
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;
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)
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;
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)
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;