Contiki的NETWORK层间数据传输流程

Contiki的NETWORK层之间的数据流路径:

Send:

Network->Mac->Rdc(->Frame802154)->Radio

Recv:

Radio->Rdc(->Frame802154)->Mac->Network

注:在此结构中,802154应该是属于RDC层的,

如果不将RDC算作一层,应该是介于Mac和Radio之间。是Mac层的出口。这也是Contiki的一项重要模块之一。在Contiki中ContikiMAC.c模块实现了RDC功能。论文《The ContikiMAC Radio Duty Cycling Protocol》详细描述了RDC的实现与理论基础。

在Contiki中接收采用事件驱动方式。接收通过一个PThread任务,等待数据到来事件,如果数据到来事件触发,则将数据则取出来。这个事件触发是在Radio的中断中设置的。

即:NETSTACK_RDC.input()的调用一般都是在Radio的一个PThread中,由于在Network.open的时候已经将每一层的回调函数设置完备,所以当接收到数据的时候,通过每一层的回调,将数据传递到Network_Network处,即协议栈的最顶部应用层处理。

以contiki\cpu\avr\radio\rf230bb\rf230bb.c文件为例

rf230_interrupt()函数中判断接收到数据, 调用process_poll(&rf230_process),发送PROCESS_EVENT_POLL事件:

[cpp] view plaincopy在CODE上查看代码片

  1. int  

  2. rf230_interrupt(void)  

  3. {  

  4.   /* Poll the receive process, unless the stack thinks the radio is off */  

  5. #if RADIOALWAYSON  

  6. if (RF230_receive_on) {  

  7.   DEBUGFLOW('+');  

  8. #endif  

  9. #if RF230_CONF_TIMESTAMPS  

  10.   interrupt_time = timesynch_time();  

  11.   interrupt_time_set = 1;  

  12. #endif /* RF230_CONF_TIMESTAMPS */  

  13.   

  14.   process_poll(&rf230_process);  

  15.     

  16.   rf230_pending = 1;  

  17.     

  18. #if RADIOSTATS //TODO:This will double count buffered packets  

  19.   RF230_receivepackets++;  

  20. #endif  

  21.   RIMESTATS_ADD(llrx);  

  22.   

  23. #if RADIOALWAYSON  

  24. else {  

  25.   DEBUGFLOW('-');  

  26.   rxframe[rxframe_head].length=0;  

  27. }  

  28. #endif  

  29.   return 1;  

  30. }  

在rf230_process PThread中收到PROCESS_EVENT_POLL,调用NETSTACK_RDC.input()进入数据接收处理流程。最后在Radio文件中,找到了调用process_poll()函数来,poll一个PROCESS_EVENT_POLL。

[cpp] view plaincopy在CODE上查看代码片

  1. PROCESS_THREAD(rf230_process, ev, data)  

  2. {  

  3.   int len;  

  4.   PROCESS_BEGIN();  

  5.   RF230PROCESSFLAG(99);  

  6.   

  7.   while(1) {  

  8.     PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);  

  9.     RF230PROCESSFLAG(42);  

  10.   

  11.     packetbuf_clear();  

  12.   

  13.     /* Turn off interrupts to avoid ISR writing to the same buffers we are reading. */  

  14.     HAL_ENTER_CRITICAL_REGION();  

  15.   

  16.     len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE);  

  17.   

  18.     /* Restore interrupts. */  

  19.     HAL_LEAVE_CRITICAL_REGION();  

  20.     PRINTF("rf230_read: %u bytes lqi %u\n",len,rf230_last_correlation);  

  21. #if DEBUG>1  

  22.      {  

  23.         uint8_t i;  

  24.         unsigned const char * rxdata = packetbuf_dataptr();  

  25.         PRINTF("0000");  

  26.         for (i=0;i<len+AUX_LEN;i++) PRINTF(" %02x",rxdata[i]);  

  27.         PRINTF("\n");  

  28.       }  

  29. #endif  

  30.   

  31.   

  32.     RF230PROCESSFLAG(1);  

  33.     if(len > 0) {  

  34.       packetbuf_set_datalen(len);  

  35.       RF230PROCESSFLAG(2);  

  36.       NETSTACK_RDC.input();  

  37.     } else {  

  38. #if RADIOSTATS  

  39.        RF230_receivefail++;  

  40. #endif  

  41.     }  

  42.   }  

  43.   

  44.   PROCESS_END();  

  45. }  


附1:

以Contiki中example-mesh.c历程为例:

examples/example-mesh.c/example_mesh_process/mesh_open

send:

(在rime中:

mesh.c/mesh_send()

multihop_send()

unicast_send()

broadcast_send()

abc_send()(abc_send中调用rime_output)

)

rime.c/rime_output()/NETSTACK_MAC.send

nullmac.c/NETSTACK_RDC.send

(NETSTACK_FRAMER.create 生成framer)

nullrdc.c/NET_RADIO.send

nullrdc.c/mac_call_sent_callback 处理发送结束后的状态。

recv:

tf230bb/fr230bb.c/rf230_interrupt  调用process_poll产生PROCESS_EVENT_POLL。

pthread

rf230bb.c/rf230_process任务/NETSTACK_RDC.input

(NETSTACK_FRAMER.parse解析收到的数据帧,是否符合MAC层要求)

nullrdc.c/NETSTACK_MAC.input

nullmac.c/NETSTACK_NETWORK.input 调用rime.c/input()/abc_input()

通过rime协议栈的回调传递给

mesh.c/data_packet_received()此函数回调应用层的接收处理函数

example-mesh.c/example_recv()处理接收数据。

附2:

stunicast.c中

对于重发的处理,由在发送过程中设置timer如果在规定的时间内,如果没有数据返回则通过timer调用回调处理函数,如果有数据返回则在在recv_from_stunicast()调用stunicast_cancel()取消timer,避免调用回调。

在Contiki中,数据的发送与接收分别使用一个任务,这样可以避免之间的冲突问题。

NETWORK协议栈层之间的数据交互,通过buf来实现。这一点与Linux的sk_buff很像,所以导致了很多不必要的内存拷贝,这也是为什么Contiki内存占用很小的原因之一。


你可能感兴趣的:(NetWork,contiki)