CSUP (Cross-platform Safe UART Protocol) - это надёжный кроссплатформенный протокол обмена сообщениями по UART, разработанный для встраиваемых систем, где требуется защита от потери или искажения данных. Протокол обеспечивает передачу кадров фиксированного формата с контролем целостности, подтверждением получения и механизмом разрешения коллизий.
- Каждое сообщение упаковывается во внутренний кадр, включающий служебные поля и контрольную сумму.
- Перед отправкой кадр кодируется методом COBS, который гарантирует отсутствие нулевых байт внутри данных и позволяет использовать
0x00как разделитель сообщений. - При получении устройство декодирует сообщение, проверяет CRC, анализирует поля и при необходимости отправляет подтверждение (ACK).
- В случае коллизий используются определённые политики разрешения.
| Технология | Пояснение |
|---|---|
| COBS (Consistent Overhead Byte Stuffing) | Метод кодирования, который удаляет нулевые байты, чтобы можно было использовать 0x00 как разделитель сообщений. |
| CRC (Cyclic Redundancy Check) | Алгоритм проверки целостности данных. По умолчанию используется CRC-16/CCITT-FALSE. |
| ACK (Acknowledgment) | Механизм подтверждения успешного получения сообщения. |
packet
+8: "Type"
+1: "ACK"
+7: "Frame ID"
+32: "Data (variable length)"
+16: "CRC"
- Type - идентификатор сообщения.
Диапазон
0x00–0xDFзарезервирован для пользовательских сообщений,0xE0–0xFF- для системных сообщений. - ACK - флаг, указывающий, требуется ли подтверждение доставки кадра.
- Frame ID - уникальный идентификатор кадра, используемый при подтверждении.
- Data - полезная нагрузка переменной длины, равной размеру фактически передаваемых данных. Максимально возможный размер поля
Dataзадаётся параметром шаблонаMaxMsgSize. - CRC - контрольная сумма кадра (по умолчанию CRC-16/CCITT-FALSE).
Перед отправкой внутренний кадр кодируется методом COBS (Consistent Overhead Byte Stuffing), что позволяет исключить байт 0x00 из полезных данных и тем самым безопасно использовать его как разделитель сообщений.
packet
+24: "COBS-encoded data (variable length)"
+8: "End (0x00)"
- COBS-encoded data - данные внутреннего кадра после кодирования.
- End (0x00) - маркер конца кадра, однозначно определяющий границу сообщения.
Таким образом, протокол увеличивает размер исходных данных на 6 байт (при длине сообщений свыше 256 байт возможно дополнительное увеличение размера на несколько байт из-за особенностей COBS-кодирования).
Пользователь может использовать типы в диапазоне 0x00-0xDF для различения собственных сообщений.
Для системных сообщений используются зарезервированные коды 0xE0-0xFF:
| Код | Тип | Назначение |
|---|---|---|
| 0xE0 | ACK | Подтверждение получения кадра |
| 0xE1 | HEARTBEAT | Проверка соединения |
| 0xE2 | VERSION_CHECK | Проверка версии протокола между устройствами |
Системное сообщение HEARTBEAT (0xE1) используется для синхронизации передачи и проверки соединения. При успешном получении оно подтверждается как обычное сообщение с флагом ACK.
Если на удалённой стороне в данный момент выполняется передача, требующая подтверждения, отправка heartbeat не прерывает её - данные будут повторно отправлены при следующей попытке.
Для получения подтверждения удалённое устройство должно вызвать
receive(),send()с ACK или собственныйheartbeat().
Протокол реализован без использования исключений, так как не все платформы их поддерживают.
В случае ошибки функции протокола возвращают один из кодов из перечисления Result, определённого в definitions.
Для удобства коды ошибок разделены на категории:
| Категория | Код | Описание |
|---|---|---|
| Успех | 0x00 | SUCCESS |
| Аппаратные ошибки | 0x10–0x12 | UART_ERROR, TIMEOUT, OVERFLOW |
| Формат / целостность | 0x20–0x26 | COBS_ERROR, CRC_ERROR, EMPTY_MSG, WRONG_MSG_TYPE, WRONG_MSG_SIZE, SYS_MSG_HANDLED, DUPLICATE_MSG |
| Логические / протокольные | 0x30–0x31 | MSG_COLLISION, MAX_ATTEMPT |
Коллизия возникает, когда оба устройства одновременно отправляют сообщения, требующие подтверждения. В этой ситуации необходимо определить, какое сообщение будет доставлено, а какое вернёт ошибку.
Метод разрешения коллизий зависит от выбранной политики:
| Политика | Совместимая политика | Назначение |
|---|---|---|
| BALANCED | BALANCED | Сообщение с меньшим Frame_ID получает приоритет |
| PRIORITY_SEND | NON_PRIORITY_SEND | Игнорирует входящие сообщения, продолжает отправку |
| NON_PRIORITY_SEND | PRIORITY_SEND | Всегда уступает отправителю |
Коллизия - это ненормальная ситуация. При проектировании системы следует стремиться избегать таких событий, используя шаблоны Master-Slave, Token Passing и другие методы управления порядком передачи.