OSAL運行原理:
前提:OSAL是按照不同層運行的。分別是應用層(App)、硬件層(HAL)、mac層(MAC).......等多個層。我們現在把每一層可以當成一個任務。也可以比喻每一層是一個房間。
開始運行:程序從main函數開始執行,一開始是初始化各個模塊。然後初始化osal_init_system(),在這個函數裏主要給各個層(各個房間)定義任務ID號。從0開始 假設應用層被分到的任務號是8。開始運行OSAL也就是這個函數osal_start_system();在這個函數裏用了一個for循環這條語句for(;;),for循環就是來觀察哪一層(哪個房間)有事件發生就去處理哪個層(房間)。這就是像高中老師查宿舍一下,如果哪個房間有聲音、不熄燈等, 老師就去處理,否則一直在走廊來回檢查。
重點內容:我們人很複雜可以通過眼睛、耳朵等知道房間有事情發生,但是程序不知道。它是怎麼處理的呢?
先來介紹 每一層(房間)可能發生的事情或者處理的事情怎麼表示。
其中tasksArr[]是函數指針。每個層(房間)會發生或者處理各種事情,比如應用層(應用房間)會處理模塊類型,還有其他的事情。所有應用層能處理的事情用一個函數a來運行,所有硬件層處理的事物也用一個函數b表示,其它層分別是函數c、函數d等等那麼我們把函數a,函數b,函數c。。。他們的地址放到tasksArr[]中。假設函數a的地址是100,函數b的地址是101,函數c的地址是102。。。。。等等 只要調用使用100 就會執行函數a,以此類推只要調用108就會執行函數h。
實際代碼如下:
const pTaskEventHandlerFn tasksArr[] = {
macEventLoop, // tasksArr[0] 對應房間100號
nwk_event_loop, // tasksArr[1] 對應房間101號
Hal_ProcessEvent, // tasksArr[2] 對應房間102號
#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 // tasksArr[8] 對應房間108號
};
現在我們來解決剛纔提出的問題,檢查老師眼耳並用可以知道房間情況。OSAL它怎麼知道去各個層執行相應事件的呢,
這需要用到另一個變量tasksEvents[],這個變量也是一個數組,並且與剛纔的tasksArr[ ] 數組一一對應。即
tasksEvents[0]--------------對應tasksArr[0]
tasksEvents[1]--------------對應tasksArr[1]
tasksEvents[2]--------------對應tasksArr[2]
tasksEvents[3]--------------對應tasksArr[3]
也就是說tasksEvents正常爲0,當不爲0時說明對應層有事件發生。比如 tasksEvents[8]不爲0,程序就到tasksArr[8] 也就是108去執行了。
在for循環裏面有一個do。。。。while循環,就是檢測tasksEvents[]數組變量不爲零,拿到ID號去對應房間處理事件。
比喻:老師不在去房間走廊檢查,每個房間都有一個特殊的指示燈(這個指示燈是2個字節,也就是說可以亮16種顏色)放在老師辦公室,老師只需要在辦公室檢查這些指示燈。如果 tasksEvents[8]指示燈亮就知道108房間有事件處理。
以上是個人理解OSAL運行的。那麼指示燈怎麼亮起來的,我們也叫事件的捕獲