Giter VIP home page Giter VIP logo

hdlco's Introduction

HDLC High-Level Data Link Control

License: MIT

Build Status

This small library provides the means to create and serilize HDLC frames in the non-extended mode.

Frame Structure

Flag Address Control Information FCS Flag
8 bits 8 or more bits 8 Variable length, 8ร—n bits 16 8 bits

Note that the end flag of one frame may be (but does not have to be) the beginning (start) flag of the next frame.

Data is usually sent in multiples of 8 bits, but only some variants require this; others theoretically permit data alignments on other than 8-bit boundaries.

The frame check sequence (FCS) is a 16-bit CRC-CCITT or a 32-bit CRC-32 computed over the Address, Control, and Information fields. It provides a means by which the receiver can detect errors that may have been induced during the transmission of the frame, such as lost bits, flipped bits, and extraneous bits. However, given that the algorithms used to calculate the FCS are such that the probability of certain types of transmission errors going undetected increases with the length of the data being checked for errors, the FCS can implicitly limit the practical size of the frame.

If the receiver's calculation of the FCS does not match that of the sender's, indicating that the frame contains errors, the receiver can either send a negative acknowledge packet to the sender, or send nothing. After either receiving a negative acknowledge packet or timing out waiting for a positive acknowledge packet, the sender can retransmit the failed frame.

Asynchronous framing

When using asynchronous serial communication such as standard RS-232 serial ports, synchronous-style bit stuffing is inappropriate for several reasons:

  • Bit stuffing is not needed to ensure an adequate number of transitions, as start and stop bits provide that,
  • Because the data is NRZ encoded for transmission, rather than NRZI encoded, the encoded waveform is different,
  • RS-232 sends bits in groups of 8, making adding single bits very awkward, and
  • For the same reason, it is only necessary to specially code flag bytes; thus it is not necessary to worry about the bit pattern straddling multiple bytes.

Instead asynchronous framing uses "control-octet transparency", also called "byte stuffing" or "octet stuffing". The frame boundary octet is 01111110, (0x7E in hexadecimal notation). A "control escape octet", has the value 0x7D (bit sequence '10111110', as RS-232 transmits least-significant bit first). If either of these two octets appears in the transmitted data, an escape octet is sent, followed by the original data octet with bit 5 inverted. For example, the byte 0x7E would be transmitted as 0x7D 0x5E ("10111110 01111010"). Other reserved octet values (such as XON or XOFF) can be escaped in the same way if necessary.

The "abort sequence" 0x7D 0x7E ends a packet with an incomplete byte-stuff sequence, forcing the receiver to detect an error. This can be used to abort packet transmission with no chance the partial packet will be interpreted as valid by the receiver.

Frame types:

  • Information frames, or I-frames, transport user data from the network layer. In addition they can also include flow and error control information piggybacked on data.
  • Supervisory Frames, or S-frames, are used for flow and error control whenever piggybacking is impossible or inappropriate, such as when a station does not have data to send. S-frames do not have information fields.
  • Unnumbered frames, or U-frames, are used for various miscellaneous purposes, including link management. Some U-frames contain an information field, depending on the typ

Control Field

HDLC control fields
7 6 5 4 3 2 1 0
N(R)
Receive sequence no.
P/F N(S)
Send sequence no.
0 I-frame
N(R)
Receive sequence no.
P/F type 0 1 S-frame
type P/F type 1 1 U-frame

Examples

Create frame.

const auto payload = std::string("PAYLOAD");
const Frame frame(payload, Frame::Type::I);

Serialize frame.

#include "hdlc/hdlc.h"
const Frame frame; //Some frame
const auto raw = FrameSerializer::serialize(frame); //Pack the frame into HDLC format
const auto raw_escaped = FrameSerializer::escape(raw); //Perform HDLC byte stuffing
magical_user_transmit(raw_escaped); //User implementation for transfering bytes. 

De-Serialize frame.

#include "hdlc/hdlc.h"
const auto raw_escaped = magical_user_recieve();
const auto raw = FrameSerializer::descape(raw_escaped);
const Frame frame = FrameSerializer::deserialize(raw);
if(frame.is_empty())
{
   //Frame empty, something has gone very wrong. 
}
else
{
   //handle the frame
}

Running a client in normal response mode:

static io_type io(); //Example io using serial. 
static session::snrm::Client<serial_io> session(io); //Example session using provided library. 

session.install_handler(Frame::Type::I, /* custom handler goes here */); //User handlers 

for (;;)
{
   auto status = session.run();
   //Handle status, or simply run continiously. 
}

Running a master in normal response mode:

static io_type io(); 
static session::snrm::Master<io_type> session(io);

for(;;)
{
   if (!session.connected())
   {
      auto status = session.connect();
      /* Handle connection success / failure. */
   }
   else
   {
      /* Do stuff when connected? Or run that in a different thread. For example: */
      const std::string    payload = "I'M A PAYLOAD";
      std::vector<uint8_t> response;
      auto                 ret = session.send_payload(payload, response);
   }
}

The session object abstracts the HDLC layer so that the user does not have to worry about such details and can simply send/recieve payloads. Note that you can use the library to just create frames and implement your own session management.

Design Notes

  • Currently the library only provides the means to create and serilize HDLC frames, there is no transfer implementaion or session management. This is difficult to implement since I would like for this library to be usable on both desktop and embedded platforms hence for the time being it is up to the user to implement transfer of serialized frames.
  • The underlaying storage type is vector which requires heap allocation, on embedded platforms I have tested this with FreeRTOS allocator with little issues but it may be easier to operate on buffers that have been pre-allocated.
  • The pipes used for recieve and transmit use boost circular buffer. While perfect for this application this means dependency on boost. It may be better to copy out the circular buffer header rather than pulling in the entire library.
  • The sessions are blocking the thread they are ran on. This is so that the user can implement their own threading based on the OS (bare metal, linux).
  • The sessions are very minial implemenations which worked for my application feel free to fork to adapt to your needs.
  • This project uses conan for packages, there are couple of issues with this. To make my travis build work correctly I rebuild all conan dependencies from source. Which means if you are using this project in your code it may download and build boost from source. This is not ideal, I am currently considering solutions to this problem.

Prerequisites

Build

mkdir build && cd build
cmake .. && make

Running tests

./bin/hdlc_test

TODOs

  • Implement example packet hardware transfer.
  • Implement example packet reciever and handler.

References

Other HDLC related repositories

hdlco's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.