В этом тексте я напишу атрибуты хорошего и простого Master<->Slave протокола канального уровня для пакетного обмена информацией между устройствами на общих шинах таких как RS485, CAN, LoRa, BLE, Lin или соединений типа точка-точка UART, RS232.

Несмотря на то, что есть стандартизированные канальные протоколы ModBus, DLMS, RDS, UBX, NEC, Pelco-D, yModem, многие российские компании всё же колхозят свои собственные внутренние протоколы для взаимодействия между электронными платами.

Тут представлены общие атрибуты и пожелания для таких доморощенных протоколов.

*1--M2M протокол должен быть бинарным

Это сделает трафик компактнее и проще в обработке на стороне firmware. 

*2--У пакета должна быть преамбула (синхробайты)

Преамбула нужна, чтобы программный конечный автомат приема мог выхватывать пакеты из потока байтов.

*3--Преамбула должна быть параметризируемая

Преамбулу следует параметризировать так как должна быть предусмотрена возможность туннелирования пакетов одного и того же протокола. То есть матрешка пакетов из одного и того же протокола. Это особенно полезно когда физика трансивера за раз может отправить только N байт, а сам пакет, например, M=2N байт. При этом получается N<M. В этом случае маленькими пакетами передается большой пакет как поток байтов.

*4--Должен быть порядковый номер пакета (Sequence Number)

Это позволит на стороне приемника определить потерю непрерывности потока. Порядковый номер пакета это также требование стандарта ISO-26262

*5--Должно быть поле, которое отвечает за длину полезных данных

Это позволит сделать протокол универсальным и сделает возможность передавать данные разной длинны.

6--Передавать многобайтовые поля в заголовках следует в Big Endian (optional)

Так проще анализировать сырые пакеты глазами в HEX редакторе или на осциллографе. Даже если микроконтроллер Little Endian, то производительность современных микроконтроллеров достаточно высока, чтобы инвертировать байты для всех типов на лету.

*7--В пакете должна быть контрольная сумма CRC

Это позволит проверить, что пакет не повредился в процессе передачи из-за радиопомех или дребезга контактов. 

*8--Контрольная сумма должна быть в конце пакета

Это позволит проще вычислять СRС, захватывая как данные так и заголовок.

9--Должен быть идентификатор типа полезных данных(optional)

Это позволит приемнику быстрее понять как интерпретировать полезные данные внутри пакета.

*10--Должно быть подтверждение принятого пакета (Ack)

Так Master Node(а) поймет, что Slave Node(а) точно съела пакет

*11--Должна быть повторная отправка в случае отсутствия подтверждения (ReTx)

Это повысит надежность передачи данных.

12--В заголовке должна быть TimeStamp отправки пакета миллисекундной точности (optional)

Временная отметка внутри пакета нужна для отладки хронологии диалога и оценки быстродействия обработки. Есть аппаратные способы прослушивать трафик в той же RS485. По логу надо уметь анализировать тайминги. Сортировать хронологию, оценивать паузы.

*13--Спецификацию протокола следует делать в формате общих электронных таблиц

Делать спеки протоколов в *.doc или *.pdf это уже архаично. Электронные таблицы идеально подходят для представления структуры пакетов. Электронные таблицы как будто бы и созданы для представления пакетов. Любой пакет это по факту обыкновенный массив. В электронных таблицах можно сортировать пакеты, быстро искать нужный пакет, раскрашивать поля, проверять полноту, находить свободные идентификаторы, и даже авто генерировать парсеры в виде С-кода для синтаксического разбора пакетов.

*14--Должно быть шифрование PayLoad(а)

В случае ответственных задач имеет смысл добавить шифрование полезных данных пакета ,чтобы нелегальные узлы не могли наблюдать за работой системы и подключать к общей шине свою шпионскую телеметрию и тем более телематику для совершения диверсий.

*15--Пакетная синхронизация должна производится по преамбуле

Раз приняли преамбулу и CRC валидная значит пришел новый пакет. Так прошивка сможет выделять пакеты из потока байт в UART.

*16--Пакетная синхронизация должна производится также по TimeOut(у)

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

*17--Должен быть периодический Hello пакет для каждой node(ы) (keep alive messages)

Мастер должен периодически опрашивать каждую Node(у) даже если нет PayLoad для этой Node(ы). (Требование ISO-26262). Это позволит убедиться, что есть link. То есть что провода не оторвались, софт не завис. В случае пропадания link(а) сгенерировать событие аварии и предложить предпринять меры по ремонту сети.

Вывод
Это основные требования к выбору кибернетики очередного бинарного протокола передачи данных. Протокола для M2M взаимодействий. Вообще не надо изобретать очередной проприетарный протокол. Воспользуйтесь спецификацией любого уже существующего канального протокола. Вероятно вам подойдет ModBus, Can, DLMS, RDS, UBX, xModem, EtherCAT. Стандартизированный протокол добавит вашему устройству совместимость с другим оборудованием и софтом. Можно будет взять программную реализацию с GitHub и просто покрыть ее своими модульными тестами.

Если вам известны еще особенные атрибуты хорошего канального протокола передачи данных, то пишите их в комментарии.

Также пишите про те стандартизированные канальные протоколы с которыми вам приходилось сталкиваться и делитель впечатлениями от работы с разными протоколами канального уровня.

Комментарии (13)


  1. sunnybear
    12.08.2022 20:20
    +4

    Переизобрели модель OSI ? :)


    1. ilynxy
      13.08.2022 00:25
      +8

      Видится, что автор сделал ровно наоборот. Смешал мух и котлеты. Протокол должен быть легко разделяем по уровням. Потому как преамбулы и пакетизация должны находиться на одном уровне, а к примеру, пэйлоад и контрольные суммы на другом. Если в качестве транспорта используется udp — нет смысла городить пакетизацию, преамбулы и прочая — это все уже реализовано, оставляем только часть ответственную за обработку пэйлоада. Если у нас голый битовый/байтовый поток типа uart — да, все это может понадобится в каком-то виде. Но обработчик пейлоада не меняется, над ним появляется надстройка которая выковыривает с транспорта собсно пейлоад и отправляет на обработку. Есть, конечно, нюансы в виде таймштампов или там контрольных сум, на каком уровне они должны быть, но это вопрос требований к точности и достоверности.

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

      Про шифрование тоже хорошо. И была б это рекомендация или пожелание, одно дело, а то ведь маст хэв. Хардкорного эмбедда на 8битных контроллерах вам в хату.


  1. MUTbKA98
    12.08.2022 20:53
    +4

    Зачем нужен бит "честности" при живом CRC? Чтобы что?


    1. Goron_Dekar
      13.08.2022 00:11
      +2

      чтобы не считать CRC для заведомо битого пакета. Parity разрешается аппаратно у всех современных МК.


      1. MUTbKA98
        13.08.2022 18:08
        +1

        Ну так и CRC аппаратный уже много где. Не везде, впрочем, он сильно гибко конфигурируемый, но надо просто не извращаться с выбором полинома.


  1. tmxx
    12.08.2022 21:10
    +4

    В упустили главное правило: "не начинайте колхозить протокол с формата пакетов"


    1. aabzel Автор
      12.08.2022 21:38
      -2

      C чего же тогда вести разработку протокола если не с формата пакета?


      1. Siemargl
        12.08.2022 22:55
        +4

        По заветам ПМБука, с анализа ситуации, в т.ч ошибок предшественников.


      1. tmxx
        14.08.2022 01:28
        +3

        Вообще-то, желание упорядочить требования к протоколу заслуживает одобрения, я считаю.

        Хотя классификации подобного рода встречались и ранее

        животные делятся на:

        а) принадлежащих Императору,

        б) набальзамированных,

        в) прирученных,

        г) молочных поросят,

        д) сирен,

        е) сказочных,

        ж) бродячих собак,

        з) включённых в эту классификацию,

        и) бегающих как сумасшедшие,

        к) бесчисленных,

        л) нарисованных тончайшей кистью из верблюжьей шерсти,

        м) прочих,

        н) разбивших цветочную вазу,

        о) похожих издали на мух.

        Видите ли, формат пакета - технический компромисс, получающийся в результате анализа требований к протоколу, как части системы, обеспечивающей решение какой-то задачи. Поэтому начинать надо с другого.

        Во-первых, посмотреть на модель ISO/OSI, как вам уже указали ранее. Как справедливо замечено, вы увидите, что в ваших требованиях смешаны части формата, отвечающие за различные уровни. После этого надо раскаяться и все-таки почитать про эту модель, она вам понадобится, если вы хотите реализовать хороший протокол.

        Во-вторых, понять, что в первую очередь надо рассмотреть уровни модели от 8 и выше, которых в текущей редакции модели нет. Это требования к системе, в которой будет применяться протокол. Здесь поможет внимательное чтение ПМБука или даже ГОСТ на ТЗ для АСУ.

        Вот, примерно накидал (здесь также смешаны уровни, но это и не статья):

        1. Имеет смысл рассматривать сценарии использования на всех этапах жизненного цикла вашего оборудования. Например, может оказаться, что протокол предназначен для настройки системы обслуживающим персоналом, в этом случае часто удобно делать его текстовым. Для payload M2M протоколов часто используется JSON или XML, в том числе, со сжатием, в этом случае объем сравним с бинарным представлением. Библиотеки для работы с ними не очень сложные. Таким образом, п.1 можно вычеркнуть. Программисты серверной части скажут вам спасибо.

        2. Можно проанализировать окружение: протокол нужен для связи между микроконтроллером и датчиком в пределах одной платы или для контроля транспортных средств в пределах региона? Система состоит из однородных или разнородных элементов? Протокол открытый или закрытый? Планируется ли расширение номенклатуры, совместимость с имеющимися устройствами или подключение устройств сторонних производителей? Например, если у вас внутренний протокол между электронными платами по шине SPI с сигналом #CS, то пп.2,3,4,5,6,8,12,15,16,17 можно вычеркнуть, если по шине I2C, то можно вычеркнуть пп.2,3,5,10,15.

        3. Кроме того, стоит рассмотреть физические ограничения: вычислительная мощность узлов, энергопотребление, требуемая скорость обмена, задержки, надежность. Предполагаемая среда передачи данных и/или аппаратная реализация. Например, если интерфейс CAN, то п.2,4,5,6,7,8,10,15,17 не имеют смысла. Если оптика, то п.14 не выглядит необходимым.

        Таким образом, аргументированным выглядит только п.13.

        Вооружившись средствами редактирования электронных таблиц и моделью ISO/OSI следует определить требования к уровням сверху вниз, возможно, не все уровни модели будут необходимы:

        1. Имеет смысл прикинуть API, лучше для каждого уровня.

        2. Будет полезно описать виды передаваемых данных и требования к ним.

        3. Также не лишним будет подумать над структурой сети: точка-точка, ведущий-ведомый, мультимастер, одноранговая сеть, ретрансляция т.п.

        4. После этого станут яснее требования к алгоритмам взаимодействия узлов: handshaking, PnP, подписки, каналы, разделяемая память, квитирование, таймауты, арбитраж, асинхронные сообщения и т.п.

        пп.1-4 повторять до просветления.

        После этого оценить затраты на реализацию. Не стоит забывать про альтернативные варианты. (Имеет смысл их все-таки изучить, потому что CAN и ModeBus это немного про разное).

        Описать форматы пакетов.


  1. select26
    12.08.2022 23:19
    +3

    Начинаю читать и вижу "канальный протокол ModeBus". Ну с кем не бывает - опечатка. А потом вижу эту опечатку в тексте не раз.

    А дальше читаю о том, что "многие российские компании просто не могут себе позволить купить на них лицензию и спецификацию". На открытый протокол Modbus. Купить не могут.

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

    Но читать я дальше не стал - нет доверия к техническому тексту, который начинается такими ляпами.


  1. a-tk
    15.08.2022 09:34

    Очередное частное мнение, выданное под заголовком общих правил...

    Вы бы хотя бы область применимости утверждений обозначили.


  1. a-tk
    15.08.2022 09:54
    -1

    Кстати, по поводу CRC. Когда Вы пишете CRC, Вы подразумеваете именно CRC или же любой алгоритм вычисления контрольной суммы?


  1. fiego
    15.08.2022 15:44
    +1

    Хочется много и по пунктам рассказать автору. Но, если коротко, он выдал свой собственный опыт как он его понимает, поделился. Видимо, есть богатый опыт изобретения собственных протоколов, который ему и говорит, что их изобретать было не нужно.