contiki netstack数据收发结构

 

摘要

本文介绍了contiki netstack的MAC层以下数据收发层次结构,并讨论如何移植新的无线器件做为contiki的无线收发器。

正文

contiki netstack的数据收发层级

 

image

  • Radio:主要完成物理层无线数据的收发和控制
  • Framer: 完成对数据帧的打包和解析
  • RDC: radio duty cycling, 周期性访问radio,主要为了减少功耗
  • MAC: 数据链路层
  • Netstack: 网络协议栈

contiki内各层级的配置与用处

contiki可以在contiki-conf.h中进行配置

#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_RADIO

定义contiki netstack使用的无线通信器件,这一层的驱动一般只完成物理层上的收发控制。其定义的原型在radio.h中:

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_FRAMER

定义使用radio driver的frame格式,这一层完成对数据帧的解析和打包,原型定义在framer.h中

struct framer {
  int (* create)(void);
  int (* parse)(void);
};

NETSTACK_CONF_RDC

radio duty cycling, RDC层,从radio层获取数据,并通过framer解析。RDC将要发送的数据通过parser打包并通过radio层发送。RDC提供无线传感的省电duty cycling。contiki提供了以下的rdc mac协议:

  • sicslowmac_driver
  • contikimac_driver
  • cxmac_driver
  • lpp_driver
  • nullrdc_driver

其中nullrdc_driver不做任何duty cycling动作。

NETSTACK_CONF_MAC

MAC层主要是完成,防碰撞的协议,contiki提供以下的MAC协议:

  • csma_driver
  • nullmac_driver

其中nullmac_driver不做任何防碰撞,直接转发数据

针对nrf24l01,NETSTACK收发各层级的移植

RDC层/MAC层/NETSTACK层的代码contiki提供,如果没有特殊的需求不用做修改和添加,主要的移植工作集中在Framer和radio层.

framer层,完成数据发送前的封包和接收后的解析,在nrf24l01同步等的framer结构都在nrf24l01的硬件中处理,因此定义的framer结构只与地址和payload有关

数据frame结构:

 

image

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地址发送数据,所有节点都能收到,则实现了广播

 

image

nrf24l01按照自己的pipe地址设置选择和接收数据,因此nrf24l01只知道自己的地址是什么,不知道发送者是谁,所以实际nrf24l01要通过RF发送的数据需要包含src address。因此将frame数据去掉dst进行发送:

image

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是否可行,还需要进一步探讨。

你可能感兴趣的:(contiki netstack数据收发结构)