Chinaunix首页 | 论坛 | 博客
  • 博客访问: 72403
  • 博文数量: 11
  • 博客积分: 210
  • 博客等级: 入伍新兵
  • 技术积分: 94
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-19 18:13
文章分类
文章存档

2013年(4)

2012年(2)

2011年(5)

分类: 嵌入式

2011-12-15 19:51:45

ESB为例:CPUmsp430, 射频芯片为Tr1001。相关代码在/platform/esb 以及 /cpu/msp430 /core/net

contiki-conf.h中首先对各层的协议栈进行了定义。

如下:

#define NETSTACK_CONF_RADIO     tr1001_driver

#define NETSTACK_CONF_NETWORK  uip_driver

#define NETSTACK_CONF_MAC      nullmac_driver

#define NETSTACK_CONF_RDC       nullrdc_driver

 

一、           收包流程

下面我们从主函数Contiki-esb-main.c开始,先说数据的接收流程。

首先,定义一块网卡:

static struct uip_fw_netif tr1001if =

  {UIP_FW_NETIF(0,0,0,0, 0,0,0,0, uip_driver_send)};

其中uip_driver_send就是这块网卡的发包函数。

在主函数中会进行协议栈的初始化,另外开启几个关于收发数据的进程。

int main(void)

{

  msp430_cpu_init();

  process_start(&etimer_process, NULL);

  netstack_init();

  init_uip_net();

  autostart_start(autostart_processes);

  watchdog_start();

  while(1) {

    int r;

    do {

      /* Reset watchdog. */

      watchdog_periodic();

      r = process_run();

    } while(r > 0);

  return 0;

}

其中,init_uip_net() 中启动了两个进程如下:

static void init_uip_net(void)

{

  process_start(&tcpip_process, NULL);

  process_start(&uip_fw_process, NULL);

}

这两个进程我们在以后会用到。


 

netstack_init()如下:

void netstack_init(void)

{

  NETSTACK_RADIO.init();

  NETSTACK_RDC.init();

  NETSTACK_MAC.init();

  NETSTACK_NETWORK.init();

}

即,netstack_init会对各层驱动均进行初始化。

下面,主要说Radio层的驱动初始化:

Int tr1001_init(void)

{

  PT_INIT(&rxhandler_pt);

  process_start(&tr1001_process, NULL);

  return 1;

}

该初始化过程中启动了 tr1001_process 如下:

PROCESS_THREAD(tr1001_process, ev, data)

{

  PROCESS_BEGIN();

  while(1) {

    PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);

    packetbuf_clear();

    len = tr1001_read(packetbuf_dataptr(), PACKETBUF_SIZE);  // 读取数据

    if(len > 0) {

      packetbuf_set_datalen(len);

      NETSTACK_RDC.input();                         // 向上提交

    }

  }

  PROCESS_END();

}

当该进程收到事件ev == PROCESS_EVENT_POLL时,就会从射频芯片读数据。

我们知道,射频芯片每收到一个frame,都会向cpu 发送一个中断,进而CPU将收到的数据读走。下面,看这个PROCESS_EVENT_POLL事件的产生过程。

中断注册函数如下:

interrupt (UART0RX_VECTOR)

     tr1001_rxhandler(void)

{

  ENERGEST_ON(ENERGEST_TYPE_IRQ);

  tr1001_default_rxhandler_pt(RXBUF0);

  if(tr1001_rxstate == RXSTATE_FULL) {

    LPM4_EXIT;

  }

  ENERGEST_OFF(ENERGEST_TYPE_IRQ);

}

 

Char tr1001_default_rxhandler_pt(unsigned char incoming_byte))

{

    static unsigned char rxtmp, tmppos;

    if(rxcrctmp == rxcrc) {

      /* A full packet has been received and the CRC checks out. We'll

           request the driver to take care of the incoming data. */

      RIMESTATS_ADD(llrx);

      process_poll(&tr1001_process);

      PT_END(&rxhandler_pt);

}

 

归结如下:

 

到这里,radio层的收包过程就结束了。通过 NETSTACK_RDC.input() 将数据提交到rdc层。

进入函数:nullrdc_driver.input() core\net\mac 下的 nullrdc.c 中的packet_input

static void  packet_input(void)

{

    NETSTACK_MAC.input();

}

提交给mac层继续处理。进入函数nullmac_driver.input(),即core\net\mac 下的 nullmac.c 中的packet_input

static void packet_input(void)

{

  NETSTACK_NETWORK.input();

}

提交给网络层进行处理。进入函数uip_driver.input(), platform/esb/net/uip_dirver.c 中的 input函数。


 

static void input(void)

{

  if(packetbuf_datalen() > 0 && packetbuf_datalen() <= UIP_BUFSIZE - UIP_LLH_LEN) {

    memcpy(&uip_buf[UIP_LLH_LEN], packetbuf_dataptr(), packetbuf_datalen());

    uip_len = hc_inflate(&uip_buf[UIP_LLH_LEN], packetbuf_datalen());

    tcpip_input();

  }

}

Void tcpip_input(void)

{

  process_post_synch(&tcpip_process, PACKET_INPUT, NULL);

}

Tcpip_input 向进程tcpip_process 传递消息PACKET_INPUT。(下面三个函数均位于/core/net/tcpip.c

PROCESS_THREAD(tcpip_process, ev, data)

{

  PROCESS_BEGIN();

  tcpip_event = process_alloc_event();

  while(1) {

    PROCESS_YIELD();

    eventhandler(ev, data);

  }

  PROCESS_END();

}

/*---------------------------------------------------------------------------*/

static void

eventhandler(process_event_t ev, process_data_t data)

{

  switch(ev) {

    case PROCESS_EVENT_EXITED:  …

    case PROCESS_EVENT_TIMER:  ….

    case TCP_POLL:   …

    case UDP_POLL:  ...

    case PACKET_INPUT:

      packet_input();

      break;

  };

}

static void

packet_input(void)

{

  if(uip_len > 0) {

    tcpip_is_forwarding = 1;

    if(uip_fw_forward() == UIP_FW_LOCAL) {    //  这里执行路由和转发

      tcpip_is_forwarding = 0;

      check_for_tcp_syn();

      uip_input();

      if(uip_len > 0) {

        tcpip_output();

      }

    }

    tcpip_is_forwarding = 0;

  }

}

uip_input,至此数据成功的转交到UIP协议栈进行处理。在uip_porcess 中会把数据包分发到不同的应用程序中。

以上的过程总结如下:

 

Uip_process中会对网络层以及传输层的包头进行分析,并提交给应用程序。

至此,数据的接收流程结束。


 

阅读(3178) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~