在基于zigbee协议栈的应用程序开发过程中,用户只需要实现应用层的开发即可,zigbee应用程序框架中包含了最多240个应用程序对象,每个应用程序对象运行在不同的端口上,因此端口的最作用是区分不同的应用程序对象,可以把一个应用程序对象看成为一个任务。因此,需要一个机制来实现任务的切换、同步和互斥,这就是OSAL产生的根源。
OSAL用一句话来说就是指支持多任务运行的系统资源分配机制。OSAL中有三个参数非常重要,即:tasksCnt、tasksEvent[]和tasksArr[]。
(1)tasksCnt:该变量用于保存任务总数;在Samples\GenericApp\CC2530DB\中可以可以看到
const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] ); //将总任务数赋值给tasksCnt
(2)tasksEvent[]:是一个数组,其中每一项表示与其相对应的任务发生的事件,例如 tasksEvent[1]=2,则表示任务1发生了事件2。
(3)tasksArr[]:是一个指针数组,其中每一项均指向对应任务的事件处理函数,例如tasksArr[1]的值为任务1的事件处理函数的地址。在Samples\GenericApp\CC2530DB\中可以可以看到:
const pTaskEventHandlerFn tasksArr[] =
{
macEventLoop,
nwk_event_loop,
Hal_ProcessEvent,
#if defined( MT_TASK )
MT_ProcessEvent,
#endif
APS_event_loop,
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_ProcessEvent,
#endif
ZDApp_event_loop,
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_event_loop,
#endif
GenericApp_ProcessEvent
};
用户自己创建的任务GenericApp的事件处理函数GenericApp_ProcessEvent()的地址赋值给了tasksArr[]中的对应项。
在ZMain.c中找到主函数,在主函数中调用了 osal_start_system(),进入该函数,可以看到for死循环中调用了 osal_run_system()函数,进入该函数,去掉一些不必要的代码后如下
void osal_run_system( void )
{
uint8 idx = 0; //任务索引
osalTimeUpdate(); Hal_ProcessPoll();
do {
if (tasksEvents[idx]) // 不断查询各个任务当前发生的事件是否为0(在系统初始化过程中把各个任务的事件初始化为0 )
{
break; //有任务发生的事件不为0,则跳出do-while循环
}
} while (++idx < tasksCnt);
if (idx < tasksCnt)
{
uint16 events;
events = tasksEvents[idx];
tasksEvents[idx] = 0; // 重置该任务事件为0.
events = (tasksArr[idx])( idx, events ); //调用该任务事件处理函数
tasksEvents[idx] |= events; //返回没有处理的事件
}
}
在上面的程序中我们可以看到for死循环中,不断查询各个任务的tasksEvents[]来确定各个任务是否有事件发生,如果有事件发生则调用对应任务的事件处理函数。每个任务只有一个事件处理函数,在这一个任务处理函数中对该任务发生的不同事件进行处理。于是OSAL就在for循环这样的运行了起来。