aboutsummaryrefslogtreecommitdiff
path: root/pw_hdlc/design.rst
blob: d20d774938ad22b9d26caa22cfc90cb68e925504 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
.. _module-pw_hdlc-design:

===============
pw_hdlc: Design
===============
.. pigweed-module-subpage::
   :name: pw_hdlc
   :tagline: Lightweight, simple, and easy serial communication

``pw_hdlc`` implements a subset of the
`HDLC <https://en.wikipedia.org/wiki/High-Level_Data_Link_Control>`_
protocol.

--------------------
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 we need 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.