Upma Xmac 測試 01

1、本文的目的主要是構建一個Xmac的測試程序,並從上層到下層,從發送到接收,深刻調試upma的Xmac協議數組

2、程序構建:app

  一、upma開源包下的  「upma/apps/tests/TestBmac」是對Bmac協議的測試,主要實現的功能就是發送和接收,若是你下載的upma是最終版的(不是最終版有一些問題),只需將文件夾「TestBmac」改爲「TestXmac」,並就TestXmac目錄下的Makefile中的  「UPMA_MAC = bmac」 改爲「UPMA_MAC = xmac」就完成了一個Xmac測試程序的構建,仍是很方便的。less

  二、代碼深刻調試(就從Boot.booted()開始分析吧)async

    a、upma/apps/tests/TestXmac/SendingC.nc$Boot.booted() 事件是硬件上電後第一個執行的事件,至關於C裏面的main,也就是程序入口ide

    event void Boot.booted()
    {
        call SplitControl.start();      //具體由XmacSplitControlP.SplitControl實現
    }

    從配置組件查找得知,這裏的SplitControl接口實際是由XmacSplitControlP提供的,跳到upma/lib/macs/xmac/XmacSplitControlP.nc文件,找到SplitControl.start() 命令的實現代碼以下:測試

      

  command error_t SplitControl.start()
    {
        if(call State.getState() != S_STOPPED)
            return FAIL;
        // Make sure we're off
        
        call State.forceState(S_STARTING);
        return call RadioPowerControl.start();
        // Turn on the radio
    }

而State接口由/tinyos-2.1.2/tos/system/StateImplP提供,跳到/tinyos-2.1.2/tos/system.nc文件,找到State.getState()的實現代碼以下:ui

    

  /**
   * Get the current state
   */
  async command uint8_t State.getState[uint8_t id]() {
    uint8_t theState;
    atomic theState = state[id];
    return theState;
  }

   這裏的id相似於AMReceiverC組件中的id,代碼以下:atom

   

#include "AM.h"

generic configuration AMReceiverC(am_id_t amId) {
  provides {
    interface Receive;
    interface Packet;
    interface AMPacket;
  }
}

implementation {
  components ActiveMessageC;

  Receive = ActiveMessageC.Receive[amId];
  Packet = ActiveMessageC;
  AMPacket = ActiveMessageC;
}

    只不過這裏的id是用來區分不一樣組件的,不一樣組件擁有不一樣的狀態機,而AMReceiverC中的id是用來區別不一樣的receiver的。State的id是何時指定的?沒思路。spa

 

    state[id]的定義以下:調試

    

    /** Each component's state - uniqueCount("State") of them */
    uint8_t state[uniqueCount(UQ_STATE)];

 

    是一個uint8_t數組,這裏的state[id]應該表明radio相對於State組件而言當前的狀態,能夠經過調用State.requestState,State.forceState,State.toIdle命令改變。

    經調試,State組件的id值爲5,而state[id]=state[5]=0,也就是S_IDLE狀態。

 

    回到upma/lib/macs/xmac/XmacSplitControlP.nc中SplitControl.start() 命令的實現代碼,第一行代碼 「 if(call State.getState() != S_STOPPED) 」的意思就是判斷radio是否處於空閒狀態(從這裏能夠看出,

    S_STOPPED也就是radio的IDLE狀態)。

 

    upma/lib/macs/xmac/XmacSplitControlP.nc中SplitControl.start() 第二行代碼 「 call State.forceState(S_STARTING) ;「的實現代碼以下:

      

  /**
   * Force the state machine to go into a certain state,
   * regardless of the current state it's in.
   */
  async command void State.forceState[uint8_t id](uint8_t reqState) {
    atomic state[id] = reqState;
  }

    不管是從命令名仍是實現代碼能夠看出,就是強制將state[id]的值置爲一個指定值。 「 call State.forceState(S_STARTING) ;「的做用應該是將radio的狀態機置爲」正在開啓「狀態,也就是說S_STARTING

    對應radio的正在開啓狀態。

 

    upma/lib/macs/xmac/XmacSplitControlP.nc中SplitControl.start() 命令的實現代碼,第三行代碼

      

      return call RadioPowerControl.start();        //RadioPowerControl接口的提供者是在哪裏指定的

    老實說,我在SendingAppC.nc,XmacSplitControlC.nc和MacC都沒有找到RadioPowerControl提供的組件,只能用搜索方法,找到了/upma/chips/cc2420/CC2420CsmaP.nc文件,上述命令的實現代碼以下:

      

  async command error_t RadioPowerControl.start() {
    if(call SplitControlState.requestState(S_STARTING) == SUCCESS) {      //SplitControlState的id號爲1,在上面的過程當中
                                                                         //咱們已經將radio的狀態設爲S_STARTING
#ifdef CC2420_ACCOUNTING                  //沒有定義,下面兩行代碼忽略
      call Alarm.start(1024UL);
      vRegStartedAt = call Counter.get();
#endif
      call CC2420Power.startVReg();
      return SUCCESS;
    
    } else if(call SplitControlState.isState(S_STARTED)) {
      return EALREADY;
      
    } else if(call SplitControlState.isState(S_STARTING)) {
      return SUCCESS;
    }
    
    return EBUSY;
  }

     這個命令主要是啓動radio時對radio進行穩壓操做,看了一下內部實現代碼,沒看懂,下面是 」call CC2420Power.startVReg();「的實現代碼

      

  /***************** CC2420Power Commands ****************/
  async command error_t CC2420Power.startVReg() {
    atomic {
      if ( m_state != S_VREG_STOPPED ) {              //m_state的初始值是0,S_VREG_STOPPED是枚舉值,也是0
        return FAIL;
      }
      m_state = S_VREG_STARTING;                    //S_VREG_STARTING=1
    }
    call VREN.set();                                //並無找到這個命令的實現
    call StartupTimer.start( CC2420_TIME_VREN );    //CC2420_TIME_VREN = 20,這裏啓動一個定時器,應該是us級的
    return SUCCESS;
  }

3、小結:

    upma/apps/tests/TestXmac/SendingC.nc$Boot$booted() 事件主要作的工做就是開啓radio。

相關文章
相關標籤/搜索