План спасения

Nov 06, 2019 14:11


Извините,  я не могу сдерживаться. Я вчера это чинил до четырёх утра, потому что в  семь утра это уже надо было везти и ставить. Не конкретно вот это,  разумеется, а вообще порядка двух тысяч строк кода, написанных вот так. Я  их с утра понедельника чиню.

***

Задача - услышать бикон  (стоит в подъезжающем авто), аутентифицировать, проверить по базе, что  этому можно въезжать, определить расстояние и направление движения, в  нужный момент дать команду на открывание ворот. Смысл - не просто  аутентификация транспондера, а чтобы авто проезжало через уже  открывшиеся ворота, не задерживаясь перед ними. И чтобы при этом ворота  не реагировали на те же транспондеры в машинах, например, стоящих на  стоянке в двадцати метрах за воротами.

Ну т.е.
1) слышим бикон
2) отвечаем ему ACK, в котором есть случайное число
 3) бикон отвечает пакетом с этим же числом, подписанным  криптографической подписью с ключом, известным только бикону и базе  (аутентифицировали)
4) база запускает процедуру измерения расстояния  - в ней всё уже формируется на уровне железа: база излучает специальный  пакет, бикон на него отвечает (ToF на LoRa в диапазоне 2,4 ГГц)
5) база повторяет измерение три раза с интервалом 1 секунда (определяем направление движения)

Теперь решение.

Как выдерживается секундный интервал между измерениями?

Миганием светодида. Ну т.е. зовётся функция мигания светодиода, у  которой параметры - сколько раз, период 1, период 0. 5, 100, 100 - вот и  получилась секунда.



Если вы думаете, что пора смеяться, то нет, ещё рано.

Что происходит дальше?

Дальше синхронно на мастере и слейве запускается процедура вычисления  расстояния - мастер испускает пакет, слейв на него отвечает (железно, с  гарантированной величиной задержки).

Между миганием и вычислением  есть выхлоп в консоль, ну что-то типа printf(«Sending ranging request  to the beacon\n»). Ну и в биконе что-то типа printf(«Waiting for ranging  request from the gateway\n»). Безобидное совершенно.

Так вот,  если на слейве эта строчка длиннее, чем на мастере, примерно на 2 или 3  буквы, то... правильно! Мастер испускает пакет раньше, чем слейв  включает приём! Потому что printf у нас - блокирующая функция!

И вот тогда - таймаут. Причём всегда таймаут, на всех измерениях.

***
Я просто в немом восхищении смотрю

Там столько способов прострелить себе ногу

1) вывод в консоль включается только при сборке отладочной прошивки,  т.е. отладку включать нельзя, всё ломается (или нет, зависит от длины  строчки, см. выше)

2) можно в настройках проекта включить  неблокирующий printf, но! Это даже круче! Потому что как только кто-то  начинает за него конкурировать, второй запрос на вывод в консоль при не  отработанном первом автоматом становится блокирующим - ну т.к. канал DMA  и USART у нас один, соответственно, там мьютекс стоит.

При этом решается в одну строчку ровно:

1) на слейве ставим таймаут на приём чего-нибудь типа 50 мс (штатный параметр функции, запускающей приём, 0 новых строчек кода)
2) на мастере делаем задержку передачи 25 мс (lptimer_sleep(25), одна строчка кода)

Всё. Это покрывает любые возможные рассинхронизации.

ОДНА СУКА СТРОЧКА.

***

И нет, это написано не джуном зелёным. Это написано человеком, у которого в резюме 11 лет опыта, в том числе в автомобильной электронике и системах промышленной автоматики.

Previous post Next post
Up