Pigweed AI summary: The pw_hdlc module provides a lightweight, simple, and easy way to transmit RPCs and other data between devices over serial communication. It supports detecting corruption and data loss, as well as streaming data to transport without buffering. The module uses a subset of the High-Level Data Link Control (HDLC) protocol and is designed for embedded devices. The size of the module is around 1400 to 2600 bytes. The module also includes an example implementation of pw_rpc's system_server backend for

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

  • Transmit RPCs and other data between devices over serial

  • Detect corruption and data loss

  • Stream to transport without buffering

Background#

Pigweed AI summary: The High-Level Data Link Control (HDLC) is a protocol designed for serial communication between devices at the data link layer. It is standardized as ISO/IEC 13239:2002.

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

Our solution#

Pigweed AI summary: The "pw_hdlc" module provides a frame-oriented transport using a subset of the HDLC protocol. It supports sending between embedded devices or the host and can be used with "pw_rpc" to enable remote procedure calls on embedded devices. The module has two primary functions: encoding data by constructing a frame with escaped payload bytes and frame check sequence, and decoding data by unescaping received bytes, verifying the frame check sequence, and returning successfully decoded frames. The module only supports unnumbered information frames

The pw_hdlc module provides a simple, robust frame-oriented transport that uses a subset of the HDLC protocol. pw_hdlc supports sending between embedded devices or the host. It can be used with pw_rpc to enable remote procedure calls (RPCs) on embedded on devices.

pw_hdlc has two primary functions:

  • Encoding data by constructing a frame with the escaped payload bytes and frame check sequence.

  • Decoding data by unescaping the received bytes, verifying the frame check sequence, and returning successfully decoded frames.

Design considerations#

Pigweed AI summary: The "pw_hdlc" only supports unnumbered information frames and uses special escaped bytes to mark the beginning and end of a frame. The frame data is stored in a buffer until the end-of-frame delimiter byte is read. For more information, refer to the "pw_hdlc: Design" section.

  • pw_hdlc only supports unnumbered information frames.

  • It uses special escaped bytes to mark the beginning and end of a frame.

  • Frame data is stored in a buffer until the end-of-frame delimiter byte is read.

See pw_hdlc: Design for more information.

Size report#

Pigweed AI summary: The "pw_hdlc" module prioritizes robustness and flexibility over binary size or performance. There are two size reports available, one showing the cost of everything needed to use HDLC, including dependencies on common modules like CRC32 and variable-length integer handling, and the other showing the cost if your application is already linking those functions. The reports include information on the size of HDLC encode and decode, with and without CRC and varint, and the delta in size for each function. The reports

pw_hdlc currently optimizes for robustness and flexibility instead of binary size or performance.

There are two size reports: the first shows the cost of everything needed to use HDLC, including the dependencies on common modules like CRC32 from pw_checksum and variable-length integer handling from pw_varint. The other is the cost if your application is already linking those functions. pw_varint is commonly used since it’s necessary for protocol buffer handling, so is often already present.

Label

Segment

Delta

HDLC encode and decode

FLASH

+68

pw::size_report::HdlcSizeReport()

+34

pw::stream::Stream::Write()

-2

pw_varint_ZigZagEncode

-2

pw_log_tokenized_HandleLog

-4

p05.0

NEW

+1,024

_pw_checksum_InternalCrc32EightBit::kCrc32Table

NEW

+264

pw::hdlc::internal::Encoder::WriteData()

NEW

+216

pw::hdlc::Decoder::Process()

NEW

+174

pw::hdlc::WriteUIFrame()

NEW

+146

pw_varint_DecodeCustom

NEW

+102

pw::hdlc::Frame::Parse()

NEW

+96

pw::hdlc::internal::Encoder::StartFrame()

NEW

+76

pw::hdlc::Decoder::CheckFrame()

NEW

+74

pw::hdlc::Decoder::AppendByte()

NEW

+64

pw::hdlc::internal::EscapeAndWrite()

NEW

+46

pw::hdlc::Decoder::VerifyFrameCheckSequence()

NEW

+44

pw::hdlc::internal::Encoder::FinishFrame()

NEW

+40

_pw_checksum_InternalCrc32EightBit

NEW

+14

pw::internal_result::StatusOrData<>::StatusOrData<>()

NEW

+12

pw::hdlc::NeedsEscaping()

NEW

+6

__gnu_cxx::__ops::_Iter_pred<>::operator()<>()

NEW

+2

pw::hdlc::kEscapedEscape

NEW

+2

pw::hdlc::kEscapedFlag

+2,496

HDLC encode and decode, ignoring CRC and varint

FLASH

+68

pw::size_report::HdlcSizeReport()

+34

pw::stream::Stream::Write()

-2

pw_log_tokenized_HandleLog

-4

p05.0

NEW

+264

pw::hdlc::internal::Encoder::WriteData()

NEW

+216

pw::hdlc::Decoder::Process()

NEW

+174

pw::hdlc::WriteUIFrame()

NEW

+102

pw::hdlc::Frame::Parse()

NEW

+96

pw::hdlc::internal::Encoder::StartFrame()

NEW

+76

pw::hdlc::Decoder::CheckFrame()

NEW

+74

pw::hdlc::Decoder::AppendByte()

NEW

+64

pw::hdlc::internal::EscapeAndWrite()

NEW

+46

pw::hdlc::Decoder::VerifyFrameCheckSequence()

NEW

+44

pw::hdlc::internal::Encoder::FinishFrame()

NEW

+14

pw::internal_result::StatusOrData<>::StatusOrData<>()

NEW

+12

pw::hdlc::NeedsEscaping()

NEW

+6

__gnu_cxx::__ops::_Iter_pred<>::operator()<>()

NEW

+2

pw::hdlc::kEscapedEscape

NEW

+2

pw::hdlc::kEscapedFlag

+1,288

Roadmap#

Pigweed AI summary: The "Roadmap" section outlines plans to expand protocol support for "pw_hdlc," which currently only supports unnumbered information frames. The goal is to add support for different frame types and extended control fields in the future.

  • Expanded protocol support - pw_hdlc currently only supports unnumbered information frames. Support for different frame types and extended control fields may be added in the future.

Getting started#

Pigweed AI summary: This section provides information on how to use HDLC with pw_rpc, including an example project called pw_hdlc: RPC over HDLC. It also includes an example implementation of pw_rpc's system_server facade that sends HDLC encoded RPC packets via pw_sys_io, but is not suitable for performance-sensitive applications. Additionally, it provides instructions on how to enable pw_hdlc.pw_rpc for Zephyr.

For an example of how to use HDLC with pw_rpc, see the pw_hdlc: RPC over HDLC example project.

Example pw::rpc::system_server backend#

Pigweed AI summary: This module provides an example implementation of pw_rpc's system_server facade, which sends HDLC encoded RPC packets via pw_sys_io. However, it has blocking sends/reads and is not suitable for performance-sensitive applications. It serves as a simplistic example for quickly setting up RPC over HDLC on bare-metal targets.

This module includes an example implementation of pw_rpc’s system_server facade. This implementation sends HDLC encoded RPC packets via pw_sys_io, and has blocking sends/reads, so it is hardly performance-oriented and unsuitable for performance-sensitive applications. This mostly servers as a simplistic example for quickly bringing up RPC over HDLC on bare-metal targets.

Zephyr#

Pigweed AI summary: The paragraph explains how to enable pw_hdlc.pw_rpc for Zephyr by adding CONFIG_PIGWEED_HDLC_RPC=y to the project's configuration. The section also includes a toctree-wrapper with links to various related documents.

To enable pw_hdlc.pw_rpc for Zephyr add CONFIG_PIGWEED_HDLC_RPC=y to the project’s configuration.