在整个协议栈中,我们通过例子程序可以看到,触发任务的事件主要有以下两种方式,
(1) 通过设置一个“软件定时器”,当其溢出时触发事件 osal_start_timeEx()àosalTimerUpdate()àosal_set_evetn()
(2)通过调用系统消息传递机制触发事件 osal_msg_send()àosal_set_event()
(3) 当然还有可以直接调用osal_set_event(),协议栈中也有很多是利用这种方式。
不过在例子例程和整个协议栈中很少看到,不过上面的两个函数最终都是调用了osal_set_event()函数触发的事件。下面我们首先来看一个soal_set_event()函数。该函数把事件event_flag(这个事件是一个标志位)传递给了task_id所指示的一个任务。表明该任务所需要的事件发生了。
/*********************************************************************
* @fn osal_set_event
*
* @brief
*
* This function is called to set the event flags for a task. The
* event passed in is OR'd into the task's event variable.
*
* @param byte task_id - receiving tasks ID
* @param byte event_flag - what event to set
*
* @return ZSUCCESS, INVALID_TASK
*/
byte osal_set_event( byte task_id, UINT16 event_flag )
{
if ( task_id < tasksCnt )
{
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState); // Hold off interrupts 关闭中断
tasksEvents[task_id] |= event_flag; // Stuff the event bit(s) 填充事件位
HAL_EXIT_CRITICAL_SECTION(intState); // Release interrupts 打开中断
}
else
return ( INVALID_TASK );
return ( ZSUCCESS );
}
通过tasksEvents[task_id] |= event_flag;可以让系统的主循环函数轮询所发生的任务事件,再调用相应任务的事件处理函数进行处理。
在协议栈里面,调用osal_set_event()的函数最主要是两个:
(1)osalTimerUpdate() 这个函数是在应用中经常使用的一种方式 也就是osal_start_timerEx()中调用的。
(2)osal_msg_send()
对于1,当有osal_start_timerEx()在系统软件定时器链表中添加一个软件定时器并启动时,系统通过osalTimerUpdate()对链表中的每一个软件定时器进行减1ms操作,当定时器溢出时,调用osal_set_event()触发事件,如下
/************************
static void osalTimerUpdate( uint16 updateTime )
{
…………
// When timeout, execute the task
if ( srchTimer->timeout == 0 )
{
osal_set_event( srchTimer->task_id, srchTimer->event_flag );
…………
}
/************************
对于2,对msg_ptr一系列处理后,调用osal_set_event()触发事件,该函数把消息msg_ptr(这个消息是一个数据包)传递给了task_id所指示的一个任务。表明把数据包传递给该任务,这个数据包里一般情况下也携带了事件标志event_flag。如下
/************************
byte osal_msg_send( byte destination_task, byte *msg_ptr )
{
…………
osal_set_event( destination_task, SYS_EVENT_MSG );
return ( ZSUCCESS );
}
/***********************
这两种方式都是在最终调用了osal_set_event()函数。我们要知道所有的任务的事件处理函数,都是通过taskArr[idx](idx,events)调用的。主要是设置事件的标志位来触发事件。然后就是在主循环中不停的检测事件的标志位,如果有事件发生了就会调用相应任务的事件处理函数处理。
在下面的文章中我们就分析两个事件的整个的OSAL系统中是怎么被触发的。一个是Key按键的触发,另一个是Timer4的触发,也就是应用程序在调用osal_start_timterEx()函数是触发的事件。
阅读(746) | 评论(0) | 转发(0) |