第二次回复后 Tinyos 接收不起作用

发布于 2024-09-17 04:56:21 字数 2483 浏览 1 评论 0原文

我的 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;
    }
  }

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

I'm in trouble with my nesC code. In my code I send a first packet using AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message)).

After that, when a message is received in function event message_t* Receive.receive(message_t* bufPtr, void* payload, uint8_t len){ a reply is generated and sent successfully, but the other nodes are not able to receive the reply. In particular I have to process a RREP reply, following the basics of DSR protocol.
This is my code:

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;
    }
  }

I removed all the logic from the code to focus on the message exchange calls. I hope that someone can help me... thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

漆黑的白昼 2024-09-24 04:56:21

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

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

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

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

  1. receive (m):
  2. 如果我不需要处理此消息,则返回 m
  3. 如果我的空闲数据包列表为空,则返回 m
  4. 否则
    1. 处理/转发m
    2. 从免费数据包列表中返回条目

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

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数组作为循环缓冲区。查看基站 代码以获取有关如何执行此操作的提示。

有关更多详细信息,我建议您阅读 TinyOS 编程书籍,特别是第 3.5.1 节。

至于您的评论:

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

永远不能在接收事件中返回NULL,因为TinyOS始终需要一个缓冲区来存储传入的数据包。

TinyOS follows almost everywhere a ownership discipline: at any point in time, every
"memory object" - a piece of memory, typically a whole variable or a single array element - should be owned by a single module. A command like send is said to pass ownership of its msg argument from caller to callee.

The main problem of your code is that in the Receive.receive event you are using the packet variable in two ways:

  • as outgoing packet by calling call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message))
  • as buffer for the next incoming packet by executing return bufPtr;

the result of this code is unpredictable (since receiving a packet will corrupt the outgoing packet). To solve your problem, you should use a Pool<message_t> component. The typical pseudocode for a program like yours is like:

  1. receive (m):
  2. if I don't need to process this message, return m
  3. if my free packet list is empty, return m
  4. else
    1. process/forward m
    2. return entry from free packet list

This is a rough implementation of a module that uses Pool<message_t> as list of free packets to manage communication:

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();
}

}

If you don't like Pool, you can use a message_t array as circular buffer. Take a look at the BaseStation code for a hint on how to do so.

For more details, I suggest you to read the TinyOS programming book, especially section 3.5.1.

As for your comment:

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

you can never return NULL in a receive event, since TinyOS needs always a buffer to store incoming packets.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文