本文介紹了contiki netstack的MAC層如下數據收發層次結構,並討論如何移植新的無線器件作爲contiki的無線收發器。網絡
contiki能夠在contiki-conf.h中進行配置ui
#define NETSTACK_CONF_NETWORK rime_driver //使用rime協議棧 #define NETSTACK_CONF_MAC nullmac_driver //不使用mac層協議 #define NETSTACK_CONF_RDC contikimac_driver //使用contikimac rdc #define NETSTACK_CONF_FRAMER framer_nrf24 //使用nrf24的frame結構 #define NETSTACK_CONF_RADIO nrf24_radio_driver //使用nrf24作爲無線器件
NETSTACK_CONF_RADIOspa
定義contiki netstack使用的無線通訊器件,這一層的驅動通常只完成物理層上的收發控制。其定義的原型在radio.h中:.net
struct radio_driver { int (* init)(void); /** Prepare the radio with a packet to be sent. */ int (* prepare)(const void *payload, unsigned short payload_len); /** Send the packet that has previously been prepared. */ int (* transmit)(unsigned short transmit_len); /** Prepare & transmit a packet. */ int (* send)(const void *payload, unsigned short payload_len); /** Read a received packet into a buffer. */ int (* read)(void *buf, unsigned short buf_len); /** Perform a Clear-Channel Assessment (CCA) to find out if there is a packet in the air or not. */ int (* channel_clear)(void); /** Check if the radio driver is currently receiving a packet */ int (* receiving_packet)(void); /** Check if the radio driver has just received a packet */ int (* pending_packet)(void); /** Turn the radio on. */ int (* on)(void); /** Turn the radio off. */ int (* off)(void); };
NETSTACK_CONF_FRAMERcode
定義使用radio driver的frame格式,這一層完成對數據幀的解析和打包,原型定義在framer.h中orm
struct framer { int (* create)(void); int (* parse)(void); };
NETSTACK_CONF_RDCip
radio duty cycling, RDC層,從radio層獲取數據,並經過framer解析。RDC將要發送的數據經過parser打包並經過radio層發送。RDC提供無線傳感的省電duty cycling。contiki提供瞭如下的rdc mac協議:get
其中nullrdc_driver不作任何duty cycling動做。原型
NETSTACK_CONF_MAC同步
MAC層主要是完成,防碰撞的協議,contiki提供如下的MAC協議:
其中nullmac_driver不作任何防碰撞,直接轉發數據
RDC層/MAC層/NETSTACK層的代碼contiki提供,若是沒有特殊的需求不用作修改和添加,主要的移植工做集中在Framer和radio層.
framer層,完成數據發送前的封包和接收後的解析,在nrf24l01同步等的framer結構都在nrf24l01的硬件中處理,所以定義的framer結構只與地址和payload有關
數據frame結構:
create frame時,RDC將MAC層要發送的數據加上dst addr和src addr後送到radio。
parser frame時,從中解析出dst addr和src addr,而後將actual payload送到MAC層。
按照上述作法實現
const struct framer framer_nrf24 = { create, parse };
driver層
不用考慮任何數據鏈路層和網絡層的內容,只作很單純的收發動做,所以按照struct radio_driver的要求實現各個API便可:
const struct radio_driver nrf24_radio_driver = { nrf24_radio_init, nrf24_radio_prepare, nrf24_radio_transmit, nrf24_radio_send, nrf24_radio_read, nrf24_radio_channel_clear, nrf24_radio_receiving_packet, nrf24_radio_pending_packet, nrf24_radio_on, nrf24_radio_off, };
因爲nrf24l01沒有廣播地址的概念,所以將nrf24l01的pipe0作爲點對點數據, pipe1作爲廣播數據。也就是將全部節點的pipe0地址設置爲本身獨有的,因此節點的pipe1的地址設置爲相同的,這樣針對pipe1地址發送數據,全部節點都能收到,則實現了廣播
nrf24l01按照本身的pipe地址設置選擇和接收數據,所以nrf24l01只知道本身的地址是什麼,不知道發送者是誰,因此實際nrf24l01要經過RF發送的數據須要包含src address。所以將frame數據去掉dst進行發送:
nrf24l01將dst address設置入硬件寄存器,nrf24l01會自動將數據發送到指定的地址。
從發送的數據格式能夠看出nrf24l01經過RF收到的數據也是沒有dst addr的,但nrf24l01只收本身地址的數據,因此dst addr也就知道是什麼,所以nrf24l01收到數據後,根據收到數據的pipe,爲數據加上dst addr而後送到RDC層,再由frame來解包。
RDC層直接使用contikimac
MAC層使用nullmac,由於nrf24l01自已後碰撞和可靠接收的硬件機制所以MAC層不用再作動做,直接轉發到NETSTACK層便可
NETSTACK用什麼,看具體狀況,能夠選擇uip也可用rime等等。
關於nrf24l01一個packet的長度
nrf24l01能發送的淨payload爲32byte,爲了適應在contiki,要從其中分出3~5個byte放src addr,在個人移植中定義爲4,所以nrf24l01發送一個包最長爲28byte
本文從contiki收發數據的層級介紹了contiki netstack的數據收發層級。並簡單介紹了nrf24l01做爲contiki radio的移植方法。nrf24l01要以28byte做爲淨數據來作爲contiki的radio是否可行,還須要進一步探討。