HDLC Reference Library

This documentation package includes a full HDLC implementation in C in src/hdlc/, that we recommend using. src/linux_c_serial_demo contains a complete demo application ready to communicate with any MyDefence serial device.

_images/lib.png

To integrate the HDLC library into your own application, you need to implement an OS Abstraction Interface for your platform.

Application Interface

The application interface to send and receive HDLC frames is defined in the header file src/hdlc/include/hdlc.h.

Defines

HDLC_MAX_FRAME_LEN

Maximum length of HDLC data frame.

Enums

enum hdlc_result_t

Values:

enumerator HDLC_SUCCESS
enumerator HDLC_OS_ERROR

Call to hdlc_os_*() function in OS Abstraction Layer failed.

On some OS more information may be available, e.g. in errno.

enumerator HDLC_NOT_CONNECTED

HDLC layer is not connected, i.e. wait for hdlc_connected_cb().

enumerator HDLC_FRAME_TOO_LONG

Frame is too long.

enum hdlc_reset_cause_t

Values:

enumerator HDLC_RESET_CAUSE_APPLICATION_FREE

Reset by application.

Reset by application due to loss of link.

enumerator HDLC_RESET_CAUSE_TIMEOUT_KEEP_ALIVE

Reset due to timeout during KEEP_ALIVE.

enumerator HDLC_RESET_CAUSE_TIMEOUT_RETRANSMIT

Reset due to timeout during retransmission.

enumerator HDLC_RESET_CAUSE_PEER_INITIATED

Reset due to peer initiated reset.

enumerator HDLC_RESET_CAUSE_NUMBER_OF_CAUSES

Not a real reset cause, but the number of reset causes Add new reset causes before this.

Functions

hdlc_result_t hdlc_send_frame(hdlc_data_t *h, const uint8_t *frame, uint32_t len)

Reliable transmission of one data frame.

This function is used to send one data frame. The frame is queued for transmission and the function returns immediately. When the frame has been successfully sent, the callback function hdlc_frame_sent_cb() is called with the same parameters. If frame transmission times out, hdlc_reset_cb() is called followed by hdlc_frame_sent_cb().

Parameters:
  • h – HDLC instance data allocated by hdlc_init()

  • frame – Pointer to data to send. The pointer must be valid until hdlc_frame_sent_cb() is called

  • len – Length of data.

Returns:

0 in case of success. Success means the data was correctly queued for transmission, not that it has been sent. See hdlc_result_t for error codes. In case of error, hdlc_frame_sent_cb() is not called.

void hdlc_frame_sent_cb(hdlc_data_t *h, const uint8_t *frame, uint32_t len)

Callback function called when a frame has been sent, or otherwise discarded.

Parameters:
hdlc_result_t hdlc_send_frame_unacknowledged(hdlc_data_t *h, const uint8_t *frame, uint32_t len)

Unreliable transmission of one data frame.

This function is used to send one HDLC UI frame. The frame is attempted transmitted immediately. There is no way of knowing whether the frame has been delivered. frame may be freed immediately after return. hdlc_frame_sent_cb() is not called.

This frame may be dropped, delivered before, or delivered after unacknowledged frames already queued with hdlc_send_frame(). Data queued with hdlc_send_frame() or hdlc_send_frame_unacknowledged() after this frame, will always be delivered after this frame was delivered (if it is delivered).

Parameters:
  • h – HDLC instance data allocated by hdlc_init()

  • frame – Pointer to data to send

  • len – Length of data.

Returns:

0 in case of success. Success means the data was correctly queued for transmission, not that it has been sent. See hdlc_result_t for error codes.

void hdlc_recv_frame_cb(hdlc_data_t *h, uint8_t *frame, uint32_t len)

Callback function called when a frame (data or UI) has been received.

This function is called when a frame has been received. Frames are always delivered in the same order they are sent, with the exception that UI frames may overtake data frames.

Parameters:
  • h – HDLC instance data allocated by hdlc_init()

  • frame – Pointer to a received HDLC frame. The pointer is invalid after this function returns.

  • len – Length of the frame

void hdlc_reset_cb(hdlc_data_t *h, hdlc_reset_cause_t cause)

This is called when HDLC sequence number are reset, which happens either.

  1. In case of retransmission timeout (see HDLC_RETRANSMIT_CNT in hdlc_os.h)

  2. If integration indicates loss of link or frees the HDLC instance

  3. If HDLC SABM frame is received from peer

This is followed by cleanup of the current TX queue including calling hdlc_frame_sent_cb(). hdlc_send_frame() and hdcl_send_frame_unacknowledged() will fail until hdlc_connected_cb() is called.

Parameters:
  • h – HDLC instance data allocated by hdlc_init()

  • cause – Reason for reset

void hdlc_connected_cb(hdlc_data_t *h)

This is called when HDLC is connected, i.e.

when the HDLC SABM frame is acknowledged by peer. All frames sent between system startup OR hdlc_reset_cb() and this are discarded.

Parameters:

h – HDLC instance data allocated by hdlc_init()

Variables

struct hdlc_stat_t hdlc_stat

Various statistics about the HDLC layer, that may be useful for diagnosing link performance.

struct hdlc_stat_t
#include <hdlc.h>

Public Members

uint32_t rx

Data frames received (not including retransmissions)

uint32_t ui_rx

UI frames received (not including retransmissions)

uint32_t rx_retrans

Out-of-sequence rx frames.

uint32_t rx_err

Failure to decode HDLC frame.

uint32_t rx_ack

Ack frames received.

uint32_t rx_nack

Nack frames received.

uint32_t tx

Data frames transmitted (not including retransmissions)

uint32_t ui_tx

UI frames transmitted (not including retransmissions)

uint32_t tx_err

Failure of hdlc_os_tx()

uint32_t tx_retrans

Data frames retransmitted (including retransmission frames)

uint32_t tx_ack

Ack frames transmitted.

uint32_t tx_nack

Nack frames transmitted.

uint32_t tx_keep_alive

Number of keep alive frames transmitted (not including retransmissions)

uint32_t reset

Number of times sequence number handling has been reset.

OS Abstraction Interface

The HDLC implementation is attempted to be generic, and requires integration into the OS as specified in src/hdlc/include/hdlc_os.h.

Some reference integrations are available in src/hdlc/ports/.

Defines

HDLC_RETRANSMIT_CNT

Number of retransmissions to attempt before resetting the link.

Thus the timeout is this value times the hdlc_os_start_timer() time.

HDLC_KEEP_ALIVE_CNT

Number of timeouts with no data transmission before sending keep-alive packet.

Thus detection of broken link takes (HDLC_KEEP_ALIVE_CNT + HDLC_RETRANSMIT_CNT) * hdlc_os_start_timer() time

log_trace(...)

Define log_ macros to enable logging.

The integration may omit this. Default no logging is enabled.

log_debug(...)
log_info(...)
log_warn(...)
log_error(...)
log_fatal(...)

Functions

hdlc_data_t *hdlc_init(void *user_data)

Called by integration to initialize an hdlc instance.

May be called multiple times if more than one HDLC device is connected.

Parameters:

user_data – pointer to user data. The pointer will be copied to hdlc_data_t.

void hdlc_free(hdlc_data_t *hdlc)

Called by integration to free resources allocated by hdlc_init().

The integration is responsible for cleanup of anything in hdlc->user_data. After call to this, no other hdlc_*()/hdlc_os_*() functions may be called and hdlc must not be accessed. Note: This function uses various hdlc_os_*() callbacks, so do not free any instance resources until AFTER this call.

int hdlc_os_tx(hdlc_data_t *hdlc, const uint8_t *buf, uint32_t count)

Called by hdlc to transmit raw serial data.

This function should be implemented by the integration. buf pointer is valid until function returns. The function is expected to send the entire buf or nothing, hdlc does not explicitly handle partial writes, but the underlying error handling will recover from it.

Beware, that if this blocks, that will also cause blocking of receive handling.

Parameters:
  • buf – data

  • count – length of data

Returns:

< 0 in case of error, otherwise number of bytes sent (== count).

void hdlc_os_rx(hdlc_data_t *hdlc, const uint8_t *buf, uint32_t count)

Called by integration when new raw serial data is received.

This function called from the integration. data pointed to by buf may be freed or overwritten after the function call returns.

Parameters:
  • buf – data

  • count – length of data

void hdlc_os_start_timer(hdlc_data_t *hdlc)

Called by hdlc to (re)start retransmission timer.

Integration must provide a single-shot timer for retransmission handling. This function is called after transmission of the first outstanding packet. Integration must select an appropriate timeout value for the time it is expected to receive an ACK, i.e. the round trip time of the largest frame plus ack.

This function will also be called to restart timer when an ACK is received, and there are still outstanding frames.

void hdlc_os_stop_timer(hdlc_data_t *hdlc)

Called by hdlc to stop retransmission timer started by hdlc_os_start_timer().

void hdlc_os_timeout(hdlc_data_t *hdlc)

Called by integration when retransmission timer expires.

Note, that the function will call hdlc_os_exit_critical_section(), hdlc_os_exit_critical_section(), hdlc_os_start_timer() and hdlc_os_tx().

Called by integration to indicate link loss.

This will reset HDLC. hdlc_reset_cb() and later hdlc_connected_cb() will be called. The integration may omit this.

void hdlc_os_enter_critical_section(hdlc_data_t *hdlc)

Called by hdlc lock a mutex.

If integration does not use multi-threading it may provide empty functions.

void hdlc_os_exit_critical_section(hdlc_data_t *hdlc)

Called by hdlc unlock a mutex.

If integration does not use multi-threading it may provide empty functions

struct hdlc_data_t
#include <hdlc_os.h>

HDLC instance data, allocated by hdlc_init().

The actual struct allocated by HDLC is larger than this and contains internal data.

Public Members

void *user_data

The user data field is a pointer the application may use to refer to any data it needs.

The integration may set it to anything it wishes including NULL. It will not be touched by hdlc.

unsigned int hdlc_tx_queue_size

Number of frames in the TX queue.

Can be used to throttle the sender. Alternatively a sender may use hdlc_frame_sent_cb() for throttling.