OSAL事件触发机制----定时器触发

OSAL事件触发机制----定时器触发

 

OSAL系统进入主循环后,轮询任务事件标志tasksEvents[],发现存在任务及其事件则进入tasksArr[]调用相对应的回调函数进行任务事件的处理,轮询任务前,向

1、由定时器超时溢出,设置任务及事件;

2、由外部信号(如按键)触发消息传递机制,设置任务及事件;

3、可调用osal_set_event()函数进行设定。

 

 1 /*********************************************************************
 2 
 3  * @fn      osal_set_event
 4 
 5  * @brief
 6 
 7  *    This function is called to set the event flags for a task. The
 8 
 9  *    event passed in is OR'd into the task's event variable.
10 
11  * @param   uint8 task_id - receiving tasks ID
12 
13  * @param   uint8 event_flag - what event to set
14 
15  * @return  SUCCESS, INVALID_TASK
16 
17  */
18 
19 uint8 osal_set_event( uint8 task_id, uint16 event_flag )
20 
21 {
22 
23   if ( task_id < tasksCnt )
24 
25   {
26 
27     halIntState_t   intState;
28 
29     HAL_ENTER_CRITICAL_SECTION(intState);    // Hold off interrupts
30 
31     tasksEvents[task_id] |= event_flag;  // Stuff the event bit(s)
32 
33     HAL_EXIT_CRITICAL_SECTION(intState);     // Release interrupts
34 
35     return ( SUCCESS );
36 
37   }
38 
39    else
40 
41   {
42 
43     return ( INVALID_TASK );
44 
45   }
46 
47 }

 

 

 

OSAL中,由osal_set_event()向主循环注入事件等待处理,

tasksEvents[task_id] |= event_flag;

task_id为任务IDevent_flag为该任务待处理事件。

 

不论是定时器还是消息传递,最终注入事件都是调用osal_set_event()完成。

 

1、 定时器触发事件流程

 

调用osal_start_timerEx()函数创建定时任务,该函数中调用osalAddTimer()接口,添加定时器函数中,遍历定时器链表,若存在该任务ID同事件的定时器,更新定时器超时时间,若不存在,则创建一个新定时器,将新创建的定时器添加到定时器链表中并返回定时器指针,创建失败返回NULL

 

OSAL调用osalTimeUpdate()函数进行定时器遍历,

  1 /*********************************************************************
  2 
  3  * @fn      osalTimeUpdate
  4 
  5  *
  6 
  7  * @brief    Uses the free running rollover count of the MAC backoff timer;
  8 
  9  *          this timer runs freely with a constant 320 usec interval.  The
 10 
 11  *          count of 320-usec ticks is converted to msecs and used to update
 12 
 13  *          the OSAL clock and Timers by invoking osalClockUpdate() and
 14 
 15  *          osalTimerUpdate().  This function is intended to be invoked
 16 
 17  *          from the background, not interrupt level.
 18 
 19  *
 20 
 21  * @param   None.
 22 
 23  *
 24 
 25  * @return  None.
 26 
 27  */
 28 
 29 void osalTimeUpdate( void )
 30 
 31 {
 32 
 33   uint16 tmp;
 34 
 35   uint16 ticks625us;
 36 
 37   uint16 elapsedMSec = 0;
 38 
 39  
 40 
 41   // Get the free-running count of 625us timer ticks
 42 
 43   tmp = ll_McuPrecisionCount();
 44 
 45  
 46 
 47   if ( tmp != previousLLTimerTick )
 48 
 49   {
 50 
 51     // Calculate the elapsed ticks of the free-running timer.
 52 
 53     ticks625us = tmp - previousLLTimerTick;
 54 
 55  
 56 
 57     // Store the LL Timer tick count for the next time through this function.
 58 
 59     previousLLTimerTick = tmp;
 60 
 61  
 62 
 63     /* It is necessary to loop to convert the usecs to msecs in increments so as
 64 
 65      * not to overflow the 16-bit variables.
 66 
 67      */
 68 
 69     while ( ticks625us > MAXCALCTICKS )
 70 
 71     {
 72 
 73       ticks625us -= MAXCALCTICKS;
 74 
 75       elapsedMSec += MAXCALCTICKS * 5 / 8;
 76 
 77       remUsTicks += MAXCALCTICKS * 5 % 8;
 78 
 79     }
 80 
 81  
 82 
 83     // update converted number with remaining ticks from loop and the
 84 
 85     // accumulated remainder from loop
 86 
 87     tmp = (ticks625us * 5) + remUsTicks;
 88 
 89  
 90 
 91     // Convert the 625 us ticks into milliseconds and a remainder
 92 
 93     elapsedMSec += tmp / 8;
 94 
 95     remUsTicks = tmp % 8;
 96 
 97  
 98 
 99     // Update OSAL Clock and Timers
100 
101     if ( elapsedMSec )
102 
103     {
104 
105       osalClockUpdate( elapsedMSec );
106 
107       osalTimerUpdate( elapsedMSec );
108 
109     }
110 
111   }
112 
113 }

 

 

 

该函数在主循环中调用,使用一个链路层的定时器,根据TI网站上工作人员的回答,使用timer2计时,时间间隔为625us,而不是注释中的320us,该函数中获取到ticks之后,转换为毫秒时间并调用osalClockUpdate()更新系统时间,单位 S;调用osalTimerUpdate()遍历定时器链表。

  1 /*********************************************************************
  2 
  3  * @fn      osalTimerUpdate
  4 
  5  *
  6 
  7  * @brief   Update the timer structures for a timer tick.
  8 
  9  *
 10 
 11  * @param   none
 12 
 13  *
 14 
 15  * @return  none
 16 
 17  *********************************************************************/
 18 
 19 void osalTimerUpdate( uint32 updateTime )
 20 
 21 {
 22 
 23   halIntState_t intState;
 24 
 25   osalTimerRec_t *srchTimer;
 26 
 27   osalTimerRec_t *prevTimer;
 28 
 29  
 30 
 31   osalTime_t timeUnion;
 32 
 33   timeUnion.time32 = updateTime;
 34 
 35  
 36 
 37   HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.
 38 
 39   // Update the system time
 40 
 41   osal_systemClock += updateTime;
 42 
 43   HAL_EXIT_CRITICAL_SECTION( intState );   // Re-enable interrupts.
 44 
 45  
 46 
 47   // Look for open timer slot
 48 
 49   if ( timerHead != NULL )
 50 
 51   {
 52 
 53     // Add it to the end of the timer list
 54 
 55     srchTimer = timerHead;
 56 
 57     prevTimer = (void *)NULL;
 58 
 59  
 60 
 61     // Look for open timer slot
 62 
 63     while ( srchTimer )
 64 
 65     {
 66 
 67       osalTimerRec_t *freeTimer = NULL;
 68 
 69  
 70 
 71       HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.
 72 
 73  
 74 
 75       // To minimize time in this critical section, avoid 32-bit math
 76 
 77       if ((timeUnion.time16[1] == 0) && (timeUnion.time8[1] == 0))
 78 
 79       {
 80 
 81         // If upper 24 bits are zero, check lower 8 bits for roll over
 82 
 83         if (srchTimer->timeout.time8[0] >= timeUnion.time8[0])
 84 
 85         {
 86 
 87           // 8-bit math
 88 
 89           srchTimer->timeout.time8[0] -= timeUnion.time8[0];
 90 
 91         }
 92 
 93         else
 94 
 95         {
 96 
 97           // 32-bit math
 98 
 99           if (srchTimer->timeout.time32 > timeUnion.time32)
100 
101           {
102 
103             srchTimer->timeout.time32 -= timeUnion.time32;
104 
105           }
106 
107           else
108 
109           {
110 
111             srchTimer->timeout.time32 = 0;
112 
113           }
114 
115         }
116 
117       }
118 
119       else
120 
121       {
122 
123           // 32-bit math
124 
125         if (srchTimer->timeout.time32 > timeUnion.time32)
126 
127         {
128 
129           srchTimer->timeout.time32 -= timeUnion.time32;
130 
131         }
132 
133         else
134 
135         {
136 
137           srchTimer->timeout.time32 = 0;
138 
139         }
140 
141       }
142 
143  
144 
145       // Check for reloading
146 
147       if ( (srchTimer->timeout.time16[0] == 0) && (srchTimer->timeout.time16[1] == 0) &&
148 
149            (srchTimer->reloadTimeout) && (srchTimer->event_flag) )
150 
151       {
152 
153         // Notify the task of a timeout
154 
155         osal_set_event( srchTimer->task_id, srchTimer->event_flag );
156 
157  
158 
159         // Reload the timer timeout value
160 
161         srchTimer->timeout.time32 = srchTimer->reloadTimeout;
162 
163       }
164 
165  
166 
167       // When timeout or delete (event_flag == 0)
168 
169       if ( ((srchTimer->timeout.time16[0] == 0) && (srchTimer->timeout.time16[1] == 0)) ||
170 
171             (srchTimer->event_flag == 0) )
172 
173       {
174 
175         // Take out of list
176 
177         if ( prevTimer == NULL )
178 
179         {
180 
181           timerHead = srchTimer->next;
182 
183         }
184 
185         else
186 
187         {
188 
189           prevTimer->next = srchTimer->next;
190 
191         }
192 
193  
194 
195         // Setup to free memory
196 
197         freeTimer = srchTimer;
198 
199  
200 
201         // Next
202 
203         srchTimer = srchTimer->next;
204 
205       }
206 
207       else
208 
209       {
210 
211         // Get next
212 
213         prevTimer = srchTimer;
214 
215         srchTimer = srchTimer->next;
216 
217       }
218 
219  
220 
221       HAL_EXIT_CRITICAL_SECTION( intState );   // Re-enable interrupts.
222 
223  
224 
225       if ( freeTimer )
226 
227       {
228 
229         if ( (freeTimer->timeout.time16[0] == 0) && (freeTimer->timeout.time16[1] == 0) )
230 
231         {
232 
233           osal_set_event( freeTimer->task_id, freeTimer->event_flag );
234 
235         }
236 
237         osal_mem_free( freeTimer );
238 
239       }
240 
241     }
242 
243   }
244 
245 }

 

 

 

该函数中获取到系统流逝时间后,存储在一个长度为32位的联合体中timeUnion,并更新系统时钟,单位ms,遍历定时器链表。

a、为了减少时间消耗,没有直接使用32位进行比较,其实本质上还是定时器超时时间减去系统流逝时间,若超时时间小于系统流逝时间,则直接置0

b、判断是否为循环定时器超时时间为0,是,则调用osal_set_event()向主循环注入任务事件,并reloadTimeout

c、判断是否是普通定时器超时,是,则调用osal_set_event()向主循环注入任务事件,并删除定时器释放内存。

 

posted on 2015-11-18 15:38  vi_cc  阅读(3596)  评论(0编辑  收藏  举报

导航