Skip to content

Framing

Framing wraps messages with headers and checksums for reliable communication over serial links, network sockets, or any byte stream.

Why Framing

When sending data over a communication channel, you need to:

  1. Identify message boundaries
  2. Validate message integrity
  3. Route messages by type

Framing solves these problems by adding structure around your message data.

Standard Profiles

Use these pre-configured profiles for common scenarios:

ProfileOverheadMax PayloadUse Case
Standard6 bytes255 bytesGeneral serial/UART
Sensor2 bytesN/ALow-bandwidth sensors
IPC1 byteN/ATrusted board-to-board
Bulk8 bytes64 KBFirmware/file transfer
Network11 bytes64 KBMulti-node networks

Quick Decision Guide

Do you need routing between nodes? → Network
Is it a trusted internal link (SPI)? → IPC
Are you bandwidth-limited (radio)? → Sensor
Sending large files (> 255 bytes)? → Bulk
Otherwise → Standard (recommended)

Basic Frame Structure

The Standard profile (recommended for most uses):

┌────────┬────────┬────────┬────────┬─────────┬─────────┬─────────┐
│ START1 │ START2 │ LENGTH │ MSG_ID │ PAYLOAD │ CRC1 │ CRC2 │
│ 0x90 │ 0x71 │ 1 byte │ 1 byte │ N bytes │ 1 byte │ 1 byte │
└────────┴────────┴────────┴────────┴─────────┴─────────┴─────────┘
  • Start bytes: Sync markers to find frame boundaries
  • Length: Payload size (0-255)
  • MSG_ID: Message type identifier
  • Payload: Your message data
  • CRC: Fletcher-16 checksum for error detection

Usage Example

from frame_profiles import ProfileStandardWriter, ProfileStandardAccumulatingReader
from struct_frame.generated.messages import MyMessage, get_message_info
# Encode
msg = MyMessage(value=42)
writer = ProfileStandardWriter(1024)
writer.write(msg)
frame = writer.data()
# Decode
reader = ProfileStandardAccumulatingReader(get_message_info=get_message_info)
for byte in frame:
result = reader.push_byte(byte)
if result and result.valid:
print(f"Message {result.msg_id}: {result.msg_data}")
#include "frame_profiles.hpp"
using namespace FrameParsers;
// Encode
uint8_t buffer[1024];
ProfileStandardWriter writer(buffer, sizeof(buffer));
writer.write(msg);
// Decode
ProfileStandardAccumulatingReader reader;
reader.add_data(buffer, buffer_size);
while (auto result = reader.next()) {
// Process message - result is valid due to operator bool()
}

For more details, see Framing Details.