摘要: 1、任務調度:osal采用一個鏈表結構來管理協(xié)議棧各層相應任務。相關操作函數有,添加任務到鏈表中;獲取下一個活動任務;根據taskID查找下一個任務。osal采用輪詢任務調度隊列(任務鏈表),通過兩個函數:調度程序主循環(huán)函數和設置事件發(fā)生標志函數。 2、時間管理:通過為事件設置超時等待時間,一旦等待時間結束,便為對應任務設置事件發(fā)生標志,從而達到對事件進行延時處理目的。 3、原語通信:請求響應原語操作:一旦調用了下層相關函數后,就立即返回。下層處理函數在操作結束后,將結果以消息的形式發(fā)送到上層并產生一個系統(tǒng)事件,調度程序發(fā)現(xiàn)這個事件后就會調用相應的事件處理函數對它進行處理。兩個相關函數:向目標任務發(fā)送消息的函數;消息提取函數。
一、操作系統(tǒng)介紹 目前TinyOS操作系統(tǒng)支持的平臺有ATMEL公司的AVR系列、TI公司的MSP430系列。由于TinyOS操作系統(tǒng)還沒有對Chipcon公司(才知道TI把它收購了)提供CC2430開發(fā)平臺提供支持,因此,要在CC2430開發(fā)平臺上使用TinyOS系統(tǒng)來開發(fā)Zigbee協(xié)議棧軟件,就必須首先對TinyOS進行移植?;页B闊?img doc360img-src='http://image57.360doc.com/DownloadImg/2012/11/3009/28576546_2.gif' alt="OSAL調度機制 - 小峰 - happy~" src="http://image57.360doc.com/DownloadImg/2012/11/3009/28576546_2.gif" __1354239570243__="ev_4380742244">…… 因此Chipcon公司為自己設計的ZStack協(xié)議棧中提供了一個名為操作系統(tǒng)抽象層OSAL的協(xié)議棧調度程序。 //------------------------------------------------------------------------------------- 二、下面分析下這個協(xié)議棧調度程序(OSAL)的調度機制。 三部分:1、任務調度 2、時間管理 3、原語通信 (一)任務調度 //每層任務=對應事件處理函數 //任務鏈表,任務按優(yōu)先級插入 OSAL采用一個鏈表結構來管理協(xié)議棧各層相應的任務。鏈表中的每一項是一個結構體,用來記錄鏈表中相關任務的基本信息。鏈表的建立是按照任務優(yōu)先級從高到低的順序進行插入的。優(yōu)先級高的任務將被插入到優(yōu)先級低的任務前面。如果倆任務優(yōu)先級相同,則按照時間順序加入到鏈表中。那么這個任務鏈表在系統(tǒng)啟動的時候建立,一旦建立后便一直存在于事個系統(tǒng)運行的過程中,直到系統(tǒng)關閉或硬件復位才被銷毀。 鏈表中的每一項數據結構聲明: typedef void (*pTaskInitFn)(unsigned char task_id) ; //指向任務初始化函數 typedef struct osalTaskRec //------------------------------------------------------------------------------------- 對于pfnInit,是指向相關層任務初始化函數的指針,比如: 網絡層中,任務初始化函數為nwkInit(),用來對網絡層相關數據進行初始化操作。函數聲明為 extern void nwkInit(byte task_id); //task_id表示為網絡層任務分配的唯一任務號 //------------------------------------------------------------------------------------- 網絡層中,事件處理函數nwk_event_loop(),用來處理與網絡層相關的各種事件。函數聲明為 extern void nwk_event_loop(byte task_id, uint16 event_flag); //event_flag標志需要在網絡層處理的事件 //------------------------------------------------------------------------------------- 上面記錄的是鏈表中的每一項數據結構,與任務鏈表有關的主要操作有:添加任務到列表中;獲取下一個活動任務;根據taskID值查找相應的任務。 (1)在任務管理列表中添加任務 這個函數遍歷整個任務隊列鏈表,并按照優(yōu)先級的高低將優(yōu)先級高的任務插入到優(yōu)先級低的任務前面;否則,就將任務插入到鏈表的尾部。在這個過程中,將為每個任務分配一個唯一的任務號。函數聲明為: Extern osalTaskAdd(pTaskInitFn pfnInit,pTaskEventHandleFn pfnEventProcessor,byte taskPriorty);
(2)獲取下一個活動任務 這個函數將根據osalTaskRec_t結構中的events標記來獲取任務隊列中下一個要執(zhí)行的任務。函數聲明: Extern osalTaskRec_t *osalNextActiveTask(void) ; (3)根據taskID查找任務 這個函數將根據任務列表在建立過程中為協(xié)議棧中每個任務分配的任務號,來查找對應任務。函數聲明: Extern osalTaskRec_t *osalFindTask(byte taskID); 當任務鏈表建立成功后,系統(tǒng)便開始運行。如果在系統(tǒng)運行的過程中有事件發(fā)生,系統(tǒng)就會通過調用相應的任務,即事件處理函數,對所發(fā)生的事件進行相應處理。在整個運行過程中,調度程序(OSAL)始終不停地輪詢任務隊列鏈表,以發(fā)現(xiàn)需要處理的事件。這個過程涉及兩個函數操作: 1、調度程序主循環(huán)函數 2、設置事件發(fā)生標志函數
(1)系統(tǒng)主循環(huán) 這個函數始終不停地輪詢隊列鏈表,來處理系統(tǒng)發(fā)生的各種事件。函數聲明和部分實現(xiàn)如下: extern void osal_start_system(void); //無限循環(huán) for(; ; ) { activeTask=osalNextActiveTask(); if(activeTask) { StoreDisableInts; events=activeTask—>events; activeTask—>events=0; if(events!=0) { (activeTask—>pfnEventProcessor)(activeTask—>taskID,events); RestoreInts; } } } (2)設置事件發(fā)生標志 當協(xié)議棧中有任何事件發(fā)生時,我們可以通過設置osalTaskRec_t結構中的events來標記有事件發(fā)生,以便主循環(huán)函數能夠及時加以處理。函數聲明如下: extern byte osal_set_event(byte task_id,uint16 event_flag);
(二)時間管理 協(xié)議棧中的每層都會有很多不同的事件發(fā)生,這些事件發(fā)生的時間順序各不相同。很多時候,事件并不要求立即得到處理,而是經過一定的時間后再進行處理。OSAL調度程序設計了與時間管理相關的函數,用來各種不同的要被處理的事件。 對事件進行時間管理,OSAL也采用了鏈表的方式進行,有時發(fā)生一個要被處理的事件,就啟動一個邏輯上的定時器,并將此定時器添加到鏈表當中。利用硬件定時器作為時間操作的基本單元。設置時間操作的最小精度為1ms,每1ms硬件定時器便產生一個時間中斷,在時間中斷處理程序中去更新定時器鏈表。每次更新,就將鏈表中的每一項時間計數減1,如果發(fā)現(xiàn)定時器鏈表中有某一表項時間計數已減到0,則將這個定時器從鏈表中刪除,并設置相應的事件標志。這樣任務調度程序便可以根據事件標志進行相應的事件處理。具體參見關于“系統(tǒng)時鐘”的記錄。 時間管理函數: extern byte osal_start_timer(byte task_id, uint16 event_id, uint16 timeout_value); 這個函數為事件event_id設置超時等待時間timeout_value。一旦等待結束,便為task_id所對應的任務設置相應的事件發(fā)生標記,再對事件進行相應處理。
(三)原語通信 (原語只是一個理論層面上的術語,描述了服務層次的關系,以及兩個通信的N用戶和它們相連的N層(子層)對待協(xié)議實體之間的關系。初學時總是想不通原語跟協(xié)議棧的代碼有什么關系,后來才了解了原語只是規(guī)范里面的一個術語,反映到協(xié)議棧代碼里就是一個個具體的函數了!例如我們可以看到很多原語是以request,confirm等為后綴的,到了程序里面就是相應的request請求函數,confirm確認函數了。) 對請求(request)、響應(response)原語可以直接使用函數調用來實現(xiàn) 對確認(confirm)、指示(indication)原語則需采用間接處理機制來完成 一個原語的操作往往需要逐層調用下層函數并根據下層返回的結果來進行進一步的操作。在這種情況下,一個原主的操作從發(fā)起到完成需要很長時間。因此,如果讓程序一直等待下層返回的結果再進一步處理,會使微處理器大部分時間處于循環(huán)等待之中,無法及時處理其它請求。 因此,與請求、響應原語操作相對應的函數,一旦調用了下層相關函數后,就立即返回。下層處理函數在操作結束后,將結果以消息的形式發(fā)送到上層并產生一個系統(tǒng)事件,調度程序發(fā)現(xiàn)這個事件后就會調用相應的事件處理函數對它進行處理。(調用就返回,而不管函數有沒有處理完成。當函數處理完成后將結果以消息的形式發(fā)送到上層產生一個系統(tǒng)事件)。 OSAL調度程序用兩個相關的函數來完成這個過程: 1、向目標任務發(fā)送消息的函數 這個函數主要用來將原語操作結果以消息的形式往上層任務發(fā)送,并產生一個系統(tǒng)事件來通知調度程序。函數聲明如下: extern byte osal_msg_send(byte destination_task,byte *msg_ptr,byte len); 參數destination_task是目標任務的任務號,參數指針msg_ptr指向要被發(fā)送的消息,參數len為消息長度
2、消息提取函數 這個消息用來從內存空間中提取相應的消息。其中消息結構和函數聲明如下: typedef struct { byte task_id; byte dst_task_id; byte send_len; }osal_msg_rec_header_t;
typedef struct { osal_msg_rec_header_t hdr; byte *msg_ptr; }osal_msg_received_t; //消息結構(上面結構體包含在里面)
extern osal_msg_received_t osal_rcvd; //全局變量
extern osal_msg_received_t *osal_msg_receive(byte task_id); //接收任務
這個函數返回一個指向osal_msg_received結構的指針,通過msg_ptr這個指針就可以提取出所需要的信息。(有一個例子,是以MAC層返回原語MCPS_DA
說明:本文作者所記錄,錯誤處還請高手指點,本人隨時更新,轉載請注明出處。 本文《OSAL調度機制》主要內容參考廈門大學閆沫的《zigbee協(xié)議棧分析與設計》 參考資料:《zigbee技術基礎及案例分析》;《zigbee協(xié)議棧分析與設計》; |
|