本文內容來源為contiki英文介紹,自己為了學習,將其大致翻譯成中文,以便了解。
歡迎轉載,轉載請注明來源,如果有什么翻譯不合適的地方,請留言指出,相互交流學習。
介紹
Contiki是一個開放源碼、多任務事件驅動的嵌入式網絡專用操作系統,輕量級的資源占用使得它很適合存儲資源緊張的微控制器。
Contiki由幾個獨立的模塊組成,包括一個類似線程的多任務事件驅動protothread庫,uIP TCP/IP(v4 and v6)協議棧,無線傳感網絡協議棧Rime。
Contiki是為了網絡應用而設計,但也可以基於它的內核開發其他應用。這時它的官方網站。official website
事件
contiki內核是基於事件驅動的,這意味着每個正在執行的應用都對於的一個事件的響應。整個應用包括kernel、libraries、user code可能包含若干個正在執行的進程。
不同的進程通常指執行特定的時間,然后等待事件的發生。在等待期間,進程處於阻塞狀態。當事件發生時,內核將傳遞關於事件發生的消息,並且激活那些等待事件發生的進程。時間可以分為以下三類。
時間事件
一個進程可以設定一個定時器,在指定的時間后產生一個事件,它自己會阻塞,直到時間期滿后,繼續運行。這對於一些周期性的操作或者網絡協議,例如同步相關的問題是,很有幫助。
外部事件
通過微控制器的具有中斷功能的IO口連接的外部設備,當觸發條件滿足時,可以產生事件。例如,一個按鈕、接收射頻數據、加速度檢測計都是可以外部中斷源。進程會依據與這些事件來響應。
內部事件
任何進程都有可能處理其他進程的事件,或者發向自己的事件,這對於進程間通訊很有幫助。一個進程可以通知另一個進程,相關數據已經准備好。
事件一般是被發送的,一個中斷服務程序執行時,可能向其他進程發起一個事件。一個事件通常具有以下幾個信息:
process:事件將要發向的進程,可以發向某一個進程,也可以發向所有登記過的進程。
event type:事件類型,用戶可以針對進程,自定義事件類型,以便於進程區分。例如發送和接收包時的事件
data:可選項,一些數據可能需要隨同事件一起發向進程
進程
進程在Contiki是任務的同義詞。進程機制使用protothread庫。一個進程是一個C函數,很有可能包含一個無限循環和一些阻塞的宏調用。由於Contiki的事件驅動內核不是可搶占的,每個進程在執行時,會獨享處理器,直到它由於等待事件而阻塞。不同的阻塞類型由不同的宏來定義實現。這允許編程狀態機作為一個順序控制流。下面給出的是一個contiki官方網站給出的一般進程結構:
#include "contiki.h" /* The PROCESS() statement defines the process' name. */ PROCESS(my_example_process, "My example process"); /* The AUTOSTART_PROCESS() statement selects what process(es) to start when the module is loaded. */ AUTOSTART_PROCESSES(&my_example_process); /* The PROCESS_THREAD() contains the code of the process. */ PROCESS_THREAD(my_example_process, ev, data) { /* Do not put code before the PROCESS_BEGIN() statement - such code is executed every time the process is invoked. */ PROCESS_BEGIN(); /* Initialize stuff here. */ while(1) { PROCESS_WAIT_EVENT(); /* Do the rest of the stuff here. */ } /* The PROCESS_END() statement must come at the end of the PROCESS_THREAD(). */ PROCESS_END(); }
這段代碼沒做任何事情,僅僅是一個進程的框架結構。重復性的等待事件發生,然后執行,然后再等待….
當使用protothread來編程時,有以下幾點要注意:
1. 本地變量是不保存的。
當一個進程調用一個阻塞宏時,實際上發生的是進程函數已經返回了,控制權交給內核去調度其他進程。當事件發生時,內核會調用相同的進程函數,它會調到發生等待事件,阻塞的地方繼續執行。因此,如果進程的本地變量(非static變量)在阻塞前被賦值,那么,當阻塞后返回時,這些變量保存的值將失效。一個好的解決方法是使用static變量。
2. 不要使用switch語句
protothreads使用本地local continuations去恢復阻塞退出后的堆棧狀態。這是通過switch來實現的。如果case表達式可以放置在任何位置(在if里面或者while段里面),它不能再和其他switch語句混合使用了。因此,在進程函數里面,最好不要使用switch語句。
uIP TCP/IP stack
contiki包含一個輕量級的TCP/IP協議棧,名為uIP。它實現了RFC兼容的IPv4、IPv6、TCP和UDP。后兩者兼容IPv4和IPv6.uIP非常精簡,僅實現最為重要的功能。例如,整個協議棧只有一個buffer,用來接受和發送數據包。
應用API
基於uIP協議棧,有兩種方式來編程。
raw API:uIP raw API適合實現簡單應用。例如一個簡單的能夠監聽一些TCP端口的簡單回顯服務器。隨着不斷的發展,它也可以編寫功能復雜的網絡程序。
protosocket API:protosocket API利用protothread庫來實現更加靈活的TCP/IP應用程序。它提供類似於標准BSN socket的接口,允許在進程中編寫應用。
Lower Layers
擁有TCP/IP功能的協議棧和一些應用程序很好,但是它還可以做的更好。uIP要求一個更低層去和附近節點通訊。有兩種節點。
nodes:在nodes之間通訊需要無線連接。uIP支持無線收發數據包。基於uIP的版本配置,Contiki遵循不同的方向。
1. 當傳輸的為IPv6數據包時,Contiki選擇route-over配置。因此,uIP6使用一個成為sicslowmac的MAC層來處理無線數據包。頭部壓縮技術由6lowpan模塊提供,它可以轉發數據包。
2. 針對IPv4通訊,Contiki選擇mesh-under配置。這由Rime通訊協議棧來負責。Rime提供mesh路由和路由發現,因此,uIP通過它,可以轉發網絡數據包。從IP的角度來看,需要本地網絡的所有傳感器節點、甚至是多跳中繼節點是需要的。
gateways:為了與無線傳感器網絡之外的網絡通訊,網關是必須的。它是連接傳感器網絡和其他網絡的橋梁。在大多數情況下,網關由PC來擔當,當然,它也可以是嵌入式設備。PC和節點通過串口連接,IP數據包使用SLIP在兩者之間傳輸。在PC端,必須允許轉換程序,來轉換串行線路和網絡接口之間的數據轉換。基於uIP的版本,功能有所不同。
1. uIPv6,一個將數據包在射頻數據轉和串行數據之間進行相互轉換的程序是很有必要的,它不需要做任何的地址比較功能,除了IPv6的頭壓縮和解壓機制外(6lowapn),它沒有任何的其他的IP棧。從PC的角度出發,這個節點充當一個以太網的接口,因此,PC可以做任何工作。
2. uIPv4,它的工作機制就完全不同了。連接到PC的節點充當網關的角色,帶有所有的IP棧。它發送的每個數據包,都會檢測它的IP地址。如果數據無線傳感器網絡的范圍,則會通過射頻通道來發送。否則,會通過串行鏈路發給PC。PC上運行的程序將構建一個IP網絡接口。
Rime stack
Rime stack提供一個層次分明的無線網絡協議棧集合,從一個簡單的匿名廣播到復雜的網狀路由.實現這一些列復雜協議肯定需要分層、分模塊來進行的。復雜模塊的實現基於簡單模塊的實現。下圖是Rime協議的概覽。
Rime每個模塊的簡要描述:
1. abc: 異步廣播模塊,它僅僅通過射頻通道發送數據包,從射頻通道接收所有的數據包,並且傳遞給高層協議,屬於Rime中最底層的模塊。
2. broadcast:指定廣播。它向輸出數據包中添加了源地址,並且將數據包傳遞給abc模塊。
3. unicast:往數據包中增加目的地址,並傳遞給broadcast模塊。在接收端,如果接受包的目的地址和節點地址不匹配,則丟棄該包。
4. stunicast:stubborn的單播,當需要向節點發送數據包時,它以一個給定的時間周期,反復的發送數據包,直到被暫停。該模塊不單獨使用,通常由高層來調用。
5. runicast:可靠的單播。它通過調用stunicast來發送數據包,並且等待ACK響應。當接收到ACK響應時,它停止持續的發送數據包。此時,為了避免無限制的發送數據包,需要制定一個最大重傳次數。
6. polite和ipolite:這兩個模塊幾乎是相同的。當一個數據包需要在指定幀中被傳送,這個模塊會等待一半的時間,然后檢查它是否收到了准備要發送的數據包。如果收到了,該數據包不會發送。否則,他會發送數據包。這在避免不必要的重傳中有用處。
7.multihop:這個模塊需要一個路由表功能,當它要發送數據包時,它查找路由表尋找下一跳地址,通過unicast向其發送數據包。當它接收到一個數據包時,如果節點是接收數據包的目標地址,該數據包被傳往上層,否則,它會查找路由表,確定下一跳地址並且轉發它。
MAC layer
正如我們所看到的,uIPv6協議棧使用一個簡單的MAC層協議,成為sicslomac,沒有其他選項。然而,IPv4棧使用Rime作為它的底層協議實現,可以選擇特定的MAC層。
在Contiki中,以下的MAC層已經實現了。
1. nullmac: 正如它名字一樣,它不做其他事情,僅僅是在上層應用和射頻驅動之前轉發數據包。
2. xmac協議:前導采樣協議,節點周期性的監聽射頻通道。
3. lpp協議:probing協議,節點周期性地發送一小段信息,說他們正在監聽,監聽一段時間后,他們轉入休眠狀態。
目前為止的工作情況
在WSN430平台上已經移植並且測試了如下幾點。
1. kernel:基本的contiki工作沒有問題,包括進城處理,不同的時間管理等等。此外,Contiki要求的所有驅動都在WSN430開發包中提供,在Contiki舊的開發包中,這些是系統的一部分,考慮到可維護因素,他們被分離了。
2. uIP:uIP在IPv4和IPv6下工作都沒有問題,TCP和UDP都是可用的。需要注意的一點是,UDP的最大段長度,通常需要設置為128個字節。節點之間的通訊,可以直接通過射頻,或者使用PC連接的gateway。
3. Rime:無線傳感器協議棧部分已經被測試了,一些簡單的模塊能夠正常工作了,例如abc, broadcast, unicast, ipolite, stunicast, runicast, multihop。使用mesh的全部的通訊協議棧已經證實可以在同樣的信道和其他節點協同工作。多跳和路由暫時沒有測試。
4. MAC層:之前提到的四個MAC層協議已經針對WSN430平台配置好了。nullmac, xmac, lpp and sicslomac.
例子
下載
Here is the archives, the Contiki OS ported for the WSN430, along with the examples:
-
-
updated to Contiki_2.4
-
added wsn430v14 support, with cc2420 radio chip
-
added tools to run SLIP from Senslab Virtual Machines
-
網址原文鏈接:http://senstools.gforge.inria.fr/doku.php?id=os:contiki