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

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

OSAL系统进入主循环后,轮询任务事件标志tasksEvents[],发现存在任务及其事件则进入tasksArr[]调用相对应的回调函数进行任务事件的处理,轮询任务前,向
1、由定时器超时溢出,设置任务及事件;
2、由外部信号(如按键)触发消息传递机制,设置任务及事件;
3、可调用osal_set_event()函数进行设定。

1 /********************************************************************* 2 3* @fnosal_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* @paramuint8 task_id - receiving tasks ID 12 13* @paramuint8 event_flag - what event to set 14 15* @returnSUCCESS, INVALID_TASK 16 17*/ 18 19 uint8 osal_set_event( uint8 task_id, uint16 event_flag ) 20 21 { 22 23if ( task_id < tasksCnt ) 24 25{ 26 27halIntState_tintState; 28 29HAL_ENTER_CRITICAL_SECTION(intState); // Hold off interrupts 30 31tasksEvents[task_id] |= event_flag; // Stuff the event bit(s) 32 33HAL_EXIT_CRITICAL_SECTION(intState); // Release interrupts 34 35return ( SUCCESS ); 36 37} 38 39else 40 41{ 42 43return ( INVALID_TASK ); 44 45} 46 47 }




OSAL中,由osal_set_event()向主循环注入事件等待处理,
tasksEvents[task_id] |= event_flag;
task_id为任务ID,event_flag为该任务待处理事件。

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

1、 定时器触发事件流程

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

OSAL调用osalTimeUpdate()函数进行定时器遍历,
1 /********************************************************************* 2 3* @fnosalTimeUpdate 4 5* 6 7* @briefUses 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* @paramNone. 22 23* 24 25* @returnNone. 26 27*/ 28 29 void osalTimeUpdate( void ) 30 31 { 32 33uint16 tmp; 34 35uint16 ticks625us; 36 37uint16 elapsedMSec = 0; 38 39 40 41// Get the free-running count of 625us timer ticks 42 43tmp = ll_McuPrecisionCount(); 44 45 46 47if ( tmp != previousLLTimerTick ) 48 49{ 50 51// Calculate the elapsed ticks of the free-running timer. 52 53ticks625us = tmp - previousLLTimerTick; 54 55 56 57// Store the LL Timer tick count for the next time through this function. 58 59previousLLTimerTick = 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 69while ( ticks625us > MAXCALCTICKS ) 70 71{ 72 73ticks625us -= MAXCALCTICKS; 74 75elapsedMSec += MAXCALCTICKS * 5 / 8; 76 77remUsTicks += 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 87tmp = (ticks625us * 5) + remUsTicks; 88 89 90 91// Convert the 625 us ticks into milliseconds and a remainder 92 93elapsedMSec += tmp / 8; 94 95remUsTicks = tmp % 8; 96 97 98 99// Update OSAL Clock and Timers 100 101if ( elapsedMSec ) 102 103{ 104 105osalClockUpdate( elapsedMSec ); 106 107osalTimerUpdate( elapsedMSec ); 108 109} 110 111} 112 113 }




该函数在主循环中调用,使用一个链路层的定时器,根据TI网站上工作人员的回答,使用timer2计时,时间间隔为625us,而不是注释中的320us,该函数中获取到ticks之后,转换为毫秒时间并调用osalClockUpdate()更新系统时间,单位 S;调用osalTimerUpdate()遍历定时器链表。
1 /********************************************************************* 2 3* @fnosalTimerUpdate 4 5* 6 7* @briefUpdate the timer structures for a timer tick. 8 9* 10 11* @paramnone 12 13* 14 15* @returnnone 16 17*********************************************************************/ 18 19 void osalTimerUpdate( uint32 updateTime ) 20 21 { 22 23halIntState_t intState; 24 25osalTimerRec_t *srchTimer; 26 27osalTimerRec_t *prevTimer; 28 29 30 31osalTime_t timeUnion; 32 33timeUnion.time32 = updateTime; 34 35 36 37HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts. 38 39// Update the system time 40 41osal_systemClock += updateTime; 42 43HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts. 44 45 46 47// Look for open timer slot 48 49if ( timerHead != NULL ) 50 51{ 52 53// Add it to the end of the timer list 54 55srchTimer = timerHead; 56 57prevTimer = (void *)NULL; 58 59 60 61// Look for open timer slot 62 63while ( srchTimer ) 64 65{ 66 67osalTimerRec_t *freeTimer = NULL; 68 69 70 71HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts. 72 73 74 75// To minimize time in this critical section, avoid 32-bit math 76 77if ((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 83if (srchTimer->timeout.time8[0] >= timeUnion.time8[0]) 84 85{ 86 87// 8-bit math 88 89srchTimer->timeout.time8[0] -= timeUnion.time8[0]; 90 91} 92 93else 94 95{ 96 97// 32-bit math 98 99if (srchTimer->timeout.time32 > timeUnion.time32) 100 101{ 102 103srchTimer->timeout.time32 -= timeUnion.time32; 104 105} 106 107else 108 109{ 110 111srchTimer->timeout.time32 = 0; 112 113} 114 115} 116 117} 118 119else 120 121{ 122 123// 32-bit math 124 125if (srchTimer->timeout.time32 > timeUnion.time32) 126 127{ 128 129srchTimer->timeout.time32 -= timeUnion.time32; 130 131} 132 133else 134 135{ 136 137srchTimer->timeout.time32 = 0; 138 139} 140 141} 142 143 144 145// Check for reloading 146 147if ( (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 155osal_set_event( srchTimer->task_id, srchTimer->event_flag ); 156 157 158 159// Reload the timer timeout value 160 161srchTimer->timeout.time32 = srchTimer->reloadTimeout; 162 163} 164 165 166 167// When timeout or delete (event_flag == 0) 168 169if ( ((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 177if ( prevTimer == NULL ) 178 179{ 180 181timerHead = srchTimer->next; 182 183} 184 185else 186 187{ 188 189prevTimer->next = srchTimer->next; 190 191} 192 193 194 195// Setup to free memory 196 197freeTimer = srchTimer; 198 199 200 201// Next 202 203srchTimer = srchTimer->next; 204 205} 206 207else 208 209{ 210 211// Get next 212 213prevTimer = srchTimer; 214 215srchTimer = srchTimer->next; 216 217} 218 219 220 221HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts. 222 223 224 225if ( freeTimer ) 226 227{ 228 229if ( (freeTimer->timeout.time16[0] == 0) && (freeTimer->timeout.time16[1] == 0) ) 230 231{ 232 233osal_set_event( freeTimer->task_id, freeTimer->event_flag ); 234 235} 236 237osal_mem_free( freeTimer ); 238 239} 240 241} 242 243} 244 245 }




【OSAL事件触发机制----定时器触发】该函数中获取到系统流逝时间后,存储在一个长度为32位的联合体中timeUnion,并更新系统时钟,单位ms,遍历定时器链表。
a、为了减少时间消耗,没有直接使用32位进行比较,其实本质上还是定时器超时时间减去系统流逝时间,若超时时间小于系统流逝时间,则直接置0;
b、判断是否为循环定时器超时时间为0,是,则调用osal_set_event()向主循环注入任务事件,并reloadTimeout;
c、判断是否是普通定时器超时,是,则调用osal_set_event()向主循环注入任务事件,并删除定时器释放内存。

转载于:https://www.cnblogs.com/zzmx/p/4974739.html

    推荐阅读