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

OSCHINA-MIRROR/RT-Thread-Mirror-TinyFrame

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Это зеркальный репозиторий, синхронизируется ежедневно с исходного репозитория.
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

TinyFrame

TinyFrame — это простая библиотека для создания и анализа фреймов данных, отправляемых через последовательный интерфейс (например, UART, telnet, сокет). Код написан с использованием --std=gnu99 и в основном совместим с --std=gnu89.

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

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

Библиотека позволяет регистрировать прослушиватели (функции обратного вызова) для ожидания:

  • любого фрейма;
  • конкретного типа фрейма;
  • определённого идентификатора сообщения. Этот высокоуровневый API достаточно универсален для реализации большинства шаблонов связи.

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

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

Порты

TinyFrame был портирован на несколько языков:

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

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

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

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

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

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

Заголовок фрейма содержит идентификатор фрейма и тип сообщения. Идентификатор фрейма увеличивается с каждым новым сообщением. Самый старший бит поля ID установлен в 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 ......... начало фрейма, обычно 0x01 (необязательно, настраивается)
ID  ......... идентификатор фрейма (старший бит — бит участника)
LEN ......... количество байтов данных во фрейме
TYPE ........ тип сообщения (можно использовать любые значения)
HEAD_CKSUM .. контрольная сумма заголовка

DATA ........ LEN байт данных
DATA_CKSUM .. контрольная сумма данных (опускается, если LEN равен 0)

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

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

Существует 3 типа прослушивателей в порядке приоритета:

  • прослушиватели идентификаторов — ожидание ответа;
  • прослушиватели типов — ожидание сообщения заданного типа;
  • общие прослушиватели — запасной вариант.

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

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

Обратные вызовы слушателей возвращают значения перечисления TF_Result:

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

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

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

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

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

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

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

  • Все функции TinyFrame, typedefs и макросы начинаются с префикса 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_AcceptChar(tf, byte), чтобы передать данные чтения в TF. TF_Accept(tf, bytes, count) примет несколько байтов.
  • Если вы хотите использовать тайм-ауты, периодически вызывайте TF_Tick(). Период вызова определяет длину одного тика. Он используется для тайм-аута парсера в случае, если он застревает в плохом состоянии (например, получая частичный фрейм), а также может тайм-аут ID слушателей.
  • Свяжите тип или универсальные слушатели, используя TF_AddTypeListener() или TF_AddGenericListener().
  • Отправьте сообщение, используя TF_Send(), TF_Query(), TF_SendSimple(), TF_QuerySimple(). Функции запроса принимают обратный вызов слушателя (указатель на функцию), который будет добавлен в качестве ID слушателя и ожидает ответа.
  • Используйте вариант *_Multipart() вышеуказанных функций отправки для полезных нагрузок, созданных в нескольких вызовах функций. Полезная нагрузка отправляется позже путём вызова TF_Multipart_Payload(), и фрейм закрывается с помощью TF_Multipart_Close().
  • Если требуется пользовательская реализация контрольной суммы, выберите TF_CKSUM_CUSTOM8, 16 или 32 и реализуйте три функции контрольной суммы.
  • Чтобы ответить на сообщение (когда ваш слушатель вызывается), используйте TF_Respond() с объектом msg, который вы получили, заменив указатель datalen) ответом.
  • В любое время вы можете вручную сбросить синтаксический анализатор сообщения с помощью TF_ResetParser(). Его также можно сбросить автоматически после тайм-аута, настроенного в файле конфигурации.

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

  • Если какие-либо пользовательские данные прикреплены к ID слушателю с тайм-аутом, когда срок действия слушателя истечёт, он будет вызван с NULL msg->data, чтобы позволить пользователю освободить пользовательские данные. Поэтому это необходимо.

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

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

Введение

TinyFrame — это простая библиотека для создания и анализа кадров данных, передаваемых через последовательный интерфейс (например, UART, Telnet, сокет). Развернуть Свернуть
MIT
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загружен новый тег 2.3.0 4 месяца назад
Загружен новый тег 2.1.0 4 месяца назад
Загружен новый тег 2.0.5 4 месяца назад
Загружен новый тег 2.0.4 4 месяца назад
Загружен новый тег 2.0.3 4 месяца назад
Загрузить больше
Больше нет результатов для загрузки
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