我的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;
}
}
我从代码中删除了所有逻辑,专注于消息交换调用。我希望有人可以帮助我......谢谢。
答案 0 :(得分:4)
TinyOS几乎随处可见所有权纪律:在任何时间点,每一个
“内存对象” - 一块内存,通常是整个变量或单个数组元素 - 应该由单个模块拥有。像send
这样的命令被称为将其msg参数的所有权从调用者传递给被调用者。
您的代码的主要问题是在Receive.receive
事件中,您使用packet
变量有两种方式:
call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message))
return bufPtr;
此代码的结果是不可预测的(因为接收数据包会破坏传出数据包)。要解决您的问题,您应该使用Pool<message_t>
组件。像你这样的程序的典型伪代码如下:
这是一个模块的粗略实现,它使用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总是需要一个缓冲区来存储传入的数据包。