| .. _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 |