AM261x MCU+ SDK: UART High Level Driver

| AM261x MCU+ SDK 26.00.00 |

UART High Level Driver

# Features Supported

- Write and Read mode of operation
- Interrupt, Polled Mode
- DMA mode of operation
- Blocking and Non-blocking (Callback) transfers
- Write and Read Cancel mode of operation

# Features NOT Supported

- UART_READ_RETURN_MODE_PARTIAL is not supported in DMA mode of operation
- MODEM control functions
- IrDA(Infrared Data Association) and CIR(Consumer Infrared) features

# Usage Overview

## API Sequence

To use the UART driver to send data or receive, the application calls the following APIs:

- UART_init() : Initialize the UART driver.
- UART_Params_init(): Initialize a UART_Params structure with default values. Then change the parameters from non-default values as needed.
- UART_open() : Open an instance of the UART driver, passing the initialized parameters, or NULL, and an index to the configuration to open (detailed later).
- UART_write(): Transmit data. This function takes a UART_Transaction argument that describes the transfer that is requested.
- UART_read() : Receive data. This function takes a UART_Transaction as an argument that describes the receive that is requested.
- UART_close(): Close the UART instance.
- UART_deinit(): De-Initialize the UART driver.

## Initializing the UART Driver

UART_init() must be called before any other UART APIs. This function iterates through the elements of the UART_config[] array, calling the element's device implementation UART initialization function. Please note that initializing UART driver is taken care by the SysConfig generated code.

## Opening the UART Driver

After initializing the UART driver by calling UART_init(), the application can open a UART instance by calling UART_open(). Please note that opening UART driver is taken care by the SysConfig generated code. This function takes an index into the UART_config[] array, and the UART parameters data structure. The UART instance is specified by the index of the UART in UART_config[]. Calling UART_open() second time with the same index previously passed to UART_open() will result in an error. You can, though, re-use the index if the instance is closed via UART_close().

If no UART_Params_init structure is passed to UART_open(), default values are used. If the open call is successful, it returns a non-NULL value.

## UART Write Mode

The UART driver supports two transfer modes of operation: interrupt and polling mode. In polling mode a task's code execution is blocked until a UART transaction has completed or a timeout has occurred.

In interrupt mode, again there are two modes blocking and callback. The transfer mode is determined by the UART_Params.writeMode parameter. The UART driver defaults to blocking mode, if the application does not set it. Once a UART driver is opened, the only way to change the operation mode is to close and re-open the UART instance with the new write mode.

In blocking mode, a task's code execution is blocked until a UART transaction has completed or a timeout has occurred. This ensures that only one UART transfer operates at a given time. Other tasks requesting UART transfers while a transfer is currently taking place will receive an error as return value. If a timeout occurs the transfer is cancelled, the task is unblocked & will receive an error as return value. The transaction count field will have the number of bytes transferred successfully before the timeout.

In callback mode, a UART transaction functions asynchronously, which means that it does not block code execution. After a UART transaction has been completed, the UART driver calls a user-provided callback function. Callback mode is supported in the execution context of tasks and hardware interrupt routines.

## UART Read Mode

The UART driver supports two read modes of operation: interrupt and polling mode. In polling mode a task's code execution is blocked until a UART transaction has completed or a timeout has occurred.

In interrupt mode, again there are two modes blocking and callback. The read mode is determined by the UART_Params.readMode parameter. The UART driver defaults to blocking mode, if the application does not set it. Once a UART driver is opened, the only way to change the operation mode is to close and re-open the UART instance with the new read mode.

In blocking mode, a task's code execution is blocked until a UART transaction has completed or a timeout has occurred. This ensures that only one UART read completes at a given time. Other tasks requesting UART read while a read is currently taking place will receive an error as return value. If a timeout occurs the read is cancelled, the task is unblocked & will receive an error as return value. The transaction count field will have the number of bytes read successfully before the timeout.

In callback mode, a UART transaction functions asynchronously, which means that it does not block code execution. After a UART transaction has been completed, the UART driver calls a user-provided callback function. Callback mode is supported in the execution context of tasks and hardware interrupt routines.

There is an additional UART_Params.readReturnMode parameter. UART_READ_RETURN_MODE_FULL unblocks or performs a callback when the read buffer has been filled with the number of bytes passed to UART_read(). UART_READ_RETURN_MODE_PARTIAL unblocks or performs a callback whenever a read timeout error occurs on the UART peripheral. The read timeout occurs if the read FIFO is non-empty and no new data has been received for a specific number of clock cycles w.r.o device/baudrate dependent. This mode can be used when the exact number of bytes to be read is not known.

# Important Usage Guidelines

- In case of DMA mode, as R5F core is not Cache Coherent, Cache Writeback is required if R5F writes to the buffers. And before reading the buffers, application needs to invalidate those. Please refer UART Echo DMA.

# Example Usage

Include the below file to access the APIs

#include <drivers/uart.h>

Instance Open Example

UART_Params params;
UART_Params_init(&params); /* Initialize parameters */
params.baudRate = 115200;
gUartHandle = UART_open(CONFIG_UART0, &params);
DebugP_assert(gUartHandle != NULL);

Instance Close Example

UART_close(gUartHandle);

Write Transfer Example

int32_t transferOK;
UART_Transaction transaction;
uint8_t txBuffer[APP_UART_MSGSIZE];
UART_Transaction_init(&transaction);
/* Initiate write */
transaction.count = APP_UART_MSGSIZE;
transaction.buf = (void *)txBuffer;
transaction.args = NULL;
transferOK = UART_write(gUartHandle, &transaction);
if((SystemP_SUCCESS != transferOK) ||
(UART_TRANSFER_STATUS_SUCCESS != transaction.status))
{
/* UART transfer failed!! */
DebugP_assert(FALSE);
}

Read Transfer Example

int32_t transferOK;
UART_Transaction transaction;
uint8_t rxBuffer[APP_UART_MSGSIZE];
UART_Transaction_init(&transaction);
/* Initiate read */
transaction.count = APP_UART_MSGSIZE;
transaction.buf = (void *)rxBuffer;
transaction.args = NULL;
transferOK = UART_read(gUartHandle, &transaction);
if((SystemP_SUCCESS != transferOK) ||
(UART_TRANSFER_STATUS_SUCCESS != transaction.status))
{
/* UART transfer failed!! */
DebugP_assert(FALSE);
}

Write Non-Blocking Transfer Example

void write_callback(UART_Handle handle, UART_Transaction *trans)
{
DebugP_assertNoLog(UART_TRANSFER_STATUS_SUCCESS == trans->status);
gNumBytesWritten = trans->count;
SemaphoreP_post(&gUartWriteDoneSem);
return;
}
void write_transfer_nonblocking(void)
{
int32_t transferOK;
UART_Transaction transaction;
uint8_t txBuffer[APP_UART_MSGSIZE];
UART_Transaction_init(&transaction);
/* Initiate write */
transaction.count = APP_UART_MSGSIZE;
transaction.buf = (void *)txBuffer;
transaction.args = NULL;
transferOK = UART_write(gUartHandle, &transaction);
if((SystemP_SUCCESS != transferOK) ||
(UART_TRANSFER_STATUS_SUCCESS != transaction.status))
{
/* UART transfer failed!! */
DebugP_assert(FALSE);
}
else
{
/* Wait for callback */
SemaphoreP_pend(&gUartWriteDoneSem, SystemP_WAIT_FOREVER);
DebugP_assert(gNumBytesWritten == transaction.count);
}
}

Read Non-Blocking Transfer Example

void read_callback(UART_Handle handle, UART_Transaction *trans)
{
DebugP_assertNoLog(UART_TRANSFER_STATUS_SUCCESS == trans->status);
gNumBytesRead = trans->count;
SemaphoreP_post(&gUartReadDoneSem);
return;
}
void read_transfer_nonblocking(void)
{
int32_t transferOK;
UART_Transaction transaction;
uint8_t rxBuffer[APP_UART_MSGSIZE];
UART_Transaction_init(&transaction);
/* Initiate read */
transaction.count = APP_UART_MSGSIZE;
transaction.buf = (void *)rxBuffer;
transaction.args = NULL;
transferOK = UART_read(gUartHandle, &transaction);
if((SystemP_SUCCESS != transferOK) ||
(UART_TRANSFER_STATUS_SUCCESS != transaction.status))
{
/* UART transfer failed!! */
DebugP_assert(FALSE);
}
else
{
/* Wait for callback */
SemaphoreP_pend(&gUartReadDoneSem, SystemP_WAIT_FOREVER);
DebugP_assert(gNumBytesRead == transaction.count);
}
}

# API

APIs for UART

FALSE
#define FALSE
Definition: os_defs.h:32
UART_TRANSFER_STATUS_SUCCESS
#define UART_TRANSFER_STATUS_SUCCESS
Transaction success.
Definition: uart_lld.h:95
UART_Transaction_init
void UART_Transaction_init(UART_Transaction *trans)
Function to initialize the UART_Transaction struct to its defaults.
UART_Params_init
void UART_Params_init(UART_Params *prms)
Function to initialize the UART_Params struct to its defaults.
SystemP_WAIT_FOREVER
#define SystemP_WAIT_FOREVER
Value to use when needing a timeout of infinity or wait forver until resource is available.
Definition: SystemP.h:83
UART_write
int32_t UART_write(UART_Handle handle, UART_Transaction *trans)
Function to perform UART write operation.
UART_close
void UART_close(UART_Handle handle)
Function to close a UART peripheral specified by the UART handle.
uart.h
UART_Transaction::status
int32_t status
Definition: uart_lld.h:467
DebugP_assertNoLog
#define DebugP_assertNoLog(expression)
Function to call for assert check, no logs are printed.
Definition: DebugP.h:199
UART_Handle
struct UART_Config_s * UART_Handle
Definition: uart/v0/uart.h:71
UART_Params
UART Parameters.
Definition: uart/v0/uart.h:120
UART_Params::baudRate
uint32_t baudRate
Definition: uart/v0/uart.h:121
SystemP_SUCCESS
#define SystemP_SUCCESS
Return status when the API execution was successful.
Definition: SystemP.h:56
UART_Transaction
Data structure used with UART_read() and UART_write()
Definition: uart_lld.h:457
UART_open
UART_Handle UART_open(uint32_t index, const UART_Params *prms)
This function opens a given UART peripheral.
SemaphoreP_post
void SemaphoreP_post(SemaphoreP_Object *obj)
Post a semaphore object or unlock a mutex.
UART_read
int32_t UART_read(UART_Handle handle, UART_Transaction *trans)
Function to perform UART read operation.
DebugP_assert
#define DebugP_assert(expression)
Function to call for assert check.
Definition: DebugP.h:187
UART_Transaction::args
uint32_t * args
Definition: uart_lld.h:469
UART_Transaction::buf
void * buf
Definition: uart_lld.h:458
SemaphoreP_pend
int32_t SemaphoreP_pend(SemaphoreP_Object *obj, uint32_t timeToWaitInTicks)
Pend on a semaphore object or lock a mutex.
UART_Transaction::count
uint32_t count
Definition: uart_lld.h:461