Simple, robust, and efficient serial communication

Stable Python C++17 TypeScript Code Size Impact: 1400 to 2600 bytes

  • Simple: Transmit RPCs and other data between devices over serial

  • Robust: Detect corruption and data loss

  • Efficient: Stream to transport without buffering

pw_hdlc implements a subset of the High-Level Data Link Control (HDLC) protocol. HDLC is a data link layer protocol intended for serial communication between devices and is standardized as ISO/IEC 13239:2002.

Encoding looks like this:

// Writes a span of data to a pw::stream::Writer and returns the status. This
// implementation uses the pw_checksum module to compute the CRC-32 frame check
// sequence.

#include "pw_hdlc/encoder.h"
#include "pw_hdlc/sys_io_stream.h"

int main() {
  pw::stream::SysIoWriter serial_writer;
  Status status = pw::hdlc::WriteUIFrame(123 /* address */, data, serial_writer);
  if (!status.ok()) {
    PW_LOG_INFO("Writing frame failed! %s", status.str());
# Read bytes from serial and encode HDLC frames

import serial
from pw_hdlc import encode

ser = serial.Serial()
address = 123
ser.write(encode.ui_frame(address, b'your data here!'))

And decoding looks like this:

// Read individual bytes from pw::sys_io and decode HDLC frames.

#include "pw_hdlc/decoder.h"
#include "pw_sys_io/sys_io.h"

int main() {
  std::byte data;
  std::array<std::byte, 128> decode_buffer;
  pw::hdlc::Decoder decoder(decode_buffer);
  while (true) {
    if (!pw::sys_io::ReadByte(&data).ok()) {
      // Log serial reading error
    Result<Frame> decoded_frame = decoder.Process(data);

    if (decoded_frame.ok()) {
      // Handle the decoded frame
# Decode data read from serial

import serial
from pw_hdlc import decode

ser = serial.Serial()
decoder = decode.FrameDecoder()

while True:
    for frame in decoder.process_valid_frames(
        # Handle the decoded frame
Get started & guides

How to set up and use pw_hdlc

API reference

Reference details about the pw_hdlc API


Design details about pw_hdlc

Code size analysis

The code size impact of pw_hdlc

RPC over HDLC example

A step-by-step example of sending RPCs over HDLC

Experimental async router

An experimental asynchronous HDLC router using pw_channel