再谈TinyOs中定时器的问题

来源:互联网 发布:slim nginx 编辑:程序博客网 时间:2024/06/05 00:30
今天又遇到了一个timer定时器的问题,经过TOSSIM一次次的debug之后,终于找到问题症结,现将问题及解决方案列出,

仅供参考.

/****************************************************************************************************************************/

  event TOS_MsgPtr ResetCounterMsg.receive(TOS_MsgPtr m){
    int i;
    uint8_t seg;
    if(TOS_LOCAL_ADDRESS==Des_Node){
    dbg(DBG_TEMP|DBG_USR1,"timer stop 1");
  call Timer.stop();
  recvPack=(struct myPack *)m->data;
  pnum=recvPack->packnum;
  seg=(pnum-1)%10*20;
  if(packLabel[pnum]==FALSE){  
  for(i=0;i<20;i++){
  des_buffer[i+seg]=recvPack->data[i];
  }
  buf_cnt+=20;
  packLabel[pnum]=TRUE;
  }
  dbg(DBG_TEMP|DBG_USR1,"buf_cnt=%d",buf_cnt);
  if(buf_cnt==200){//完整的接收到一批数据包(1批数据包为10个,每个数据包有20个字节)
  ackPack->acknum=(ackPack->acknum+1)%256;
  buf_cnt=0;
  sendAck((pnum-1)/10*10);
  call Leds.yellowToggle();
  dbg(DBG_TEMP|DBG_USR1,"timer start 1");

        call Timer.start(TIMER_REPEAT,50);

  signal MyRouting.packReceiveDone(des_buffer);
  }
  else{
  ackPack->acknum=(ackPack->acknum+1)%256;
  dbg(DBG_TEMP|DBG_USR1,"timer start 2");
  call Timer.start(TIMER_REPEAT,1000);
  }
  }
  else if(TOS_LOCAL_ADDRESS==Source_Node){
  tempPack=(struct myPack *)m->data;
  if(ackPack->acknum!=tempPack->acknum){
   ackPack->packSort=tempPack->packSort;
  ackPack->last=tempPack->last;
  ackPack->acknum=tempPack->acknum;
  ackPack->packnum=tempPack->packnum;
for(i=0;i<20;i++){
ackPack->data[i]=tempPack->data[i];
}
    retransmit();
  }
  }
  else{
  //在路由表中判断是否进行转发
  }
  return m;
  }

/****************************************************************************************************************************/

以上是本人写的部分代码,注意代码中的红色部分.

熟悉TinyOs的人应该知道,这个事件是GennericComm接口声明的event,作用是收到无线数据报之后的通知.

本段函数的目的是在收到源节点图片数据包之后,做相应的处理.

蓝色字体部分的意思是在收完一批数据包(10组)之后,通知网络层以上执行相应动作.问题就出在这一段中了.

上一批数据收完之后,下一批数据很快就会来到.但当下一批数据中的第一个数据包过来的时候,

这时红色代码call Timer.start(TIMER_REPEAT,50); 定时器已经启动了(定时器的工作是根据

当前数据包进行计算发送本批数据的ACK),尽管在event开始的时候都会将定时器关掉,但是,

已经开始执行的定时器并不会因此而终止掉,它会执行完本次定时器中的内容,然后才会stop(

一开始不知道,严重被坑!!!,怎么都不会想到这个细节).那么这个时候问题就来了.定时器里的操作

本来应该是根据当前数据包,也就是上一批的最后一个数据包进行进行计算,但这个时候下一批数

据包的第一个报文已经到达,recvPack=(struct myPack *)m->data;被篡改成了下一批数据包的

第一个报文,那么这个时候定时器进行的计算实际上是下一批次的ACK,计算完以后迅速发给源节

点.然而这个时候源节点的这一批报文还没有发送完,怎么能直接先给确认呢?

所以经过TOSSIM的多次模拟,最终把call Timer.start(TIMER_REPEAT,50);中的50改为了100.


原创粉丝点击