1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/RT-Thread-Mirror-TinyFrame

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
README-ZH.md 16 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 5 месяцев назад 00c5d59

TinyFrame

TinyFrame — это простая библиотека, предназначенная для создания и анализа данных, передаваемых через последовательный интерфейс (например, UART, Telnet, сокет). Код написан так, чтобы быть совместимым с большинством компиляторов, использующих стандарт C99 или C89.

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

TinyFrame подходит для широкого спектра приложений, включая коммуникацию между микроконтроллерами, использование в качестве протокола для приложений на базе FTDI или передачу сообщений через UDP.

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

В TinyFrame также есть вспомогательные функции для построения и анализа полезной нагрузки сообщений, которые доступны в папке utils.

Порты

TinyFrame уже перенесён на множество языков:

  • Исходная реализация на C находится в этом репозитории.
  • Порт на Python — MightyPork/PonyFrame.
  • Порт на Rust — cpsdqs/tinyframe-rs.
  • Порт на JavaScript — cpsdqs/tinyframe-js.

Обратите внимание, что большинство портов являются экспериментальными и могут содержать различные ошибки или недостающие функции. Тестировщики приветствуются!

Функциональный обзор

Основные функции TinyFrame объясняются здесь. Для получения информации о конкретных API-функциях рекомендуется обратиться к комментариям в заголовочных файлах.

Структура фрейма

Каждый кадр состоит из заголовка и полезной нагрузки. Оба компонента могут быть защищены контрольной суммой, чтобы предотвратить повреждение формата кадра (например, неправильное поле длины) или отказ от повреждённой полезной нагрузки.

Заголовок кадра содержит идентификатор кадра и тип сообщения. Каждый новый кадр увеличивает идентификатор. Биты старшего разряда идентификатора фиксированы на 1 и 0, чтобы избежать конфликтов.

Идентификатор кадра можно повторно использовать в ответе для объединения двух сообщений. Значение поля типа определяется пользователем.

Все поля в библиотеке имеют настраиваемый размер. Изменяя поля в файле конфигурации, такие как TF_LEN_BYTES (1, 2 или 4), библиотека бесшовно переключается между использованием uint8_t, uint16_t и uint32_t для работы со всеми функциями, необходимыми в данной области.

,-----+-----+-----+------+------------+- - - -+-------------,
| SOF | ID  | LEN | TYPE | HEAD_CKSUM | DATA  | DATA_CKSUM  |
| 0-1 | 1-4 | 1-4 | 1-4  | 0-4        | ...   | 0-4         | <- size (bytes)
'-----+-----+-----+------+------------+- - - -+-------------'

SOF ......... start of frame, usually 0x01 (optional, configurable)
ID  ......... the frame ID (MSb is the peer bit)
LEN ......... number of data bytes in the frame
TYPE ........ message type (used to run Type Listeners, pick any values you like)
HEAD_CKSUM .. header checksum

DATA ........ LEN bytes of data
DATA_CKSUM .. data checksum (left out if LEN is 0)

Прослушиватели сообщений

TinyFrame основан на концепции прослушивателей сообщений. Прослушиватель — это функция обратного вызова, ожидающая получения определённого типа сообщения или идентификатора.

Существует три типа прослушивателей, упорядоченных по приоритету:

  • Прослушиватели идентификаторов — ожидают ответа.
  • Прослушиватели типов — ожидают сообщения с заданным полем типа.
  • Общие прослушиватели — резервные.

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

Прослушиватели идентификаторов используются для приёма ответов на запросы. При регистрации прослушивателя идентификатора можно добавить пользовательские данные в функцию обратного вызова прослушивателя. Эти данные (void *) могут быть любого типа переменной контекста приложения.

Для прослушивателей идентификаторов можно установить тайм-аут. Когда прослушиватель истекает, он будет вызван с NULL полезной нагрузкой данных перед удалением, чтобы позволить пользователю освободить любые данные. Это происходит только тогда, когда пользовательские данные не равны NULL.

Функция обратного вызова прослушивателя возвращает значение перечисления TF_Result:

  • TF_CLOSE — принять сообщение, удалить прослушиватель.
  • TF_STAY — принять сообщение, сохранить прослушиватель.
  • TF_RENEW — аналогично TF_STAY, но обновляет тайм-аут прослушивателя идентификаторов.
  • TF_NEXT — не принимать сообщение, сохранить прослушиватель и передать сообщение следующему прослушивателю, который может его обработать.

Буферы данных, многочастные фреймы

TinyFrame использует два буфера данных: небольшой буфер отправки и более крупный буфер приёма. Буфер отправки используется для подготовки байтов для одной отправки или для циклической отправки, если буфер недостаточно велик. Буфер может содержать только полный заголовок кадра, поэтому, например, 32 байта должно быть достаточно для коротких сообщений.

Используя функцию _Multipart(), можно разделить заголовок кадра и полезную нагрузку на несколько вызовов функций, позволяя приложению генерировать полезную нагрузку немедленно.

В отличие от буфера отправки, буфер приёма должен быть достаточно большим, чтобы вместить весь кадр. Это связано с тем, что окончательная контрольная сумма должна быть проверена до обработки кадра.

Если требуется кадр большего размера, чем возможный размер буфера приёма (например, в системах с ограниченной RAM на встраиваемых устройствах), рекомендуется реализовать механизм многосообщений на более высоком уровне и отправлять данные блоками.

Советы по использованию

  • Все функции, typedefs и макросы TinyFrame начинаются с префикса TF_.
  • Оба равноправных устройства должны включать библиотеку с одинаковыми параметрами конфигурации.
  • Обратитесь к TF_Integration.example.c и TF_Config.example.c для получения инструкций по настройке и интеграции библиотеки.
  • По возможности избегайте изменения файлов библиотеки. Это упрощает обновление.
  • Используйте TF_Init() с TF_MASTER или TF_SLAVE в качестве параметра для начала использования. Это создаёт дескриптор. Используйте TF_InitStatic(), чтобы избежать использования malloc().
  • Если вы используете несколько экземпляров, вы можете пометить их с помощью tf.userdata / tf.usertag.
  • Реализуйте TF_WriteImpl() — объявите его как extern в нижней части файла заголовка. Эта функция используется TF_Send() и другими для записи байтов в ваш UART (или другой физический уровень). Кадр может быть отправлен целиком или несколькими кадрами, в зависимости от его размера.
  • Если вам нужно использовать тайм-аут, регулярно вызывайте TF_Tick(). Счётчик определяет длину тика. Он используется для тайм-аута анализатора, когда он застревает в плохом состоянии (например, получает частичный кадр), и также может использоваться для тайм-аута прослушивателей идентификаторов.
  • Связывание прослушивателей типов или общих прослушивателей осуществляется с помощью TF_AddTypeListener() или TF_AddGenericListener().
  • Отправьте сообщение с помощью TF_Send(), TF_Query(), TF_SendSimple() или TF_QuerySimple(). Функция запроса требует обратного вызова прослушивателя (указатель функции), который добавляется как прослушиватель идентификаторов и ожидает ответа.
  • _Multipart() использует варианты вышеупомянутых функций отправки для генерации полезной нагрузки в нескольких вызовах функций. Затем полезная нагрузка отправляется с помощью TF_Multipart_Payload(), а кадр закрывается с помощью TF_Multipart_Close().
  • Если требуется пользовательская реализация контрольной суммы, выберите TF_CKSUM_CUSTOM8, 16 или 32, а затем выполните три функции контрольной суммы.
  • Чтобы ответить на сообщение (когда ваш прослушиватель вызывается), используйте TF_Respond() объект msg, полученный вами, заменив данные указателя (и len) на ответ.
  • В любое время вы можете вручную сбросить анализатор сообщений с помощью TF_ResetParser(). Он также может автоматически сбрасываться после тайм-аута, настроенного в файле конфигурации.

Проблемы, на которые следует обратить внимание

  • Если есть какие-либо пользовательские данные, прикреплённые к прослушивателю идентификаторов с тайм-аутом, то при истечении времени ожидания прослушивателя он будет вызван с полезной нагрузкой NULL msg->data, чтобы пользователь мог освободить пользовательские данные. Поэтому необходимо проверить msg->data перед продолжением обработки сообщения.
  • При отправке многочастных кадров библиотека блокирует Tx часть, чтобы предотвратить одновременный доступ. Перед отправкой другого содержимого кадр должен быть полностью отправлен и закрыт.
  • При использовании многопоточности не забудьте реализовать мьютекс для обратного вызова, чтобы избежать одновременного доступа к функциям Tx. Реализация по умолчанию не полностью потокобезопасна, поскольку она не может полагаться на специфичные для платформы ресурсы, такие как мьютексы или атомарный доступ. Установите TF_USE_MUTEX на 1 в файле конфигурации. Демонстрация написана для Linux и использует сокеты и фоновые процессы с применением clone(). Они пытаются имитировать поведение TinyFrame в асинхронных системах со встроенными Rx и Tx. Если вы не можете запустить демонстрацию, исходный файл всё равно будет хорошим примером.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/RT-Thread-Mirror-TinyFrame.git
git@gitlife.ru:oschina-mirror/RT-Thread-Mirror-TinyFrame.git
oschina-mirror
RT-Thread-Mirror-TinyFrame
RT-Thread-Mirror-TinyFrame
master