1、應(yīng)用層是一個任務(wù),它有一個系統(tǒng)分配給他的數(shù)值唯一的編號叫任務(wù)ID 2、任務(wù)可以處理事件,處理事件的這些代碼都在一個函數(shù)里,這個函數(shù)叫任務(wù)事件處理函數(shù) 3、應(yīng)用層任務(wù)還有一個 2個字節(jié)的變量 —任務(wù)事件變量
4、應(yīng)用層任務(wù)事件變量 和 應(yīng)用層定義的事件的關(guān)系,如果事件變量和某個事件的宏值(該宏定義事先定義好)與操作為1,那么表示應(yīng)用層任務(wù)將要處理這個事件。對應(yīng)SimonApp_PRocessEvent函數(shù)!
5、而系統(tǒng)在運行的時候會不斷的去讀應(yīng)用層任務(wù)事件變量,當(dāng)它發(fā)現(xiàn)這個變量為0就認(rèn)為,應(yīng)用層任務(wù)當(dāng)前沒有事件需要去處理,如果發(fā)現(xiàn)這個變量不為0,它就認(rèn)為應(yīng)用層任務(wù)有事件將要去處理,它就會去調(diào)用應(yīng)用層任務(wù)事件處理函數(shù)UINT16 SimonApp_ProcessEvent( byte task_id, UINT16 events ),并且把任務(wù)事件變量的值傳給events;在這個事件處理函數(shù)里,events;會分別和應(yīng)用層定義的所有事件宏值進行與操作,如果發(fā)現(xiàn)那個不為0,那么就去執(zhí)行這個事件處理的相應(yīng)代碼。對應(yīng)如下代碼:
6、任務(wù)事件處理函數(shù)是一個數(shù)組,程序員提前定義好! 在OSAL_SimonApp.c中,const pTaskEventHandlerFn tasksArr[]數(shù)組是一個函數(shù)指針數(shù)組!一般應(yīng)用層的任務(wù)事件處理函數(shù)指針添加在末尾,下標(biāo)顯然是8,一般來說整個函數(shù)指針數(shù)組有9個元素!
// The order in this table must be identical to the task initialization calls below in osalInitTask.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 SimonApp_ProcessEvent};7、任務(wù)數(shù)常量和任務(wù)事件變量 雖然任務(wù)事件處理函數(shù)指針數(shù)組確定好了,但是任務(wù)事件變量數(shù)組還沒有定義,所以需要定義一個事件變量數(shù)組(或者動態(tài)內(nèi)存分配),但是在定義數(shù)組的時候,需要指定要分配的內(nèi)存大小(元素個數(shù)),根據(jù)函數(shù)指針數(shù)組tasksArr確定需要多少個元素,然后再分配相應(yīng)的內(nèi)存空間!對應(yīng)OSAL_SimonApp.c中如下代碼:
const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );uint16 *tasksEvents;以及
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));8、osal_set_event(SimonApp_TaskID,SimonApp_SEND_MSG_EVT); 為什么調(diào)用上面的設(shè)置任務(wù)事件函數(shù),SimonApp_TaskID就會去執(zhí)行SimonApp_SEND_MSG_EVT事件相應(yīng)的處理代碼。 這個函數(shù)的本質(zhì)是,把SimonApp_TaskID(應(yīng)用層任務(wù))的任務(wù)事件變量中對應(yīng)于SimonApp_SEND_MSG_EVT宏值為1的那個位變成1,這樣的話首先這個任務(wù)事件變量就變成了非0,系統(tǒng)在檢測到任務(wù)事件變量為非0,就會去調(diào)用任務(wù)事件處理函數(shù)SimonApp_ProcessEvent,在這個函數(shù)里,任務(wù)事件變量肯定和SimonApp_SEND_MSG_EVT宏值與操作為1,所以必定會執(zhí)行處理這個事件相關(guān)的代碼。
9、幾乎每一個層都是一個任務(wù),那么每一個層都有1個任務(wù)ID、 任務(wù)事件處理函數(shù) 、 任務(wù)事件變量。
UN函數(shù)數(shù)組={任務(wù)事件處理A,任務(wù)事件處理B,任務(wù)事件處理C..}
Arr變量數(shù)組={任務(wù)事件變量a,任務(wù)事件變量b,任務(wù)事件變量c..} 任務(wù)ID系統(tǒng)不是隨便分配,我們可以通過這個值立即找到這個任務(wù)自己的任務(wù)事件處理函數(shù)和事件變量。 對應(yīng)關(guān)系是:FUN[0]<—> Arr[0]
應(yīng)用層任務(wù)的任務(wù)ID是8。 FUN[8]<—–> Arr[8] tasksArr[8]就是我們應(yīng)用層事件處理函數(shù) tasksEvents[8]就是我們應(yīng)用層事件變量
10、關(guān)注2個函數(shù) (1)osal_init_system,在這個函數(shù)里的osalInitTasks,系統(tǒng)給所有任務(wù)分配任務(wù)ID.
void osalInitTasks( void ){ uint8 taskID = 0; tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt); osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt)); macTaskInit( taskID++ ); nwk_init( taskID++ ); Hal_Init( taskID++ );#if defined( MT_TASK ) MT_TaskInit( taskID++ );#endif APS_Init( taskID++ );#if defined ( ZIGBEE_FRAGMENTATION ) APSF_Init( taskID++ );#endif ZDApp_Init( taskID++ );#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT ) ZDNwkMgr_Init( taskID++ );#endif SimonApp_Init( taskID );}(2)osal_start_system();
所以ZSTACK協(xié)議棧在穩(wěn)定工作時,它行為是 在 for(;;) {
} 死循環(huán)里,不斷去讀所有任務(wù)的任務(wù)事件變量,如果發(fā)現(xiàn)所有任務(wù)的任務(wù)事件變量都為0,沒問題,說明所有任務(wù)都沒有事件將要去處理,再次重逢這個過程,直到發(fā)現(xiàn)某個任務(wù)事件變量不為0,就會通過不為0的這個任務(wù)ID找到這個任務(wù)事件處理函數(shù),去處理相應(yīng)的事件。
void osal_start_system( void ){#if !defined ( ZBIT ) && !defined ( UBIT ) for(;;) // Forever Loop#endif { uint8 idx = 0; osalTimeUpdate(); Hal_ProcessPoll(); // This replaces MT_SerialPoll() and osal_check_timer(). do { if (tasksEvents[idx]) // Task is highest priority that is ready. { break; } } while (++idx < tasksCnt); if (idx < tasksCnt) { uint16 events; halIntState_t intState; HAL_ENTER_CRITICAL_SECTION(intState); events = tasksEvents[idx]; tasksEvents[idx] = 0; // Clear the Events for this task. HAL_EXIT_CRITICAL_SECTION(intState); events = (tasksArr[idx])( idx, events ); HAL_ENTER_CRITICAL_SECTION(intState); tasksEvents[idx] |= events; // Add back unprocessed events to the current task. HAL_EXIT_CRITICAL_SECTION(intState); }#if defined( POWER_SAVING ) else // Complete pass through all task events with no activity? { osal_pwrmgr_powerconserve(); // Put the processor/system into sleep }#endif }}新聞熱點
疑難解答