Upma Xmac 测试 02

一、接上 Upma Xmac 测试 01

二、程序调试分析:

  1、跳到upma/apps/tests/TestXmac/SendingC$SplitControl$startDone事件,代码如下:

    event void SplitControl.startDone(error_t err)
    {
        uint8_t * nodeId;
        call LowPowerListening.setLocalWakeupInterval(interval);
            
        nodeId = (uint8_t *)call Packet.getPayload(&packet, sizeof(uint8_t));
        *nodeId = TOS_NODE_ID;

        call SendTimer.startPeriodic(8000);
    }

    LowPowerListening接口实际是由BmacLplPacketP组件实现的,源码如下: 

    command void LowPowerListening.setLocalWakeupInterval(uint16_t ms)
    {
        call ChannelPoller.setWakeupInterval(ms);
    }

   ChannelPoller.setWakeupInterval命令是由ChannelPollerP.setWakeupInterval实现的,源码如下:

    async command void ChannelPoller.setWakeupInterval(uint16_t ms)
    {
        atomic ms_ = ms;    
        if(running_)                    //初始值 bool running_ = FALSE;经调试不知道在什么时候变为了true.
            call Alarm.start(ms);        //
        // Save the sleep interval, and reset the alarm if the poller is active
    }

    Alarm.fired()实现代码如下:  

async event void Alarm.fired()
    {
        // If the channel poller is active
        if(running_)
        {
            call Alarm.start(ms_);
            // Restart the timer
            call State.forceState(S_CHECKING);
            // Move into the busy state
            call ChannelMonitor.check();
            // Do a CCA check
        }
    }

    call Alarm.start(ms_);就是ms_之后在触发一次Alarm,Alarm也是一类定时器,只不过更为准确。

    call State.forceState(S_CHECKING);  就是将State的状态设为S_CHECKING,表示正在进行信道检测

    ChannelMonitor.check()由PowerCycleP组件实现,代码如下:

  async command void ChannelMonitor.check() {
    post startRadio();
  }

    可以看出,信道检测是通过一个任务来实现的,startRadio()的代码如下:

 task void startRadio() {
    error_t err;
    err = call RadioPowerControl.start();
    if(err == EALREADY) {
      post getCca();
    } else if (err != SUCCESS) {
      post startRadio();
    }
  

    经调试,第一次err=9=EALREADY,进行CCA检测。getCca() task的实现代码如下

 task void getCca() {
    uint8_t detects = 0;
#ifdef OLDCCA                           ////使用的不是old cca,下面不用看了
    uint16_t ccaChecks;
    atomic {
      for(ccaChecks = 0; ccaChecks < MAX_LPL_CCA_CHECKS; ccaChecks++) {
        if(call PacketIndicator.isReceiving()) {      
          detected++;
          signal ChannelMonitor.busy();
          return;
        }
          
        if(call EnergyIndicator.isReceiving()) {
          detects++;
          if(detects > MIN_SAMPLES_BEFORE_DETECT) {
            detected++;
            signal ChannelMonitor.busy(); 
            return;
          }
          // Leave the radio on for upper layers to perform some transaction
        }
      }
      free++;
      signal ChannelMonitor.free();
    }
#else
    local_time16_t startAt, endAt, length, now;
    uint16_t count = 0;
        
    length.mticks = 0;
    length.sticks = ccaCheckLength;
    startAt = call Time.getNow();
    endAt = call Time.add(&startAt, &length);       //endAt.sticks=startAt.sticks+8*32;

    while(TRUE) {
      count++;
      if(count % 32 == 0) {
        now = call Time.getNow();                    //每检测32次,看一下CCA的时间长度是否超过预定的长度
        if(!call Time.lessThan(&now, &endAt)) {      //now是否<endAt
          break;
        }
      }
      
      if(call PacketIndicator.isReceiving()) {      //是否接收到数据包,如果接收到数据包,直接认为信道忙
        detects = MIN_SAMPLES_BEFORE_DETECT + 1;    //避免多余的检测   #define MIN_SAMPLES_BEFORE_DETECT 3
        break;
      }
            
       if(call EnergyIndicator.isReceiving()) {     //信道检测其实就是检测能量,当信道的功率大于某个值一定次数,也认为信道忙
         detects++;
         if(detects > MIN_SAMPLES_BEFORE_DETECT) {   //避免多余的检测
           break;
         }
         // Leave the radio on for upper layers to perform some transaction
       }
    }
    
    if(detects > MIN_SAMPLES_BEFORE_DETECT) {     //说明信道忙   
      detected++;
      signal ChannelMonitor.busy();
    } else {
      free++;
      signal ChannelMonitor.free();
    }
#endif
    
  }

    从上诉代码可以看出,CCA检测其实就是检测有没收到packet或者信道中的功率是不是大于某个阈值一定次数。

    小结:call LowPowerListening.setLocalWakeupInterval(interval); 就是设置本地节点listen的间隔,而listen也就是CCA。

 

    继续分析upma/apps/tests/TestXmac/SendingC$SplitControl$startDone事件,代码如下:

        nodeId = (uint8_t *)call Packet.getPayload(&packet, sizeof(uint8_t));
        *nodeId = TOS_NODE_ID;
        call SendTimer.startPeriodic(8000);

    packet之前并没有填充,由此也可见我的这个upma并非最终版本,里面是随机值。

    call SendTimer.startPeriodic(8000);   每隔8s触发一次SendTimer,跳到 event void SendTimer.fired()事件:

      

    event void SendTimer.fired()
    {
        if(sends)
        {
            call Leds.led2On();
            call AMSender.send(AM_BROADCAST_ADDR, &packet, 2 * sizeof(uint8_t));        
        }
    }

    触发后就以广播方式发送一次数据。

 

  总结:

    upma/apps/tests/TestXmac/SendingC$SplitControl$startDone事件主要:设置本地节点的唤醒间隔,并启动发送packet定时器。

posted @ 2017-11-20 10:52  XiaoBBai  阅读(185)  评论(0编辑  收藏  举报