【问题标题】:Tinyos reception after second reply doesn't work第二次回复后 Tinyos 接收不起作用
【发布时间】:2010-09-01 12:25:57
【问题描述】:

我的 nesC 代码有问题。在我的代码中,我使用AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message)) 发送第一个数据包。

之后,当函数event message_t* Receive.receive(message_t* bufPtr, void* payload, uint8_t len){收到消息时,会生成回复并发送成功,但其他节点无法接收回复。特别是我必须按照 DSR 协议的基础来处理 RREP 回复。 这是我的代码:

implementation{


/**********************Variables used*****************************/
short phase = 0;
message_t packet;
bool locked;

event void Boot.booted(){
    dbg("Boot", "Node %hhu booted\n", TOS_NODE_ID);
    call AMControl.start(); 


}

  [cut]

event void MilliTimer.fired(){
    /*This contains the discovery message*/
    rd_message *rreq = NULL;

    if (phase == 0){
        //Route discovery phase
        rreq = (rd_message *) call Packet.getPayload(&packet, (int) NULL);


        if(call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message)) == SUCCESS){
        //locked = TRUE;

        }
        return;
    }

}


event message_t* Receive.receive(message_t* bufPtr, void* payload, uint8_t len){
    rd_message *received_mex = NULL;  
    rd_message *reply_mex = NULL;

    int i,j;

    received_mex = (rd_message*) payload;   //cast to rd_message

      if (received_mex->type == RREQ){
          reply_mex = (rd_message*) call Packet.getPayload(&packet, (int) NULL);  //reply packet is created.
        if (received_mex->sender_id == TOS_NODE_ID){
          //The original sender received its RREQ. Stopping the forward procedure
          return bufPtr;   //FIXME: see if it's correct to return null here
        }

        //RREQ message case 1: I am not the receiver_id
        if (received_mex->receiver_id != TOS_NODE_ID){

        }
        else if (received_mex->receiver_id == TOS_NODE_ID){
          //I am the receiver of the RREQ message. I can now reply with a RREP

        }


        if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message)) == SUCCESS) {
                dbg("dsr", "packet sent\n");    
                //locked = TRUE;
            }
        else{
          dbg("dsr", "failed to send reply packet.\n");

        }


      }
      else if (received_mex->type == RREP){
       //DO SOMETHING WITH CHE NEW RECEIVED MESSAGE HERE

      }

    return bufPtr;


}


  event void AMSend.sendDone(message_t* bufPtr, error_t error) {
    if (&packet == bufPtr) {
      //locked = FALSE;
    }
  }

我从代码中删除了所有逻辑,以专注于消息交换调用。我希望有人可以帮助我...谢谢。

【问题讨论】:

    标签: tinyos nesc


    【解决方案1】:

    TinyOS 几乎在所有地方都遵循 所有权 原则:在任何时间点,每个 “内存对象” - 一块内存,通常是整个变量或单个数组元素 - 应该由单个模块拥有。像send 这样的命令据说会将其 msg 参数的所有权从调用者传递给被调用者。

    您的代码的主要问题是在Receive.receive 事件中,您以两种方式使用packet 变量:

    • 作为传出数据包调用call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message))
    • 通过执行return bufPtr;作为下一个传入数据包的缓冲区

    此代码的结果是不可预测的(因为接收数据包会破坏传出数据包)。要解决您的问题,您应该使用Pool<message_t> 组件。像您这样的程序的典型伪代码如下:

    1. 接收(米):
    2. 如果我不需要处理这条消息,返回m
    3. 如果我的空闲包列表为空,返回m
    4. 其他
      1. 处理/转发 m
      2. 从空闲数据包列表返回条目

    这是一个使用Pool<message_t>作为空闲数据包列表来管理通信的模块的粗略实现:

    module Foo
    {
        /* this is our free packet list */
        uses interface Pool<message_t>;
        uses interface Receive;
        uses interface AMSend;
    }
    
    implementation
    {
    
    event void MilliTimer.fired()
    {
        message_t *packet;
        /* get a free packet */
        packet = Pool.get();
        if (packet)
        {
            /* code to send the packet */
        }
    }
    
    event void AMSend.sendDone(message_t *msg, error_t error)
    {
        /* the send function ended, put back the packet in the free packet pool */
        /* check here if msg was taken from Pool */
        call Pool.put(msg);
    }
    
    event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len)
    {
        if (!haveToProcess(msg))
            return msg; // don't have to process this message
        if (Pool.empty())
            return msg; // memory exahusted;
        /* ... */
        /* code that processes the packet */
        call AMSend.send(AM_BROADCAST_ADDR, msg, sizeof(rd_message));
        /* return a free message_t* as buffer to store the next received packet */
        return Pool.get();
    }
    
    }
    

    如果您不喜欢Pool,可以使用message_t 数组作为循环缓冲区。查看BaseStation 代码以获取有关如何执行此操作的提示。

    更多细节,我建议你阅读TinyOS programming book,尤其是第3.5.1节。

    至于你的评论:

    return bufPtr;   //FIXME: see if it's correct to return null here
    

    你可以永远在接收事件中返回NULL,因为 TinyOS 总是需要一个缓冲区来存储传入的数据包。

    【讨论】:

    • 谢谢您的回复,事情已经清楚了。当然,我必须详细研究 TinyOS 的开发,并了解如何处理这种情况。 Ancora Grazie Mille!!
    猜你喜欢
    • 2019-08-14
    • 1970-01-01
    • 1970-01-01
    • 2021-01-13
    • 1970-01-01
    • 2014-01-31
    • 2015-06-21
    • 2011-10-04
    • 1970-01-01
    相关资源
    最近更新 更多