TinyOS почти везде соблюдает дисциплину владения : в любой момент времени каждый
«объект памяти» - часть памяти, обычно целая переменная или отдельный элемент массива - должен принадлежать одному модулю. Говорят, что команда типа send
передает владение своим аргументом msg вызывающему абоненту.
Основная проблема вашего кода заключается в том, что в событии Receive.receive
вы используете переменную packet
двумя способами:
- как исходящий пакет, набрав
call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(rd_message))
- в качестве буфера для следующего входящего пакета, выполнив
return bufPtr;
результат этого кода непредсказуем (поскольку получение пакета повредит исходящий пакет). Чтобы решить вашу проблему, вы должны использовать компонент Pool<message_t>
. Типичный псевдокод для такой программы, как ваша:
- прием (м):
- если мне не нужно обрабатывать это сообщение, верните m
- если мой список бесплатных пакетов пуст, вернуть m
- еще
- процесс / переадресация м
- возврат записи из списка бесплатных пакетов
Это грубая реализация модуля, который использует 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 всегда нужен буфер для хранения входящих пакетов.