UART (Universal Asynchronous Receiver-Transmitter)

group group_hal_uart

High level interface for interacting with the Universal Asynchronous Receiver-Transmitter (UART).

The Universal Asynchronous Receiver/Transmitter (UART) protocol is an asynchronous serial interface protocol. UART communication is typically point-to-point. The UART interface consists of two signals:

  • TX: Transmitter output

  • RX: Receiver input

Additionally, two side-band signals are used to implement flow control in UART. Note that the flow control applies only to TX functionality.

  • Clear to Send (CTS): This is an input signal to the transmitter. When active, it indicates that the slave is ready for the master to transmit data.

  • Ready to Send (RTS): This is an output signal from the receiver. When active, it indicates that the receiver is ready to receive data

Flow control can be configured via cyhal_uart_set_flow_control()

The data frame size, STOP bits and parity can be configured via cyhal_uart_cfg_t. The UART contains dedicated hardware buffers for transmit and receive. Optionally, either of these can be augmented with a software buffer.

note

For applications that require printing messages on a UART terminal using printf(), the retarget-io utility library can be used directly.

Features

Interrupts and callbacks

Interrupts are handled by callbacks based on events cyhal_uart_event_t If an event is disabled, the underlying interrupt is still enabled. Enabling or disabling an event only enables or disables the callback.

note

Care must be exercised whenusing the CYHAL_UART_IRQ_RX_NOT_EMPTY event. The callback must read all available received data or the interrupt will not be cleared leading to the callback being immediately retriggered.

Quick Start

cyhal_uart_init is used for UART initialization

Code Snippets

Snippet 1: Initialization and Configuration

The following snippet initializes the UART block and assigns the tx, rx pins and sets the baudrate.

The snippet also shows how to use cyhal_uart_write, cyhal_uart_putc, cyhal_uart_read API.

    #define DATA_BITS_8     8
    #define STOP_BITS_1     1
    #define BAUD_RATE       115200
    #define UART_DELAY      10u
    #define RX_BUF_SIZE     4
    #define TX_BUF_SIZE     4

    // Variable Declarations
    cy_rslt_t    rslt;
    cyhal_uart_t uart_obj;
    uint32_t     actualbaud;
    uint8_t      tx_buf[TX_BUF_SIZE] = { '1', '2', '3', '4' };
    uint8_t      rx_buf[RX_BUF_SIZE];
    size_t       tx_length = TX_BUF_SIZE;
    size_t       rx_length = RX_BUF_SIZE;
    uint32_t     value     = 'A';

    // Initialize the UART configuration structure
    const cyhal_uart_cfg_t uart_config =
    {
        .data_bits      = DATA_BITS_8,
        .stop_bits      = STOP_BITS_1,
        .parity         = CYHAL_UART_PARITY_NONE,
        .rx_buffer      = rx_buf,
        .rx_buffer_size = RX_BUF_SIZE
    };

    // Initialize the UART Block
    rslt = cyhal_uart_init(&uart_obj, CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, NULL, &uart_config);

    // Set the baud rate
    rslt = cyhal_uart_set_baud(&uart_obj, BAUD_RATE, &actualbaud);

    // Begin Tx Transfer
    cyhal_uart_write(&uart_obj, (void*)tx_buf, &tx_length);
    cyhal_system_delay_ms(UART_DELAY);

    // Send a Character
    cyhal_uart_putc(&uart_obj, value);
    cyhal_system_delay_ms(UART_DELAY);

    // Begin Rx Transfer
    cyhal_uart_read(&uart_obj, (void*)rx_buf, &rx_length);
    cyhal_system_delay_ms(UART_DELAY);

Snippet 2: Interrupts on UART events

In the following snippet, UART events are handled in a callback function. The callback function has to be registered and then the events have to be enabled.

// Event handler callback function
void uart_event_handler(void* handler_arg, cyhal_uart_event_t event)
{
    (void)handler_arg;

    if ((event & CYHAL_UART_IRQ_TX_ERROR) == CYHAL_UART_IRQ_TX_ERROR)
    {
        // An error occurred in Tx
        // Insert application code to handle Tx error
    }
    else if ((event & CYHAL_UART_IRQ_TX_DONE) == CYHAL_UART_IRQ_TX_DONE)
    {
        // All Tx data has been transmitted
        // Insert application code to handle Tx done
    }
    else if ((event & CYHAL_UART_IRQ_RX_DONE) == CYHAL_UART_IRQ_RX_DONE)
    {
        // All Rx data has been received
        // Insert application code to handle Rx done
    }
}


void snippet_cyhal_uart_event()
{
    // Macro Definitions
    #define BAUD_RATE       115200
    #define UART_DELAY      10u
    #define TX_BUF_SIZE     4
    #define INT_PRIORITY    3
    #define DATA_BITS_8     8
    #define STOP_BITS_1     1

    // Variable Declarations
    cy_rslt_t    rslt;
    cyhal_uart_t uart_obj;
    uint8_t      tx_buf[TX_BUF_SIZE] = { '1', '2', '3', '4' };
    size_t       tx_length           = TX_BUF_SIZE;

    // Initialize the UART configuration structure
    const cyhal_uart_cfg_t uart_config =
    {
        .data_bits      = DATA_BITS_8,
        .stop_bits      = STOP_BITS_1,
        .parity         = CYHAL_UART_PARITY_NONE,
        .rx_buffer      = NULL,
        .rx_buffer_size = 0
    };

    // Initialize the UART Block
    rslt = cyhal_uart_init(&uart_obj, CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, NULL, &uart_config);
    CY_ASSERT(CY_RSLT_SUCCESS == rslt);

    // The UART callback handler registration
    cyhal_uart_register_callback(&uart_obj, uart_event_handler, NULL);

    // Enable required UART events
    cyhal_uart_enable_event(&uart_obj,
                            (cyhal_uart_event_t)(CYHAL_UART_IRQ_TX_DONE | CYHAL_UART_IRQ_TX_ERROR |
                                                 CYHAL_UART_IRQ_RX_DONE),
                            INT_PRIORITY, true);

    // Begin asynchronous TX transfer
    cyhal_uart_write_async(&uart_obj, (void*)tx_buf, tx_length);
    cyhal_system_delay_ms(UART_DELAY);
}

Defines

CYHAL_UART_DEFAULT_BAUD

The baud rate to set to if no clock is specified in the init function.

CYHAL_UART_MAX_BAUD_PERCENT_DIFFERENCE

The maximum allowable difference between baud requested and actual baud.

Typedefs

typedef void (*cyhal_uart_event_callback_t)(void *callback_arg, cyhal_uart_event_t event)

UART callback function type.

Enums

enum cyhal_uart_parity_t

cyhal_uart_parity_t: UART Parity.

Values:

enumerator CYHAL_UART_PARITY_NONE

UART has no parity check.

enumerator CYHAL_UART_PARITY_EVEN

UART has even parity check.

enumerator CYHAL_UART_PARITY_ODD

UART has odd parity check.

enum cyhal_uart_event_t

cyhal_uart_event_t: Enum to enable/disable/report interrupt cause flags.

Values:

enumerator CYHAL_UART_IRQ_NONE

No interrupt.

enumerator CYHAL_UART_IRQ_TX_TRANSMIT_IN_FIFO

All TX data from transmit has been moved to the HW TX FIFO buffer.

enumerator CYHAL_UART_IRQ_TX_DONE

All TX data has been transmitted (applicable only for cyhal_uart_write_async)

enumerator CYHAL_UART_IRQ_TX_ERROR

An error occurred during TX.

enumerator CYHAL_UART_IRQ_RX_FULL

The SW RX buffer (if used) is full. Additional data will be stored in the HW RX FIFO buffer.

enumerator CYHAL_UART_IRQ_RX_DONE

All RX data has been received (applicable only for cyhal_uart_read_async)

enumerator CYHAL_UART_IRQ_RX_ERROR

An error occurred during RX.

enumerator CYHAL_UART_IRQ_RX_NOT_EMPTY

The HW RX FIFO buffer is not empty.

enumerator CYHAL_UART_IRQ_TX_EMPTY

The HW TX FIFO buffer is empty.

enumerator CYHAL_UART_IRQ_TX_FIFO

Number of entries in the HW TX FIFO is less than the TX FIFO trigger level.

enumerator CYHAL_UART_IRQ_RX_FIFO

Number of entries in the HW RX FIFO is more than the RX FIFO trigger level.

enum cyhal_uart_fifo_type_t

cyhal_uart_fifo_type_t: UART FIFO type.

Values:

enumerator CYHAL_UART_FIFO_RX

Set RX FIFO level.

enumerator CYHAL_UART_FIFO_TX

Set TX FIFO level.

enum cyhal_uart_output_t

cyhal_uart_output_t: Enum of possible output signals from a UART.

Values:

enumerator CYHAL_UART_OUTPUT_TRIGGER_RX_FIFO_LEVEL_REACHED

Output the RX FIFO signal which is triggered when the receive FIFO has more entries than the configured level.

enumerator CYHAL_UART_OUTPUT_TRIGGER_TX_FIFO_LEVEL_REACHED

Output the TX FIFO signal which is triggered when the transmit FIFO has less entries than the configured level.

Functions

cy_rslt_t cyhal_uart_init(cyhal_uart_t *obj, cyhal_gpio_t tx, cyhal_gpio_t rx, const cyhal_clock_t *clk, const cyhal_uart_cfg_t *cfg)

Initialize the UART peripheral.

note

This will set the baud rate to a default of CYHAL_UART_DEFAULT_BAUD. This can be changed by calling cyhal_uart_set_baud.

Return

The status of the init request

Parameters
  • [out] obj: Pointer to a UART object. The caller must allocate the memory for this object but the init function will initialize its contents.

  • [in] tx: The TX pin name, if no TX pin use NC

  • [in] rx: The RX pin name, if no RX pin use NC

  • [in] clk: The clock to use can be shared. If not provided, a new clock will be allocated and the default baud rate will be set

  • [in] cfg: The UART configuration data for data bits, stop bits and parity. If not provided, default values of (8, 1, none) will be used

void cyhal_uart_free(cyhal_uart_t *obj)

Release the UART peripheral.

Parameters
  • [inout] obj: The UART object

cy_rslt_t cyhal_uart_set_baud(cyhal_uart_t *obj, uint32_t baudrate, uint32_t *actualbaud)

Configure the baud rate.

note

This function should only be called if a shared clock divider is not used i.e. the clock parameter is set to NULL when calling cyhal_uart_init.

Return

The status of the set_baud request

Parameters
  • [inout] obj: The UART object

  • [in] baudrate: The baud rate to be configured

  • [out] actualbaud: The actual baud rate achieved by the HAL Specify NULL if you do not want this information.

cy_rslt_t cyhal_uart_configure(cyhal_uart_t *obj, const cyhal_uart_cfg_t *cfg)

Configure the data bits, stop bits, and parity.

Return

The status of the configure request

Parameters
  • [inout] obj: The UART object

  • [in] cfg: The UART configuration data for data bits, stop bits and parity. rx_buffer and rx_buffer_size are ignored.

cy_rslt_t cyhal_uart_getc(cyhal_uart_t *obj, uint8_t *value, uint32_t timeout)

Get a character.

This is a blocking call which waits till a character is received.

Return

The status of the getc request

Parameters
  • [in] obj: The UART object

  • [out] value: The value read from the serial port

  • [in] timeout: The time in ms to spend attempting to receive from serial port. Zero is wait forever

cy_rslt_t cyhal_uart_putc(cyhal_uart_t *obj, uint32_t value)

Send a character.

This is a blocking call which waits till the character is sent out from the UART completely.

Return

The status of the putc request

Parameters
  • [in] obj: The UART object

  • [in] value: The character to be sent

uint32_t cyhal_uart_readable(cyhal_uart_t *obj)

Check the number of bytes available to read from the receive buffers.

Return

The number of readable bytes

Parameters
  • [in] obj: The UART object

uint32_t cyhal_uart_writable(cyhal_uart_t *obj)

Check the number of bytes than can be written to the transmit buffer.

Return

The number of bytes that can be written

Parameters
  • [in] obj: The UART object

cy_rslt_t cyhal_uart_clear(cyhal_uart_t *obj)

Clear the UART buffers.

Return

The status of the clear request

Parameters
  • [in] obj: The UART object

cy_rslt_t cyhal_uart_set_flow_control(cyhal_uart_t *obj, cyhal_gpio_t cts, cyhal_gpio_t rts)

Configure the UART for flow control.

It sets flow control in the hardware if a UART peripheral supports it, otherwise software emulation is used.

Return

The status of the init_flow_control request

Parameters
  • [inout] obj: The UART object

  • [in] cts: The TX pin name

  • [in] rts: The RX pin name

cy_rslt_t cyhal_uart_write(cyhal_uart_t *obj, void *tx, size_t *tx_length)

Begin synchronous TX transfer.

This will write either length bytes or until the write buffer is full, whichever is less, then return. The value pointed to by length will be updated to reflect the number of bytes that was actually written.

Return

The status of the tx request

Parameters
  • [in] obj: The UART object

  • [in] tx: The transmit buffer

  • [inout] tx_length: [in] The number of bytes to transmit, [out] number actually transmitted

cy_rslt_t cyhal_uart_read(cyhal_uart_t *obj, void *rx, size_t *rx_length)

Begin synchronous RX transfer (enable interrupt for data collecting)

This will read either length bytes or the number of bytes that are currently available in the receive buffer, whichever is less, then return. The value pointed to by length will be updated to reflect the number of bytes that was actually read.

Return

The status of the rx request

Parameters
  • [in] obj: The UART object

  • [in] rx: The receive buffer

  • [inout] rx_length: [in] The number of bytes to receive, [out] number actually received

cy_rslt_t cyhal_uart_write_async(cyhal_uart_t *obj, void *tx, size_t length)

Begin asynchronous TX transfer.

This will transfer length bytes into the buffer pointed to by tx in the background. When the requested quantity of data has been transferred, the CYHAL_UART_IRQ_TX_TRANSMIT_IN_FIFO event will be raised. The transmit buffer is a user defined buffer that will be sent on the UART. The user must register a callback with cyhal_uart_register_callback. If desired, TX callback events can be enabled using cyhal_uart_enable_event with the appropriate events.

Return

The status of the tx_async request

Parameters
  • [in] obj: The UART object

  • [in] tx: The transmit buffer

  • [in] length: The number of bytes to transmit

cy_rslt_t cyhal_uart_read_async(cyhal_uart_t *obj, void *rx, size_t length)

Begin asynchronous RX transfer.

This will transfer length bytes into the buffer pointed to by rx in the background. When the requested quantity of data has been transferred, the CYHAL_UART_IRQ_RX_DONE event will be raised. Received data is placed in the user specified buffer. The user must register a callback with cyhal_uart_register_callback. RX callback events can be enabled using cyhal_uart_enable_event with the appropriate events.

Return

The status of the rx_async request

Parameters
  • [in] obj: The UART object

  • [out] rx: The user specified receive buffer

  • [in] length: The number of bytes to receive

bool cyhal_uart_is_tx_active(cyhal_uart_t *obj)

Determines if the UART peripheral is currently in use for TX.

Return

TX channel active status (active=true)

Parameters
  • [in] obj: The UART object

bool cyhal_uart_is_rx_active(cyhal_uart_t *obj)

Determines if the UART peripheral is currently in use for RX.

Return

RX channel active status (active=true)

Parameters
  • [in] obj: The UART object

cy_rslt_t cyhal_uart_write_abort(cyhal_uart_t *obj)

Abort the ongoing TX transaction.

Disables the TX interrupt and flushes the TX hardware buffer if TX FIFO is used.

Return

The status of the tx_abort request

Parameters
  • [in] obj: The UART object

cy_rslt_t cyhal_uart_read_abort(cyhal_uart_t *obj)

Abort the ongoing read transaction.

Disables the RX interrupt and flushes the RX hardware buffer if RX FIFO is used.

Return

The status of the read_abort request

Parameters
  • [in] obj: The UART object

void cyhal_uart_register_callback(cyhal_uart_t *obj, cyhal_uart_event_callback_t callback, void *callback_arg)

Register a uart callback handler.

This function will be called when one of the events enabled by cyhal_uart_enable_event occurs.

Parameters
  • [in] obj: The UART object

  • [in] callback: The callback handler which will be invoked when the interrupt fires

  • [in] callback_arg: Generic argument that will be provided to the callback when called

void cyhal_uart_enable_event(cyhal_uart_t *obj, cyhal_uart_event_t event, uint8_t intr_priority, bool enable)

Enable or disable specified UART events.

When an enabled event occurs, the function specified by cyhal_uart_register_callback will be called.

Parameters
  • [in] obj: The UART object

  • [in] event: The uart event type, this argument supports the bitwise-or of multiple enum flag values

  • [in] intr_priority: The priority for NVIC interrupt events

  • [in] enable: True to turn on interrupts, False to turn off

cy_rslt_t cyhal_uart_set_fifo_level(cyhal_uart_t *obj, cyhal_uart_fifo_type_t type, uint16_t level)

Sets a threshold level for a FIFO that will generate an interrupt and a trigger output.

The RX FIFO interrupt and trigger will be activated when the receive FIFO has more entries than the threshold. The TX FIFO interrupt and trigger will be activated when the transmit FIFO has less entries than the threshold.

Return

The status of the level set

Parameters
  • [in] obj: The UART object

  • [in] type: FIFO type to set level for

  • [in] level: Level threshold to set

cy_rslt_t cyhal_uart_enable_output(cyhal_uart_t *obj, cyhal_uart_output_t output, cyhal_source_t *source)

Enables the specified output signal from a UART.

Return

The status of the output enable

Parameters
  • [in] obj: The UART object

  • [in] output: Which output signal to enable

  • [out] source: Pointer to user-allocated source signal object which will be initialized by enable_output. source should be passed to (dis)connect_digital functions to (dis)connect the associated endpoints.

cy_rslt_t cyhal_uart_disable_output(cyhal_uart_t *obj, cyhal_uart_output_t output)

Disables the specified output signal from a UART.

Return

The status of the output disable

Parameters
  • [in] obj: The UART object

  • [in] output: Which output signal to disable

struct cyhal_uart_cfg_t
#include <cyhal_uart.h>

Initial UART configuration.

Public Members

uint32_t data_bits

The number of data bits (generally 8 or 9)

uint32_t stop_bits

The number of stop bits (generally 0 or 1)

cyhal_uart_parity_t parity

The parity.

uint8_t *rx_buffer

The rx software buffer pointer, if NULL, no rx software buffer will be used.

uint32_t rx_buffer_size

The number of bytes in the rx software buffer.