Upma Xmac 测试 03

一、分析内容:

   这次主要分析:从上层的AMSender.send发送packet到Xmac将packet发送出去的流程。

二、

  找到upma/apps/tests/TestXmac/SendingC$SendTimer$startPeriodic事件,代码如下:  

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

  call AMSender.send(AM_BROADCAST_ADDR, &packet, 2 * sizeof(uint8_t));的实现代码如下(/opt/tinyos-2.1.2/tos/system/AMQueueEntryP.nc文件):

  command error_t AMSend.send(am_addr_t dest,
                  message_t* msg,
                  uint8_t len) {
    // printf("AMSend.send!!!\r\n");
    call AMPacket.setDestination(msg, dest);        //设置packet的目的地址
    call AMPacket.setType(msg, amId);              //设置packet的类型
    return call Send.send(msg, len);             //发送packet
  }

   call Send.send(msg, len);的实现代码如下:(/opt/tinyos-2.1.2/tos/system/AMQueueImplP.nc)    

/**
     * Accepts a properly formatted AM packet for later sending.
     * Assumes that someone has filled in the AM packet fields
     * (destination, AM type).
     *
     * @param msg - the message to send
     * @param len - the length of the payload
     *
     */
    command error_t Send.send[uint8_t clientId](message_t* msg,
                                                uint8_t len) {

    //printf("Send.send !!!  numClients=%d clientId=%d\r\n",numClients,clientId);
        if (clientId >= numClients) {            //numClients=1,    clientId=0,具体什么意义暂时不了解
            return FAIL;
        }
        if (queue[clientId].msg != NULL) {
            return EBUSY;
        }
        dbg("AMQueue", "AMQueue: request to send from %hhu (%p): passed checks\n", clientId, msg);
        //printf("msg=%s !!!\r\n",msg);
        queue[clientId].msg = msg;

        call Packet.setPayloadLength(msg, len);        //在头部加入CC2420_SIZE的大小的头
    
        if (current >= numClients) { // queue empty      //current=1
        error_t err;
            am_id_t amId = call AMPacket.type(msg);        //amId=240  new AMSenderC(240)
            am_addr_t dest = call AMPacket.destination(msg);    //dest=-1,广播目的节点为-1?
       // printf("current=%d amId=%d,dest=%d!!!\r\n",current,amId,dest);
            dbg("AMQueue", "%s: request to send from %hhu (%p): queue empty\n", __FUNCTION__, clientId, msg);
            current = clientId;
            
        //printf("AMQueueImplP\r\n");
            err = call AMSend.send[amId](dest, msg, len);
            if (err != SUCCESS) {
        //printf("underlying send failed\r\n");
                dbg("AMQueue", "%s: underlying send failed.\n", __FUNCTION__);
                current = numClients;
                queue[clientId].msg = NULL;
                
            }
        //printf("SUCCESS\r\n");
            return err;
        }
        else {
            dbg("AMQueue", "AMQueue: request to send from %hhu (%p): queue not empty\n", clientId, msg);
        }
        return SUCCESS;
    }

   err = call AMSend.send[amId](dest, msg, len);由/opt/tinyos-2.1.2/wustl/upma/chips/cc2420/CC2420ActiveMessageP.nc实现,代码如下:  

/***************** AMSend Commands ****************/
  command error_t AMSend.send[am_id_t id](am_addr_t addr,
                      message_t* msg,
                      uint8_t len) {
    cc2420_header_t* header = call CC2420PacketBody.getHeader( msg );
    
    if (len > call Packet.maxPayloadLength()) {
      return ESIZE;
    }
    
    header->type = id;                //header->type就是new AMSenderC(240)这里的240
    header->dest = addr;            //header->dest=-1,由于是广播        
    header->destpan = call CC2420Config.getPanAddr();    //header->destpan
    header->src = call AMPacket.address();    //header->src  packet源地址
 //   printf("header->type=%d,header->dest=%d,header->destpan=%d,header->src=%d,\r\n",
//                                header->type,header->dest,header->destpan,header->src);
    //printf("CC2420ActiveMessageP\r\n");
    if (call RadioResource.immediateRequest() == SUCCESS) {    //立即请求radio资源,经调试,一般都会成功
      error_t rc;
      signal SendNotifier.aboutToSend[id](addr, msg);        //为什么AMQueueImplP没有实现该事件。
      
    //printf("CC2420ActiveMessageP\r\n");
      rc = call SubSend.send( msg, len );
      if (rc != SUCCESS) {
        call RadioResource.release();
      }

      return rc;
    } else {
      pending_length  = len;
      pending_message = msg;
      return call RadioResource.request();
    }
  }

  rc = call SubSend.send( msg, len );由/opt/tinyos-2.1.2/tos/chips/cc2420/lowpan/ CC2420TinyosNetworkP.nc实现,源码如下: 

command error_t ActiveSend.send(message_t* msg, uint8_t len) {
    //printf("CC2420TinyosNetworkP\r\n");
    call CC2420Packet.setNetwork(msg, TINYOS_6LOWPAN_NETWORK_ID);
    m_busy_client = CLIENT_AM;
    return call SubSend.send(msg, len);
  }
call SubSend.send(msg, len); 由/opt/tinyos-2.1.2/tos/chips/cc2420/unique/UniqueSendP.nc实现,源码如下:
  
  /***************** Send Commands ****************/
  /**
   * Each call to this send command gives the message a single
   * DSN that does not change for every copy of the message
   * sent out.  For messages that are not acknowledged, such as
   * a broadcast address message, the receiving end does not
   * signal receive() more than once for that message.
   */
  command error_t Send.send(message_t *msg, uint8_t len) {
    error_t error;
    //printf("UniqueSendP Send.send\r\n");
    if(call State.requestState(S_SENDING) == SUCCESS) {
      (call CC2420PacketBody.getHeader(msg))->dsn = localSendId++;
      
      if((error = call SubSend.send(msg, len)) != SUCCESS) {
        call State.toIdle();
      }
      
      return error;
    }
    
    return EBUSY;
  }

   error = call SubSend.send(msg, len)的由/opt/tinyos-2.1.2/wustl/upma/system/AsyncSendAdapterP.nc实现,源码如下:

command error_t Send.send(message_t * msg, uint8_t len)
    {
        printf("AsyncSendAdapterP Send.send\r\n");
        return call AsyncSend.send(msg, len);
    }
    

  call AsyncSend.send(msg, len)由/opt/tinyos-2.1.2/wustl/upma/lib/macs/xmac/XmacSenderP.nc实现,终于快到目的地了,源码如下:

    

async command error_t Send.send(message_t * msg, uint8_t len)
    {
        //printf("XmacSenderP Send.send\r\n");
        if(call SendState.getState() == S_STOPPED)
            return EOFF;
        // Make sure that the radio isn't off
        
        // Try to move to the preamble state            
        if(call SendState.requestState(S_PREAMBLE) == SUCCESS)
        {
            call FixedSleepLplListener.cancelTimeout();
            atomic
            {
                msg_ = msg;
                len_ = len;
            }
            
            post doStart();
            return SUCCESS;
            // Save the parameters and start the radio
        }
        
        return FAIL;
    }

  总结:本想着一步一步深入了解每个步骤的内容,花了不少时间,但是还是想不通每行代码的意义,所以直接跳到XmacSenderP的实现,这里必须一步一步分析。

    

posted @ 2017-11-20 22:38  XiaoBBai  阅读(215)  评论(0编辑  收藏  举报