在基於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循環這樣的運行了起來。
