Serial#

Hardware Interface#

Defined in namespace hal

#include <libhal/serial.hpp>

class serial#

Hardware abstract interface for the serial communication protocol.

Use this interface for hardware that implements a serial protocol like UART, RS232, RS485 and others that use a similar communication protocol but may use different voltage schemes.

This interface only works 8-bit serial data frames.

Due to the asynchronous and unformatted nature of serial communication protocols, all implementations of serial devices must be buffered. Buffered, in this case, is defined as automatic storage of received bytes without direct application intervention.

All implementations MUST allow the user to supply their own buffer of arbitrary size up to the limits of what hardware can support. This allows a developer the ability to tailored the buffer size to the needs of the application.

Examples of buffering schemes are:

  • Using DMA to copy data from a serial peripheral to a region of memory

  • Using interrupts when a serial peripheral’s queue has filled to a point

Subclassed by hal::lpc40::uart, hal::soft::inert_serial, hal::stm32f1::uart

Public Functions

inline void configure(settings const &p_settings)#

Configure serial to match the settings supplied.

Implementing drivers must verify if the settings can be applied to hardware before modifying the hardware. This will ensure that if this operation fails, the state of the serial device has not changed.

Parameters:

p_settings – - settings to apply to serial driver

Throws:

hal::operation_not_supported – - if the settings could not be achieved.

inline write_t write(std::span<hal::byte const> p_data)#

Write data to the transmitter line of the serial port.

Parameters:

p_data – - data to be transmitted over the serial port

Returns:

write_t - serial write response

inline read_t read(std::span<hal::byte> p_data)#

Copy bytes from working buffer into passed buffer.

This operation copies the bytes from the serial driver’s internal working buffer to the buffer supplied.

The buffer will be filled up either to the end of the buffer or until there are no more bytes left in the working buffer. The remaining portion of the input buffer is returned in read_t::remaining.

If a frame error has occurred at any point during serial reception, this function will throw a hal::io_error value. The contents of the internal working buffer will stay the same. No information from the internal working buffer will be copied into the supplied buffer and no data will be removed from the internal working buffer. The frame error status will be internally cleared after its occurrence. Subsequent calls of this function will read out the contents of the buffer although the data inside may be corrupt.

When an hal::io_error occurs the options available are to flush the buffer and attempt reception again or read out the potentially corrupted data and parse it as needed. The choice of operation is application/driver specific.

Parameters:

p_data – - Buffer to read bytes in to

Throws:

hal::io_error – - if a frame error occurred at any point during reception of the bytes held currently.

Returns:

read_t - serial read response data

inline void flush()#

Flush working buffer.

The behavior of flushing the internal working buffer is this:

  • Sets the serial port’s internal working buffer to an β€œempty” state.

  • Clear any received data stored in hardware registers.

  • Use the fastest available option to perform these operations, meaning that the contents of the internal working buffer will not be zeroed out.

struct read_t#

Return type for serial read operations.

Public Members

std::span<hal::byte> data#

The filled portion of the input buffer from the serial port.

The size of this buffer indicates the number of bytes read The address points to the start of the buffer passed into the read() function.

size_t available#

Number of enqueued and available to be read out bytes.

This value can be equal to or exceed the value of capacity. In this situation, the number of bytes above the capacity are bytes that have been dropped. Not all drivers will indicate the number of bytes lost. It is up to the driver or application to decide what to do in this situation.

size_t capacity#

The maximum number of bytes that the serial port can queue up.

struct settings#

Generic settings for a standard serial device.

Public Types

enum class stop_bits : uint8_t#

Set of available stop bits options.

Values:

enumerator one#
enumerator two#
enum class parity : uint8_t#

Set of parity bit options.

Values:

enumerator none#

Disable parity bit as part of the frame.

enumerator odd#

Enable parity and set 1 (HIGH) when the number of bits is odd.

enumerator even#

Enable parity and set 1 (HIGH) when the number of bits is even.

enumerator forced1#

Enable parity bit and always return 1 (HIGH) for ever frame.

enumerator forced0#

Enable parity bit and always return 0 (LOW) for ever frame.

Public Members

hertz baud_rate = 115200.0f#

The operating speed of the baud rate (in units of bits per second)

stop_bits stop = stop_bits::one#

Number of stop bits for each frame.

parity parity = parity::none

Parity bit type for each frame.

struct write_t#

Return type for serial write operations.

Public Members

std::span<hal::byte const> data#

The portion of the buffer transmitted.

Utilities#

Defined in namespace hal

#include <libhal-util/serial.hpp>

group Serial

Functions

constexpr auto operator==(serial::settings const &p_lhs, serial::settings const &p_rhs)#

Compares two serial objects via their settings.

Parameters:
  • p_lhs – A serial object

  • p_rhs – A serial object

Returns:

A boolean if they are the same or not.

inline serial::write_t write_partial(serial &p_serial, std::span<hal::byte const> p_data_out)#

Write bytes to a serial port.

Parameters:
  • p_serial – - the serial port that will be written to

  • p_data_out – - the data to be written out the port

Returns:

serial::write_t - information about the write_t operation.

inline void write(serial &p_serial, std::span<hal::byte const> p_data_out, timeout auto p_timeout)#

Write bytes to a serial port.

Unlike write_partial, this function will attempt to write bytes to the serial port until the timeout time has expired.

Parameters:
  • p_serial – - the serial port that will be written to

  • p_data_out – - the data to be written out the port

  • p_timeout – - timeout callable that throws a std::errc::timed_out exception when the timeout expires.

Throws:

std::errc::timed_out – - if p_timeout expires

inline void write(serial &p_serial, std::string_view p_data_out, timeout auto p_timeout)#

Write std::span of const char to a serial port.

Parameters:
  • p_serial – - the serial port that will be written to

  • p_data_out – - chars to be written out the port

  • p_timeout – - timeout callable that throws a std::errc::timed_out exception when the timeout expires.

Throws:

std::errc::timed_out – - if p_timeout expires

inline void read(serial &p_serial, std::span<hal::byte> p_data_in, timeout auto p_timeout)#

Read bytes from a serial port.

Parameters:
  • p_serial – - the serial port that will be read from

  • p_data_in – - buffer to have bytes from the serial port read into. When this function completes, the full contents of p_data_in should contain

  • p_timeout – - timeout callable that throws a std::errc::timed_out exception when the timeout expires.

Throws:

std::errc::timed_out – - if p_timeout expires

template<size_t bytes_to_read>
std::array<hal::byte, bytes_to_read> read(serial &p_serial, timeout auto p_timeout)#

Read bytes from a serial port and return an array.

This call eliminates the boiler plate of creating an array and then passing that to the read function.

Template Parameters:

bytes_to_read – - the number of bytes to be read from the serial port.

Parameters:
  • p_serial – - the serial port to be read from

  • p_timeout – - timeout callable that throws a std::errc::timed_out exception when the timeout expires.

Throws:

std::errc::timed_out – - if p_timeout expires

Returns:

std::array<hal::byte, bytes_to_read> - array containing the bytes read from the serial port.

inline void write_then_read(serial &p_serial, std::span<hal::byte const> p_data_out, std::span<hal::byte> p_data_in, timeout auto p_timeout)#

Perform a write then read transaction over serial.

This is especially useful for devices that use a command and response method of communication.

Parameters:
  • p_serial – - the serial port to have the transaction occur on

  • p_data_out – - the data to be written to the port

  • p_data_in – - a buffer to receive the bytes back from the port

  • p_timeout – - timeout callable that throws a std::errc::timed_out exception when the timeout expires.

Throws:

std::errc::timed_out – - if p_timeout expires

template<size_t bytes_to_read>
std::array<hal::byte, bytes_to_read> write_then_read(serial &p_serial, std::span<hal::byte const> p_data_out, timeout auto p_timeout)#

Perform a write then read transaction over serial.

This is especially useful for devices that use a command and response method of communication.

Template Parameters:

bytes_to_read – - the number of bytes to read back

Parameters:
  • p_serial – - the serial port to have the transaction occur on

  • p_data_out – - the data to be written to the port

  • p_timeout – - timeout callable that indicates when to bail out of the read operation.

Throws:

std::errc::timed_out – - if p_timeout expires

Returns:

std::array<hal::byte, bytes_to_read> - array containing the bytes read from the serial port.

template<typename byte_array_t>
void print(serial &p_serial, byte_array_t &&p_data)#

Write data to serial buffer and drop return value.

Only use this with serial ports with infallible write operations, meaning they will never return an error result.

Template Parameters:

byte_array_t – - data array type

Parameters:
  • p_serial – - serial port to write data to

  • p_data – - data to be sent over the serial port

template<size_t buffer_size, typename ...Parameters>
void print(serial &p_serial, char const *p_format, Parameters... p_parameters)#

Write formatted string data to serial buffer and drop return value.

Uses snprintf internally and writes to a local statically allocated an array. This function will never dynamically allocate like how standard std::printf does.

This function does NOT include the NULL character when transmitting the data over the serial port.

Template Parameters:
  • buffer_size – - Size of the buffer to allocate on the stack to store the formatted message.

  • Parameters – - printf arguments

Parameters:
  • p_serial – - serial port to write data to

  • p_format – - printf style null terminated format string

  • p_parameters – - printf arguments

Coroutines#

#include <libhal-util/serial_coroutines.hpp>

group SerialCoroutines

A collection of functions and other utilities used for asynchronous coroutines with serial communication.

Functions

inline skip_past(serial &p_serial, std::span<hal::byte const> p_sequence, size_t p_read_limit = 32)#

Construct a new skip beyond object.

Parameters:
  • p_serial – - serial port to skip through

  • p_sequence – - sequence to search for. The lifetime of this data pointed to by this span must outlive this object, or not be used when the lifetime of that data is no longer available.

  • p_read_limit – - the maximum number read attempts from the port before returning. A value 0 will result in no reads from the serial port.

inline work_state operator()()#

skip data from the serial port until the sequence is reached.

This function will return if the sequence is found or if there are no more bytes in the serial port.

Call this function again to resume reading from the port.

Returns:

work_state::in_progress - if the sequence hasn’t been met and the buffer still has space.

Returns:

work_state::finished - if the sequence was found before the buffer was filled completely.

inline read_into(serial &p_serial, std::span<hal::byte> p_buffer, size_t p_read_limit = 32)#

Construct a new read_into object.

Parameters:
  • p_serial – - serial port to skip through

  • p_buffer – - buffer to read data into

  • p_read_limit – - the maximum number read attempts from the port before returning. A value 0 will result in no reads from the serial port.

inline work_state operator()()

read data into the buffer.

This function will return if the read limit is reached or if there are no more bytes in the serial port.

Call this function again to resume reading from the port.

Returns:

work_state - work_state::in_progress if the sequence hasn’t been met and the buffer still has space.

Returns:

work_state - work_state::finished if the sequence was found before the buffer was filled completely.

inline read_upto(serial &p_serial, std::span<hal::byte const> p_sequence, std::span<hal::byte> p_buffer, size_t p_read_limit = 32)#

Construct a new skip beyond object.

Parameters:
  • p_serial – - serial port to skip through

  • p_sequence – - sequence to search for. The lifetime of this data pointed to by this span must outlive this object, or not be used when the lifetime of that data is no longer available.

  • p_buffer – - buffer to fill data into

  • p_read_limit – - the maximum number of bytes to read off from the serial port before returning. A value 0 will result in no reads from the serial port.

inline work_state operator()()

read data into the buffer.

This function will return if the read limit is reached or if there are no more bytes in the serial port.

Call this function again to resume reading from the port.

Returns:

work_state - work_state::in_progress if the sequence hasn’t been met and the buffer still has space.

Returns:

work_state - work_state::failed if the sequence wasn’t found before the buffer was filled completely.

Returns:

work_state - work_state::finished if the sequence was found before the buffer was filled completely.

inline read_uint32(serial &p_serial, size_t p_read_limit = 32)#

Construct a new read_uint32 object.

Parameters:
  • p_serial – - serial port to skip through

  • p_read_limit – - the maximum number read attempts from the port before returning. A value 0 will result in no reads from the serial port.

inline work_state operator()()

parse serial data and convert to an integer

This function will return if an integer ws found or no more bytes in the serial port.

Call this function again to resume reading from the port.

Returns:

work_state - work_state::in_progress - if an integer hasn’t been found

Returns:

work_state - work_state::finished - integer has been found and a non-integer byte has also been found.

class skip_past#
#include <serial_coroutines.hpp>

Discard received bytes until the sequence is found.

Public Functions

inline skip_past(serial &p_serial, std::span<hal::byte const> p_sequence, size_t p_read_limit = 32)#

Construct a new skip beyond object.

Parameters:
  • p_serial – - serial port to skip through

  • p_sequence – - sequence to search for. The lifetime of this data pointed to by this span must outlive this object, or not be used when the lifetime of that data is no longer available.

  • p_read_limit – - the maximum number read attempts from the port before returning. A value 0 will result in no reads from the serial port.

inline work_state operator()()#

skip data from the serial port until the sequence is reached.

This function will return if the sequence is found or if there are no more bytes in the serial port.

Call this function again to resume reading from the port.

Returns:

work_state::in_progress - if the sequence hasn’t been met and the buffer still has space.

Returns:

work_state::finished - if the sequence was found before the buffer was filled completely.

class read_into#
#include <serial_coroutines.hpp>

Non-blocking callable for reading serial data into a buffer.

Public Functions

inline read_into(serial &p_serial, std::span<hal::byte> p_buffer, size_t p_read_limit = 32)#

Construct a new read_into object.

Parameters:
  • p_serial – - serial port to skip through

  • p_buffer – - buffer to read data into

  • p_read_limit – - the maximum number read attempts from the port before returning. A value 0 will result in no reads from the serial port.

inline work_state operator()()#

read data into the buffer.

This function will return if the read limit is reached or if there are no more bytes in the serial port.

Call this function again to resume reading from the port.

Returns:

work_state - work_state::in_progress if the sequence hasn’t been met and the buffer still has space.

Returns:

work_state - work_state::finished if the sequence was found before the buffer was filled completely.

class read_upto#
#include <serial_coroutines.hpp>

Discard received bytes until the sequence is found.

Public Functions

inline read_upto(serial &p_serial, std::span<hal::byte const> p_sequence, std::span<hal::byte> p_buffer, size_t p_read_limit = 32)#

Construct a new skip beyond object.

Parameters:
  • p_serial – - serial port to skip through

  • p_sequence – - sequence to search for. The lifetime of this data pointed to by this span must outlive this object, or not be used when the lifetime of that data is no longer available.

  • p_buffer – - buffer to fill data into

  • p_read_limit – - the maximum number of bytes to read off from the serial port before returning. A value 0 will result in no reads from the serial port.

inline work_state operator()()#

read data into the buffer.

This function will return if the read limit is reached or if there are no more bytes in the serial port.

Call this function again to resume reading from the port.

Returns:

work_state - work_state::in_progress if the sequence hasn’t been met and the buffer still has space.

Returns:

work_state - work_state::failed if the sequence wasn’t found before the buffer was filled completely.

Returns:

work_state - work_state::finished if the sequence was found before the buffer was filled completely.

class read_uint32#
#include <serial_coroutines.hpp>

Read bytes from serial port and convert to integer.

Public Functions

inline read_uint32(serial &p_serial, size_t p_read_limit = 32)#

Construct a new read_uint32 object.

Parameters:
  • p_serial – - serial port to skip through

  • p_read_limit – - the maximum number read attempts from the port before returning. A value 0 will result in no reads from the serial port.

inline work_state operator()()#

parse serial data and convert to an integer

This function will return if an integer ws found or no more bytes in the serial port.

Call this function again to resume reading from the port.

Returns:

work_state - work_state::in_progress - if an integer hasn’t been found

Returns:

work_state - work_state::finished - integer has been found and a non-integer byte has also been found.

inline std::optional<uint32_t> get()#
Returns:

std::optional<uint32_t> - integer if the parsing is finished or std::nullopt