долгое время читатель, впервые постер.Надежный последовательный протокол с автоответчиком вопросы
У меня есть последовательная связь между датчиком и базовой станцией через bluetooth. Ссылка bluetooth невероятно ненадежна и отбрасывает пакеты, как вы не поверите. Я использую это как положительное и собираюсь разработать надежный последовательный протокол, который может пережить связь с дерьмом.
Просто хочу отбросить идеи от людей, поскольку я единственный встроенный разработчик в офисе.
Планирование использования байтовой начинки для создания пакетов с байтами начала (STX) и конца (ETX), номера индекса и CRC. Я планирую использовать escape-символ (DLE), когда появляются символы STX и ETX и DLE. Эта часть все довольно ясно, и здесь сказано код, который должен сделать
static void SendCommand(struct usart_module * const usart_module, uint16_t cmd,
uint8_t *data, uint8_t len)
{
//[STX] ({ [IDX] [CMD_H] [CMD_L] [LEN] ...[DATA]... } [CRC]) [ETX] // Data in {} brackets is XORed together for the CRC. // Data in() is the packet length
static uint8_t idx;
uint8_t packet[256];
uint8_t crc, packetLength, i;
if (len > 250)
return;
packetLength = len + 5;
packet[0] = idx++;
packet[1] = (cmd >> 8);
packet[2] = (cmd & 0x00FF);
packet[3] = packetLength;
crc = 0;
for (i = 0; i <= 3; i++)
{
crc ^= packet[i];
}
for (i = 0; i < len; i++)
{
packet[4 + i] = data[i];
crc ^= data[i];
}
packet[4 + len] = crc;
// Send Packet
uart_putc(usart_module, STX);
for (i = 0; i < packetLength; i++)
{
if ((packet[i] == STX) || (packet[i] == ETX) || (packet[i] == DLE))
{
uart_putc(usart_module, DLE);
}
uart_putc(usart_module, packet[i]);
}
uart_putc(usart_module, ETX);
}
Так что пошлет пакет, но теперь мне нужно добавить код для отслеживания пакетов и автоматически ретранслировать неисправные из них и Вот где мне нужна помощь с некоторыми идеями.
Варианты пар у меня были; -Easiest, назначьте гигантский массив из 256 пакетов, каждый из которых имеет достаточно места для хранения пакета и после передачи пакета, поместите его в буфер, и если я не получу ACK через х количество времени, отправьте его снова. Тогда, если я действительно получаю ACK, удалите эту запись из массива, чтобы запись была пустой, поэтому я знаю, что она получена просто отлично.
Проблема с этим состоит в том, что если я использую худший размер случае пакета 256 байт, и 256 экземпляров из них, тот 64К оперативной памяти и я не имею, что (и даже если я сделал, вот страшная мысль)
-Следующая идея, создайте связанный список всех пакетов и динамически назначайте память с помощью команд malloc и т. Д. И удалите те, которые получили подтверждение, и сохраните те, которые есть, поэтому я знаю, что для повторной передачи через x время.
Вопросы, которые у меня есть, это идея всего malloc. Честно говоря, я никогда не использовал его, и мне не нравится идея его использования во встроенной среде с ограниченной памятью. Может быть, это только я, будучи глупым, но я чувствую, что это открывает дверь для загрузки ковша других проблем, которые мне не нужны.
-Потенциальное решение, создайте связанный список для всех пакетов, как указано выше, но создайте их в fifo и переместите все записи вокруг, чтобы сохранить их в fifo.
например. отправить пакет 1, положить пакет в в ФИФО
отправки пакета 2, положить пакет в в ФИФО
получить NACK для пакета 1, ничего не делать
отправить пакет 3, положить пакет в в ФИФО
получить ACK для пакет 2, MemSet пакет 2 до 0х00 в FIFO
приема ACK для пакета 3, MemSet пакетов от 2 до 0х00 в Fifo
отправки пакета 4, поместите пакет в в FIFO
отправить пакет 5, положить пакет в в FIFO
больше нет места в FIFO, пройдите и перетасуйте все на фронт, потому что там, где пакеты 2 и 3 были пусты, теперь.
Не могли бы они их перетасовать в реальном времени, но тогда нам нужно перетасовать целую фило после каждого полученного пакета, и это похоже на ненужную работу?
Что я ищу для одного из вас, чтобы сказать «Jeez Ned, это неплохо, но если вы просто делаете xyz, то это экономит ваши кучи работы или оперативной памяти или сложности» или что-то в этом роде.
Просто хочу, чтобы пара людей отказывалась от идей действительно так, как вы обычно получаете лучшее решение. Мне нравится мое решение, но я чувствую, что я что-то пропустил, или, может быть, усложнил его? не уверен ... я просто не чувствую себя на 100% довольной этой идеей, я не думаю, но просто не могу думать о лучшем пути.
Вам действительно нужно жонглировать сразу несколькими пакетами? Почему бы просто не повторить один пакет, пока вы не получите ACK до передачи следующего? – kkrambo
Я тоже с этим боролся, но если я могу делать сразу несколько пакетов, тогда мне не нужно ждать «длинного» времени между пакетами, чтобы убедиться, что они туда попали, и вместо этого загружать кучу данных, которые нужно отправить быстро. – Ned
У меня есть некоторые сценарии, в которых я отправляю 100 пакетов в короткой последовательности, так что возможность иметь приемник обрабатывать их, пока передатчик будет отправлять сообщения, будет замечательным. Это значительно ускорит передачу данных – Ned