1

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

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

4

1 回答 1

4

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 编程书,尤其是第 3.5.1 节。

至于你的评论:

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

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

于 2010-09-01T20:40:48.793 回答