AM263Px MCU+ SDK: UART Low Level Driver

| AM263Px MCU+ SDK 26.00.00 |

UART Low Level Driver

# Features Supported

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

# 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_lld_init() : Initialize the UART driver.
- UART_lld_read() / UART_lld_readIntr() / UART_lld_readDma(): Read data in polling, interrupt, and Dma mode respectively.
- UART_lld_write() / UART_lld_writeIntr() / UART_lld_writeDma(): Write data in polling, interrupt, and Dma mode respectively..
- UART_lld_deInit(): De-initialize the UART instance.

## Initializing the UART Driver

UART_lld_init() must be called before any other UART APIs. This function uses uart handle to initialize each instance. Calling UART_lld_init() a second time with the same handle previously passed to UART_lld_init() will result in an error. You can, though, re-use the handle if the instance is closed via UART_lld_deInit(). In DMA mode, UART_lld_initDma() needs to be called instead of UART_lld_init() to acquire and initialize uart instance. Please note that initializing UART driver is taken care by the SysConfig generated code.

## 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 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 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 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 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.

# 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 LLD.

# Example Usage

Include the below file to access the APIs

#include "string.h"
#include <kernel/dpl/DebugP.h>
#include <kernel/dpl/SystemP.h>
#include <kernel/dpl/SemaphoreP.h>
#include <kernel/dpl/HwiP.h>
#include <kernel/dpl/MutexArmP.h>
#include <kernel/nortos/dpl/r5/HwiP_armv7r_vim.h>
#include <drivers/uart/v0/lld/uart_lld.h>

Instance Open Example

int32_t status = UART_STATUS_SUCCESS;
gUartHandle0 = &gUartObject[CONFIG_UART0];
status = UART_lld_init(gUartHandle0);
DebugP_assert(status == UART_STATUS_SUCCESS);

Instance Close Example

int32_t status = UART_STATUS_SUCCESS;
status = UART_lld_deInit(gUartHandle0);
DebugP_assert(status == UART_STATUS_SUCCESS);

Write Non-Blocking Transfer Example

int32_t transferOK;
UART_Transaction transaction;
intrNum = gUartInitObject[CONFIG_UART0].intrNum;
gUartVimStsAddr = gVimBaseAddr + (0x404u + (((intrNum)>> 5) & 0xFu) * 0x20u);
gUartVimStsClrMask = 0x1u << ((intrNum) & 0x1Fu);
UART_lld_Transaction_init(&transaction);
/* Send entry string */
gNumBytesWritten = 0U;
transaction.buf = &gUartBuffer[0U];
strncpy(transaction.buf,"This is uart echo test non-blocking mode\r\nReceives 8 characters then echo's back. Please input..\r\n", APP_UART_BUFSIZE);
transaction.count = strlen(transaction.buf);
transferOK = UART_lld_writeIntr(gUartHandle0, transaction.buf, transaction.count, NULL);
while(try_lock_mutex(gUartObject[CONFIG_UART0].writeTransferMutex) == MUTEX_ARM_LOCKED);
APP_UART_ASSERT_ON_FAILURE(transferOK, transaction);
/* Deregister IRQ */
HwiP_setVecAddr(intrNum, 0);
HwiP_setPri(intrNum, 15);

Read Non-Blocking Transfer Example

int32_t transferOK;
UART_Transaction transaction;
intrNum = gUartInitObject[CONFIG_UART0].intrNum;
gUartVimStsAddr = gVimBaseAddr + (0x404u + (((intrNum)>> 5) & 0xFu) * 0x20u);
gUartVimStsClrMask = 0x1u << ((intrNum) & 0x1Fu);
UART_lld_Transaction_init(&transaction);
/* Read 8 chars */
gNumBytesRead = 0U;
transaction.buf = &gUartReceiveBuffer[0U];
transaction.count = APP_UART_RECEIVE_BUFSIZE;
transferOK = UART_lld_readIntr(gUartHandle0, transaction.buf, transaction.count, NULL);
while(try_lock_mutex(gUartObject[CONFIG_UART0].readTransferMutex) == MUTEX_ARM_LOCKED);
APP_UART_ASSERT_ON_FAILURE(transferOK, transaction);
/* Deregister IRQ */
HwiP_setVecAddr(intrNum, 0);
HwiP_setPri(intrNum, 15);

Non-Blocking Example write callback

void UART_lld_writeCompleteCallback(void *args)
{
unlock_mutex(gUartObject[CONFIG_UART0].writeTransferMutex);
}

Non-Blocking Example read callback

void UART_lld_readCompleteCallback(void *args)
{
unlock_mutex(gUartObject[CONFIG_UART0].readTransferMutex);
return;
}

Non-Blocking Example ISR CALL callback

static __attribute__((__section__(".text.hwi"), noinline, naked, target("arm"), aligned(4))) void App_UART_ISR(void)
{
ISR_CALL_LEVEL_NONFLOAT_REENTRANT(UART_lld_controllerIsr, \
gUartHandle0, \
intrNum, \
gUartVimStsAddr, \
gUartVimStsClrMask,
gVimBaseAddr);
}

# API

APIs for UART

UART_lld_readIntr
int32_t UART_lld_readIntr(UARTLLD_Handle hUart, void *rxBuf, uint32_t size, const UART_ExtendedParams *extendedParams)
This API reads data from the UART instance in Interrupt mode.
args
void * args
Definition: hsmclient_msg.h:4
UART_lld_deInit
int32_t UART_lld_deInit(UARTLLD_Handle hUart)
This API De-Initializes the UART instance.
UART_lld_Transaction_init
void UART_lld_Transaction_init(UART_Transaction *trans)
Function to initialize the UART_Transaction struct to its defaults.
UART_lld_writeIntr
int32_t UART_lld_writeIntr(UARTLLD_Handle hUart, void *txBuf, uint32_t size, const UART_ExtendedParams *extendedParams)
This API writes data to the UART instance in Interrupt mode.
SystemP.h
SemaphoreP.h
UART_lld_controllerIsr
void UART_lld_controllerIsr(void *args)
This is the UART ISR and can be used as IRQ handler.
__attribute__
struct lld_sockaddr __attribute__
This is the SecureBoot Stream type which holds the data for a specific bootloader to HSM call....
HwiP.h
UART_lld_init
int32_t UART_lld_init(UARTLLD_Handle hUart)
This API Initializes the UART instance.
UART_Transaction
Data structure used with UART_read() and UART_write()
Definition: uart_lld.h:457
DebugP.h
UART_STATUS_SUCCESS
#define UART_STATUS_SUCCESS
Transaction success.
Definition: uart_lld.h:91
uart_lld.h
This file contains the prototype of UART driver APIs.
DebugP_assert
#define DebugP_assert(expression)
Function to call for assert check.
Definition: DebugP.h:187
UART_Transaction::buf
void * buf
Definition: uart_lld.h:458
UART_Transaction::count
uint32_t count
Definition: uart_lld.h:461