Проблемы начинаются, когда мы видим, что на шине появляются паразитные сигналы: это может быть спецификой работы передатчика при его включении-выключении, внешние наводки и т.п. Например, я время от времени регистрировал характерные данные на своём МК и долго не мог понять их просхождение. Виновником оказалась моя привычка дрыгать ногами под столом и задевать штекер питания настольных аудиоколонок, которые очень сильно "звонили".
В этом случае мы должны оградиться от таких помех логическими, программными, методами: если я знаю характер сигнала, а именно, его количественные и временные характеристики, то я могу написать фильтр для сообщений от передатчика.
Количественно-временные показатели я могу получить с помощью таймера.
Алгоритм прост:
- Начальное состояние: счётчик обнулён, таймер остановлен;
- При получении первого сигнала таймер запускается, счётчик инкрементируется (как и при получении последующих сигналов);
- Если показания счётчика достигли длины ожидаемого сообщения, таймер останавливается и проверяется его значение: оно должно быть не меньше заранее заданной константы. Таким образом мы защищаемся от наводок, несущих большое количество данных за короткий период времени;
- Если таймер достиг максимального значения (т.е. времени, за которое сообщение точно должно было быть доставлено), то и таймер, и счётчик обнуляются. Вернулись к исходным значениям. Этим действием нейтралезуем короткие всплески на шине.
Теперь надо уточнить ещё один оставшийся момент: сколько мне нужно таймеров для предотвращения DoS в своей системе? Столько же, сколько и линий передачи данных? Достаточно лишь завести очередь, к кажной ячейки которой будет привязан свой таймер. Ячейка будет характеризоваться состоянием свободна-занята. Таким образом доступ к такой ячейке производиться свободно, но ни как в FIFO.
А вопрос о случае заполнения всей очереди при поступлении большого количество запросов (т.е. вопрос о величине и готовности "жертвования" системных таймеров) зависит от характеристик протокола передачи данных и от условий эксплуатации.
Кстати, для выходных сигналов так же потребуется своя очередь, поскольку они имеют свои временные характеристики.
/* Очередь входящих сообщений */
volatile struct sPeriphMsg {
unsigned long ulPeriphMsgBuf[PERIPH_MSG_LEN]; // буфер для пакета
unsigned short usBitCount; // счётчик
unsigned short usDevId; // ID устройства. Так я найду свою ячейку при поступлении следующего сигнала.
} g_sPeriphMsg[PERIPH_QUEUE_LEN];
volatile struct sPeriphMsg {
unsigned long ulPeriphMsgBuf[PERIPH_MSG_LEN]; // буфер для пакета
unsigned short usBitCount; // счётчик
unsigned short usDevId; // ID устройства. Так я найду свою ячейку при поступлении следующего сигнала.
} g_sPeriphMsg[PERIPH_QUEUE_LEN];
Комментариев нет:
Отправить комментарий