Тайм-аут передачи по CAN-шине Linux
сценарий
Существует устройство на базе Linux, подключенное к шине CAN. Устройство периодически передает сообщение CAN. Характер данных, переносимых этим сообщением, подобен измерению, а не команде, то есть, действительно, действительным является только самое последнее, и если некоторые сообщения потеряны, это не проблема, если последнее сообщение было успешно получено.
Затем рассматриваемое устройство отключается от шины CAN на некоторое время, которое намного превышает интервал между последующими передачами сообщений. Логика устройства все еще пытается передать сообщения, но, поскольку шина отключена, контроллер CAN не может передать ни одно из них, поэтому сообщения накапливаются в очереди TX.
Через некоторое время соединение по шине CAN восстанавливается, и все накопленные сообщения выводятся на шину один за другим.
проблема
- При восстановлении соединения с шиной CAN из очереди TX будет передано неопределенное количество устаревших сообщений.
- Хотя соединение по шине CAN по-прежнему недоступно, но очередь передачи уже заполнена, передача некоторых самых последних сообщений (т. Е. Единственно допустимых сообщений) будет отклонена.
- Как только соединение по шине CAN будет восстановлено, во время очистки очереди TX будет происходить кратковременный всплеск трафика. Это может изменить расписание запуска по времени, если оно используется (в моем случае).
Вопрос
Мое приложение использует драйвер SocketCAN, поэтому в основном вопрос должен быть применен к SocketCAN, но другие варианты также рассматриваются, если они есть.
Я вижу два возможных решения: определить тайм-аут передачи сообщения (если сообщение не было передано в течение некоторого предварительно определенного количества, если время, оно будет автоматически отброшено), или прервать передачу устаревших сообщений вручную (хотя я сомневаюсь, что это вообще возможно с сокетом API).
Поскольку первый вариант представляется мне наиболее реальным, вопрос заключается в следующем:
- Как определить время ожидания передачи для интерфейса CAN в Linux?
- Существуют ли другие варианты для решения проблем, описанных выше, кроме тайм-аутов TX?
3 ответа
Некоторые хорошие ответы были предоставлены списком рассылки linux-can: http://thread.gmane.org/gmane.linux.can/4167
Моим решением этой проблемы было выключение и повторное включение устройства:
void
clear_device_queue
(void)
{
if (!queue_cleared)
{
const char
*dev = getenv("MOTOR_CAN_DEVICE");
char
cmd[1024];
sprintf(cmd, "sudo ip link set down %s", dev);
system(cmd);
usleep(500000);
sprintf(cmd, "sudo ip link set up %s", dev);
system(cmd);
queue_cleared = true;
}
}
Я не знаю внутреннего устройства SocketCAN, но думаю, что большая часть проблемы должна быть решена на более общем, логическом уровне.
Раньше нужно прояснить один аспект: вопрос включает теги, критичные для безопасности...
Если связь CAN не имеет отношения к реализации функции безопасности, вы можете выбрать любое решение, которое сочтете полезным. Могут быть части второй альтернативы, которые будут вам полезны и в этом случае, но это не mandatorx.
Если связь, тем не менее, используется в контексте безопасности, должна быть концепция, которая учитывает требования, налагаемые IEC 61508 (безопасность программируемых электронных систем в целом) и IEC 61784-x/62280 (протоколы безопасной связи).. Эти стандарты обычно приводят к некоторым мерам протокола, которые пригодятся при любой встроенной связи, но особенно для настоящей проблемы:
- Добавьте счетчик последовательностей в кадры протокола. Приемник должен следить за тем, чтобы значения счетчика, которые он видит, не делали больших "скачков", чем разрешено (например, если вы позволяете пропустить 2 кадра по пути, максимальное приращение счетчика может быть +3. Шина CAN может удвоить кадр., так что увеличение счетчика на +0 тоже должно быть допустимым.
- Получатель должен следить за тем, чтобы за каждым принятым кадром следовал другой в течение периода ожидания. Если ваше CAN-соединение потеряно и восстановлено тем временем, это зависит от того, было ли прерывание более длительным или в пределах тайм-аута. Кроме того, получатель может отслеживать, что кадр не следует за предыдущим слишком рано, но если кадры содержат правильные данные, обычно в этом нет необходимости.
[...] По своей природе данные, переносимые этим сообщением, похожи на измерение, а не на команду, то есть только самое последнее действительно действительное, и если некоторые сообщения потеряны, это не проблема, если последнее было получено успешно.
Через CAN вы никогда не должны передавать "команды" в том смысле, что каждая из них может инициировать изменение, например "переключить состояние вывода" или "увеличить установленное значение на одну единицу", потому что вы никогда не узнаете, ударит ли вас дублирование кадра или нет..
Кроме того, вы никогда не должны сообщать "что-либо, имеющее отношение к безопасности" через один кадр, потому что любой кадр может быть потерян или поврежден из-за ошибки. Вместо этого "команды" должны передаваться (как измерения) в виде потока периодических кадров с обновлениями измерений или установленных значений.
Теперь, чтобы получить необходимую доступность из конструкции протокола, очередь TX не должна быть длинной. Если вы действительно чувствуете, что вам нужна эта очередь, возможно, шина перегружена по сравнению с требованиями по времени, с которыми она сталкивается. С моей точки зрения, "очередь" передачи не должна быть длиннее одного-двух кадров. Тогда проблема восстановления CAN-соединения почти решена...