blob: 729798d3f2f48a45d6792bc5bf83b87303775ce7 [file] [log] [blame]
.. _module-pw_hdlc-design:
================
Design & roadmap
================
.. pigweed-module-subpage::
:name: pw_hdlc
.. pw_hdlc-overview-start
``pw_hdlc`` implements a subset of the `High-Level Data Link Control
<https://en.wikipedia.org/wiki/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
<https://www.iso.org/standard/37010.html>`_.
.. pw_hdlc-overview-end
--------
Overview
--------
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 :ref:`module-pw_rpc` to enable
remote procedure calls (RPCs) on embedded 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
=====================
* ``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.
--------------------
Protocol Description
--------------------
Frames
======
The HDLC implementation in ``pw_hdlc`` supports only HDLC unnumbered
information frames. These frames are encoded as follows:
.. code-block:: text
_________________________________________
| | | | | | |...
| | | | | | |... [More frames]
|_|_|_|__________________________|____|_|...
F A C Payload FCS F
F = flag byte (0x7e, the ~ character)
A = address field
C = control field
FCS = frame check sequence (CRC-32)
Encoding and sending data
=========================
This module first writes an initial frame delimiter byte (``0x7E``) to indicate
the beginning of the frame. Before sending any of the payload data through
serial, the special bytes are escaped:
+-------------------------+-----------------------+
| Unescaped Special Bytes | Escaped Special Bytes |
+=========================+=======================+
| ``7E`` | ``7D 5E`` |
+-------------------------+-----------------------+
| ``7D`` | ``7D 5D`` |
+-------------------------+-----------------------+
The bytes of the payload are escaped and written in a single pass. The
frame check sequence is calculated, escaped, and written after. After this, a
final frame delimiter byte (``0x7E``) is written to mark the end of the frame.
Decoding received bytes
=======================
Frames may be received in multiple parts, so ``pw_hdlc`` needs to store the
received data in a buffer until the ending frame delimiter (``0x7E``) is read.
When the ``pw_hdlc`` decoder receives data, it unescapes it and adds it to a
buffer. When the frame is complete, it calculates and verifies the frame check
sequence and does the following:
* If correctly verified, the decoder returns the decoded frame.
* If the checksum verification fails, the frame is discarded and an error is
reported.
-------
Roadmap
-------
- **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.
-----------------
More pw_hdlc docs
-----------------
.. include:: docs.rst
:start-after: .. pw_hdlc-nav-start
:end-before: .. pw_hdlc-nav-end