596 lines
15 KiB
C
596 lines
15 KiB
C
|
/*
|
||
|
* @brief UART ROM API declarations and functions
|
||
|
*
|
||
|
* @note
|
||
|
* Copyright(C) NXP Semiconductors, 2014
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* @par
|
||
|
* Software that is described herein is for illustrative purposes only
|
||
|
* which provides customers with programming information regarding the
|
||
|
* LPC products. This software is supplied "AS IS" without any warranties of
|
||
|
* any kind, and NXP Semiconductors and its licensor disclaim any and
|
||
|
* all warranties, express or implied, including all implied warranties of
|
||
|
* merchantability, fitness for a particular purpose and non-infringement of
|
||
|
* intellectual property rights. NXP Semiconductors assumes no responsibility
|
||
|
* or liability for the use of the software, conveys no license or rights under any
|
||
|
* patent, copyright, mask work right, or any other intellectual property rights in
|
||
|
* or to any products. NXP Semiconductors reserves the right to make changes
|
||
|
* in the software without notification. NXP Semiconductors also makes no
|
||
|
* representation or warranty that such application will be suitable for the
|
||
|
* specified use without further testing or modification.
|
||
|
*
|
||
|
* @par
|
||
|
* Permission to use, copy, modify, and distribute this software and its
|
||
|
* documentation is hereby granted, under NXP Semiconductors' and its
|
||
|
* licensor's relevant copyrights in the software, without fee, provided that it
|
||
|
* is used in conjunction with NXP Semiconductors microcontrollers. This
|
||
|
* copyright, permission, and disclaimer notice must appear in all copies of
|
||
|
* this code.
|
||
|
*/
|
||
|
|
||
|
#include "error.h"
|
||
|
#include "hw_uart_rom_api.h"
|
||
|
|
||
|
#define UART_IDLE_FIX /* Remove once IDLE problem is fixed */
|
||
|
|
||
|
/* UART Driver internal data structure */
|
||
|
typedef struct {
|
||
|
void *pUserData; /* Pointer to user data */
|
||
|
UART_REGS_T *pREGS; /* Pointer to Registers */
|
||
|
UART_DATA_T xfer[2]; /* TX/RX transfer data */
|
||
|
#ifdef UART_IDLE_FIX
|
||
|
uint32_t dly; /* Delay to count 1 bit time; REMOVE: when H/W is fixed */
|
||
|
#endif
|
||
|
void(*cbTable[UART_CB_RESERVED]) (UART_HANDLE_T, UART_EVENT_T, void *); /* Call-back index table */
|
||
|
} UART_DRIVER_T;
|
||
|
|
||
|
/* PRIVATE: Division logic to divide without integer overflow */
|
||
|
static uint32_t _UART_DivClk(uint32_t pclk, uint32_t m)
|
||
|
{
|
||
|
uint32_t q, r, u = pclk >> 24, l = pclk << 8;
|
||
|
m = m + 256;
|
||
|
q = (1 << 24) / m;
|
||
|
r = (1 << 24) - (q * m);
|
||
|
return ((q * u) << 8) + (((r * u) << 8) + l) / m;
|
||
|
}
|
||
|
|
||
|
/* PRIVATE: Get highest Over sampling value */
|
||
|
static uint32_t _UART_GetHighDiv(uint32_t val, uint8_t strict)
|
||
|
{
|
||
|
int32_t i, max = strict ? 16 : 5;
|
||
|
for (i = 16; i >= max; i--) {
|
||
|
if (!(val % i)) {
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* PRIVATE: Queue a transfer in UART */
|
||
|
static ErrorCode_t _UART_Xfer(UART_DRIVER_T *pUART, void *buff, uint16_t len, uint8_t op)
|
||
|
{
|
||
|
UART_DATA_T *xfr = &pUART->xfer[op];
|
||
|
|
||
|
/* Xfer of 0 bytes in a UART should always be successful */
|
||
|
if (!len) {
|
||
|
return LPC_OK;
|
||
|
}
|
||
|
|
||
|
/* Check if a Xfer is alredy in progress */
|
||
|
if (xfr->count > xfr->offset) {
|
||
|
return ERR_BUSY;
|
||
|
}
|
||
|
|
||
|
xfr->buf = (void *) buff;
|
||
|
xfr->count = len;
|
||
|
xfr->offset = 0;
|
||
|
xfr->state = UART_ST_BUSY;
|
||
|
if (!op) {
|
||
|
pUART->pREGS->INTENSET = UART_INT_TXRDY;
|
||
|
}
|
||
|
else {
|
||
|
pUART->pREGS->INTENSET = UART_INT_RXRDY | UART_INT_FRMERR | UART_INT_RXNOISE | UART_INT_START | UART_INT_OVR;
|
||
|
}
|
||
|
|
||
|
return LPC_OK;
|
||
|
}
|
||
|
|
||
|
/* Calculate error difference */
|
||
|
static int32_t _CalcErr(uint32_t n, uint32_t d, uint32_t *prev)
|
||
|
{
|
||
|
uint32_t err = n - (n / d) * d;
|
||
|
uint32_t herr = ((n / d) + 1) * d - n;
|
||
|
if (herr < err) {
|
||
|
err = herr;
|
||
|
}
|
||
|
|
||
|
if (*prev <= err) {
|
||
|
return 0;
|
||
|
}
|
||
|
*prev = err;
|
||
|
return (herr == err) + 1;
|
||
|
}
|
||
|
|
||
|
/* Calculate the base DIV value */
|
||
|
static ErrorCode_t _UART_CalcDiv(UART_BAUD_T *ub)
|
||
|
{
|
||
|
int32_t i = 0;
|
||
|
uint32_t perr = ~0UL;
|
||
|
|
||
|
if (!ub->div) {
|
||
|
i = ub->ovr ? ub->ovr : 16;
|
||
|
}
|
||
|
|
||
|
for (; i > 4; i--) {
|
||
|
int32_t tmp = _CalcErr(ub->clk, ub->baud * i, &perr);
|
||
|
|
||
|
/* Continue when no improvement seen in err value */
|
||
|
if (!tmp) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
ub->div = tmp - 1;
|
||
|
if (ub->ovr == i) {
|
||
|
break;
|
||
|
}
|
||
|
ub->ovr = i;
|
||
|
}
|
||
|
|
||
|
if (!ub->ovr) {
|
||
|
return ERR_UART_BAUDRATE;
|
||
|
}
|
||
|
|
||
|
ub->div += ub->clk / (ub->baud * ub->ovr);
|
||
|
if (!ub->div) {
|
||
|
return ERR_UART_BAUDRATE;
|
||
|
}
|
||
|
|
||
|
ub->baud = ub->clk / (ub->div * ub->ovr);
|
||
|
return LPC_OK;
|
||
|
}
|
||
|
|
||
|
/* Calculate the best MUL value */
|
||
|
static void _UART_CalcMul(UART_BAUD_T *ub)
|
||
|
{
|
||
|
uint32_t m, perr = ~0UL, pclk = ub->clk, ovr = ub->ovr;
|
||
|
|
||
|
/* If clock is UART's base clock calculate only the divider */
|
||
|
for (m = 0; m < 256; m++) {
|
||
|
uint32_t ov = ovr, x, v, tmp;
|
||
|
|
||
|
/* Get clock and calculate error */
|
||
|
x = _UART_DivClk(pclk, m);
|
||
|
tmp = _CalcErr(x, ub->baud, &perr);
|
||
|
v = (x / ub->baud) + tmp - 1;
|
||
|
|
||
|
/* Update if new error is better than previous best */
|
||
|
if (!tmp || (ovr && (v % ovr)) ||
|
||
|
(!ovr && ((ov = _UART_GetHighDiv(v, ovr)) == 0))) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
ub->ovr = ov;
|
||
|
ub->mul = m;
|
||
|
ub->clk = x;
|
||
|
ub->div = tmp - 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* PRIVATE: Invoke UART Call back functions */
|
||
|
static void _UART_InvokeCB(UART_DRIVER_T *pUART, UART_EVENT_T event, void *arg)
|
||
|
{
|
||
|
void (*cbfn)(UART_HANDLE_T, UART_EVENT_T, void *);
|
||
|
cbfn = pUART->cbTable[(uint32_t) event >> 1];
|
||
|
if (cbfn != NULL) {
|
||
|
cbfn((UART_HANDLE_T) pUART, event, arg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* PRIVATE: Handler for data transfers */
|
||
|
static void _UART_HandleTxRx(UART_HANDLE_T hUART, UART_EVENT_T event, void *arg)
|
||
|
{
|
||
|
UART_DATA_T *dat = (UART_DATA_T *) arg;
|
||
|
UART_DRIVER_T *pUART = (UART_DRIVER_T *) hUART;
|
||
|
uint16_t *buf16 = dat->buf;
|
||
|
uint8_t *buf8 = dat->buf;
|
||
|
|
||
|
/* Transmit data */
|
||
|
if (event == UART_TX_DATA) {
|
||
|
while (dat->count && (pUART->pREGS->INTSTAT & UART_INT_TXRDY)) {
|
||
|
if (dat->dwidth) {
|
||
|
pUART->pREGS->TXDAT = *buf16++;
|
||
|
}
|
||
|
else {
|
||
|
pUART->pREGS->TXDAT = *buf8++;
|
||
|
}
|
||
|
dat->count--;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Receive data */
|
||
|
while (dat->count && (pUART->pREGS->INTSTAT & UART_INT_RXRDY)) {
|
||
|
if (dat->dwidth) {
|
||
|
*buf16++ = pUART->pREGS->RXDAT & 0x1FF;
|
||
|
}
|
||
|
else {
|
||
|
*buf8++ = pUART->pREGS->RXDAT & 0xFF;
|
||
|
}
|
||
|
dat->count--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Handle UART Receive event */
|
||
|
static int32_t _UART_HandleXfer(UART_DRIVER_T *pUART, uint8_t op)
|
||
|
{
|
||
|
UART_DATA_T dat;
|
||
|
UART_DATA_T *xfr = &pUART->xfer[op];
|
||
|
|
||
|
/* See if the transfer is already complete */
|
||
|
if (xfr->offset >= xfr->count) {
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
/* Fill the buffer data structure */
|
||
|
dat.count = xfr->count - xfr->offset;
|
||
|
dat.dwidth = ((pUART->pREGS->CFG >> 2) & 3) > 1;
|
||
|
if (dat.dwidth) {
|
||
|
dat.buf = &((uint16_t *) xfr->buf)[xfr->offset];
|
||
|
}
|
||
|
else {
|
||
|
dat.buf = &((uint8_t *) xfr->buf)[xfr->offset];
|
||
|
}
|
||
|
|
||
|
if (!xfr->offset && xfr->count) {
|
||
|
_UART_InvokeCB(pUART, UART_TX_START, xfr);
|
||
|
}
|
||
|
|
||
|
pUART->cbTable[UART_CB_DATA]((UART_HANDLE_T) pUART, (UART_EVENT_T) (UART_TX_DATA + op), &dat);
|
||
|
xfr->offset = (xfr->count - dat.count);
|
||
|
|
||
|
if (xfr->offset >= xfr->count) {
|
||
|
if (!op) {
|
||
|
pUART->pREGS->INTENCLR = UART_INT_TXRDY;
|
||
|
}
|
||
|
else {
|
||
|
pUART->pREGS->INTENCLR = UART_INT_RXRDY;
|
||
|
}
|
||
|
|
||
|
_UART_InvokeCB(pUART, (UART_EVENT_T) (UART_TX_DONE + op), xfr);
|
||
|
if (xfr->state == UART_ST_BUSY) {
|
||
|
xfr->state = UART_ST_DONE;
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* STOP Receive under progress */
|
||
|
static void _UART_StopRx(UART_HANDLE_T hUART)
|
||
|
{
|
||
|
UART_DRIVER_T *pUART = (UART_DRIVER_T *) hUART;
|
||
|
UART_DATA_T *rx = &pUART->xfer[1];
|
||
|
volatile uint16_t *idx = (volatile uint16_t *) &rx->offset;
|
||
|
|
||
|
if (*idx >= rx->count) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* Disable further receive interrupts */
|
||
|
pUART->pREGS->INTENCLR = UART_INT_RXRDY;
|
||
|
rx->count = *idx;
|
||
|
_UART_InvokeCB(pUART, UART_RX_DONE, rx);
|
||
|
}
|
||
|
|
||
|
/* EXPROTED API: Returns memory required for UART ROM driver */
|
||
|
uint32_t UART_GetMemSize(void)
|
||
|
{
|
||
|
return sizeof(UART_DRIVER_T);
|
||
|
}
|
||
|
|
||
|
/* EXPORTED API: Calculate UART Baudrate divisors */
|
||
|
ErrorCode_t UART_CalculateBaud(UART_BAUD_T *ub)
|
||
|
{
|
||
|
if (!ub->mul) {
|
||
|
_UART_CalcMul(ub);
|
||
|
}
|
||
|
|
||
|
return _UART_CalcDiv(ub);
|
||
|
}
|
||
|
|
||
|
/* EXPORTED API: UART Initialization function */
|
||
|
UART_HANDLE_T UART_Init(void *mem, uint32_t base_addr, void *args)
|
||
|
{
|
||
|
UART_DRIVER_T *pUART;
|
||
|
|
||
|
/* Check if the memory is word aligned */
|
||
|
if ((uint32_t) mem & 0x3) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/* Assign memory provided by application */
|
||
|
pUART = (UART_DRIVER_T *) mem;
|
||
|
memset(pUART, 0, sizeof(UART_DRIVER_T));
|
||
|
|
||
|
/* Assign the base address */
|
||
|
pUART->pREGS = (UART_REGS_T *) base_addr;
|
||
|
pUART->pUserData = args;
|
||
|
|
||
|
/* Set default handler for TX and RX */
|
||
|
pUART->cbTable[UART_CB_DATA] = _UART_HandleTxRx;
|
||
|
return (UART_HANDLE_T) pUART;
|
||
|
}
|
||
|
|
||
|
/* EXPORTED API: Configure UART parameters */
|
||
|
ErrorCode_t UART_Configure(UART_HANDLE_T hUART, const UART_CFG_T *cfg)
|
||
|
{
|
||
|
UART_DRIVER_T *pUART = (UART_DRIVER_T *) hUART;
|
||
|
UART_REGS_T *pREGS = pUART->pREGS;
|
||
|
|
||
|
if (((cfg->cfg & UART_PAR_MASK) == (1 << 4)) ||
|
||
|
( (cfg->cfg & UART_DATA_MASK) == (3 << 2)) ) {
|
||
|
return ERR_UART_PARAM;
|
||
|
}
|
||
|
|
||
|
/* Enable parity error when parity is enabled */
|
||
|
if ((cfg->cfg & UART_PAR_MASK) >> 4) {
|
||
|
pREGS->INTENSET = UART_INT_PARERR;
|
||
|
}
|
||
|
|
||
|
if (((int32_t) cfg->div <= 0) || ((int32_t) cfg->ovr <= 0)) {
|
||
|
return ERR_UART_PARAM;
|
||
|
}
|
||
|
|
||
|
pREGS->OSR = (cfg->ovr - 1) & 0x0F;
|
||
|
pREGS->BRG = (cfg->div - 1) & 0xFFFF;
|
||
|
pREGS->CFG = UART_CFG_ENABLE | (cfg->cfg & ~UART_CFG_RES);
|
||
|
|
||
|
/* Enabled RX of BREAK event */
|
||
|
if (cfg->cfg & UART_CFG_BRKRX) {
|
||
|
pREGS->INTENSET = UART_INT_BREAK;
|
||
|
}
|
||
|
|
||
|
/* Enable CTS interrupt if requested */
|
||
|
if (cfg->cfg & UART_CFG_CTSEV) {
|
||
|
pREGS->INTENSET = UART_INT_CTS;
|
||
|
}
|
||
|
|
||
|
#ifdef UART_IDLE_FIX
|
||
|
/* REMOVE: if/else block after H/W idle is fixed */
|
||
|
if (cfg->res > 224) {
|
||
|
pUART->dly = 3072 * (cfg->res - 224);
|
||
|
}
|
||
|
else {
|
||
|
pUART->dly = cfg->res << 2;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return LPC_OK;
|
||
|
}
|
||
|
|
||
|
/* EXPORTED API: UART setup special operation like BREAK etc. */
|
||
|
void UART_SetControl(UART_HANDLE_T hUART, uint32_t cfg)
|
||
|
{
|
||
|
uint32_t en, dis;
|
||
|
UART_REGS_T *pREGS = ((UART_DRIVER_T *) hUART)->pREGS;
|
||
|
|
||
|
/* Get list of enabled and disabled options */
|
||
|
en = ((cfg >> 16) & (cfg & 0xFFFF)) << 1;
|
||
|
dis = ((cfg >> 16) & ~(cfg & 0xFFFF)) << 1;
|
||
|
|
||
|
/* See if it is RX Stop request */
|
||
|
if (cfg & UART_RX_STOP) {
|
||
|
_UART_StopRx(hUART);
|
||
|
}
|
||
|
|
||
|
/* See if any IDLEs are enabled */
|
||
|
if (cfg & (UART_IDLE_MASK << 16)) {
|
||
|
pREGS->INTENSET = (en >> 1) & UART_IDLE_MASK;
|
||
|
pREGS->INTENCLR = (dis >> 1) & UART_IDLE_MASK;
|
||
|
}
|
||
|
|
||
|
/* See if it is a request BREAK after TX */
|
||
|
if (en & UART_CTL_TXDIS) {
|
||
|
if (en & UART_CTL_TXBRKEN) {
|
||
|
pREGS->CTL = (pREGS->CTL & ~UART_CTL_RES) | UART_CTL_TXDIS;
|
||
|
while (!(pREGS->STAT & UART_INT_TXDIS)) {}
|
||
|
#ifdef UART_IDLE_FIX
|
||
|
if (1) {
|
||
|
volatile uint32_t dly = ((UART_DRIVER_T *) hUART)->dly;
|
||
|
while (dly--) {}/* Provide some idling time H/W does not do this */
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
else {
|
||
|
pREGS->INTENSET = UART_INT_TXDIS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* See if we are releasing break and resume TX operation */
|
||
|
if ((dis & UART_CTL_TXDIS) && (dis & UART_CTL_TXBRKEN)) {
|
||
|
pREGS->CTL = pREGS->CTL & ~(UART_CTL_RES | UART_CTL_TXBRKEN);
|
||
|
#ifdef UART_IDLE_FIX
|
||
|
if (1) {
|
||
|
volatile uint32_t dly = ((UART_DRIVER_T *) hUART)->dly;
|
||
|
while (dly--) {} /* Provide some idling time H/W does not do this */
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/* Check for autobaud and enable autobaud err interrupt */
|
||
|
if (en & UART_CTL_AUTOBAUD) {
|
||
|
pREGS->INTENSET = UART_INT_ABAUDERR;
|
||
|
}
|
||
|
|
||
|
pREGS->CTL = ((pREGS->CTL | en) & ~dis) & ~UART_CTL_RES;
|
||
|
}
|
||
|
|
||
|
/* EXPORTED API: Register a call-back function */
|
||
|
ErrorCode_t UART_RegisterCB(UART_HANDLE_T hUART,
|
||
|
UART_CBINDEX_T idx,
|
||
|
void (*cb_func)(UART_HANDLE_T, UART_EVENT_T, void *))
|
||
|
{
|
||
|
if (idx < UART_CB_RESERVED) {
|
||
|
((UART_DRIVER_T *) hUART)->cbTable[idx] = cb_func;
|
||
|
}
|
||
|
else {
|
||
|
return ERR_UART_PARAM;
|
||
|
}
|
||
|
|
||
|
/* Restore internal data handlers when external ones are un-registered */
|
||
|
if ((idx == UART_CB_DATA) && (cb_func == NULL)) {
|
||
|
((UART_DRIVER_T *) hUART)->cbTable[idx] = _UART_HandleTxRx;
|
||
|
}
|
||
|
|
||
|
return LPC_OK;
|
||
|
}
|
||
|
|
||
|
/* EXPORTED API: UART Event handler */
|
||
|
void UART_Handler(UART_HANDLE_T hUART)
|
||
|
{
|
||
|
UART_DRIVER_T *pUART = (UART_DRIVER_T *) hUART;
|
||
|
uint32_t flags = pUART->pREGS->INTENSET & pUART->pREGS->INTSTAT;
|
||
|
|
||
|
if (flags & UART_INT_TXRDY) {
|
||
|
_UART_HandleXfer(pUART, 0);
|
||
|
}
|
||
|
|
||
|
if (flags & UART_INT_FRMERR) {
|
||
|
pUART->pREGS->STAT = UART_INT_FRMERR;
|
||
|
if (pUART->xfer[1].state == UART_ST_BUSY) {
|
||
|
pUART->xfer[1].state = UART_ST_ERRFRM;
|
||
|
}
|
||
|
_UART_InvokeCB(pUART, UART_EV_ERROR, (void *) UART_ERROR_FRAME);
|
||
|
}
|
||
|
|
||
|
if (flags & UART_INT_PARERR) {
|
||
|
pUART->pREGS->STAT = UART_INT_PARERR;
|
||
|
if (pUART->xfer[1].state == UART_ST_BUSY) {
|
||
|
pUART->xfer[1].state = UART_ST_ERRPAR;
|
||
|
}
|
||
|
_UART_InvokeCB(pUART, UART_EV_ERROR, (void *) UART_ERROR_PARITY);
|
||
|
}
|
||
|
|
||
|
if (flags & UART_INT_ABAUDERR) {
|
||
|
pUART->pREGS->STAT = UART_INT_ABAUDERR;
|
||
|
if (pUART->xfer[1].state == UART_ST_BUSY) {
|
||
|
pUART->xfer[1].state = UART_ST_ERR;
|
||
|
}
|
||
|
_UART_InvokeCB(pUART, UART_EV_ERROR, (void *) UART_ERROR_AUTOBAUD);
|
||
|
}
|
||
|
|
||
|
if (flags & UART_INT_RXNOISE) {
|
||
|
pUART->pREGS->STAT = UART_INT_RXNOISE;
|
||
|
if (pUART->xfer[1].state == UART_ST_BUSY) {
|
||
|
pUART->xfer[1].state = UART_ST_ERRNOISE;
|
||
|
}
|
||
|
_UART_InvokeCB(pUART, UART_EV_ERROR, (void *) UART_ERROR_RXNOISE);
|
||
|
}
|
||
|
|
||
|
if (flags & UART_INT_OVR) {
|
||
|
pUART->pREGS->STAT = UART_INT_OVR;
|
||
|
if (pUART->xfer[1].state == UART_ST_BUSY) {
|
||
|
pUART->xfer[1].state = UART_ST_ERROVR;
|
||
|
}
|
||
|
_UART_InvokeCB(pUART, UART_EV_ERROR, (void *) UART_ERROR_OVERRUN);
|
||
|
}
|
||
|
|
||
|
if (flags & UART_INT_RXRDY) {
|
||
|
_UART_HandleXfer(pUART, 1);
|
||
|
#ifdef UART_IDLE_FIX
|
||
|
if (1) {
|
||
|
volatile uint32_t dly = ((UART_DRIVER_T *) hUART)->dly;
|
||
|
while ((pUART->pREGS->STAT & UART_STAT_RXIDLE) && dly--) {}
|
||
|
}
|
||
|
#else
|
||
|
while (pUART->pREGS->STAT & UART_STAT_RXIDLE) {}
|
||
|
#endif
|
||
|
_UART_InvokeCB(pUART, (UART_EVENT_T) (UART_RX_INPROG + ((pUART->pREGS->STAT >> 1) & 1)), &pUART->xfer[1]);
|
||
|
}
|
||
|
|
||
|
if (flags & UART_INT_TXIDLE) {
|
||
|
_UART_InvokeCB(pUART, UART_EV_EVENT, (void *) UART_EVENT_TXIDLE);
|
||
|
}
|
||
|
|
||
|
if (flags & UART_INT_TXDIS) {
|
||
|
pUART->pREGS->INTENCLR = UART_INT_TXDIS;/* Disable interrupt */
|
||
|
_UART_InvokeCB(pUART, UART_EV_EVENT, (void *) UART_EVENT_TXPAUSED);
|
||
|
}
|
||
|
|
||
|
if (flags & UART_INT_CTS) {
|
||
|
pUART->pREGS->STAT = UART_INT_CTS;
|
||
|
_UART_InvokeCB(pUART, UART_EV_EVENT,
|
||
|
(void *) ((pUART->pREGS->STAT & UART_STAT_CTS) ? UART_EVENT_CTSHI : UART_EVENT_CTSLO));
|
||
|
}
|
||
|
|
||
|
if (flags & UART_INT_BREAK) {
|
||
|
pUART->pREGS->STAT = UART_INT_BREAK | UART_INT_FRMERR;
|
||
|
_UART_InvokeCB(pUART, UART_EV_EVENT,
|
||
|
(void *) ((pUART->pREGS->STAT & UART_STAT_BREAK) ? UART_EVENT_BREAK : UART_EVENT_NOBREAK));
|
||
|
}
|
||
|
|
||
|
if (flags & UART_INT_START) {
|
||
|
pUART->pREGS->STAT = UART_INT_START;
|
||
|
_UART_InvokeCB(pUART, UART_RX_START, &pUART->xfer[1]);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/* EXPORTED API: UART Transmit API */
|
||
|
ErrorCode_t UART_Tx(UART_HANDLE_T hUART, const void *buff, uint16_t len)
|
||
|
{
|
||
|
return _UART_Xfer((UART_DRIVER_T *) hUART, (void *) buff, len, 0);
|
||
|
}
|
||
|
|
||
|
/* EXPORTED API: UART Receive API */
|
||
|
ErrorCode_t UART_Rx(UART_HANDLE_T hUART, void *buff, uint16_t len)
|
||
|
{
|
||
|
return _UART_Xfer((UART_DRIVER_T *) hUART, buff, len, 1);
|
||
|
}
|
||
|
|
||
|
/* EXPORTED API: Flush the TX buffer */
|
||
|
void UART_WaitTX(UART_HANDLE_T hUART)
|
||
|
{
|
||
|
while (!_UART_HandleXfer(hUART, 0)) {}
|
||
|
}
|
||
|
|
||
|
/* EXPORTED API: Fetch the data from UART into RX buffer */
|
||
|
void UART_WaitRX(UART_HANDLE_T hUART)
|
||
|
{
|
||
|
UART_REGS_T *pREGS = ((UART_DRIVER_T *) hUART)->pREGS;
|
||
|
/* See if the data needs to be discarded */
|
||
|
if (_UART_HandleXfer(hUART, 1) == 2) {
|
||
|
volatile uint32_t dummy;
|
||
|
while ((pREGS->STAT & UART_INT_RXRDY) || !(pREGS->STAT & UART_STAT_RXIDLE)) {
|
||
|
dummy = pREGS->RXDAT;
|
||
|
}
|
||
|
}
|
||
|
while (!_UART_HandleXfer(hUART, 1)) {}
|
||
|
}
|
||
|
|
||
|
/* EXPORTED API: Function to Get the firmware Version */
|
||
|
uint32_t UART_GetDriverVersion(void)
|
||
|
{
|
||
|
return UART_DRIVER_VERSION;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Table of the addresses of all the UART ROM APIs
|
||
|
* @note This table of function pointers is the API interface.
|
||
|
*/
|
||
|
const ROM_UART_API_T uartrom_api = {
|
||
|
UART_GetMemSize,
|
||
|
UART_CalculateBaud,
|
||
|
UART_Init,
|
||
|
UART_Configure,
|
||
|
UART_SetControl,
|
||
|
UART_RegisterCB,
|
||
|
UART_Handler,
|
||
|
UART_Tx,
|
||
|
UART_Rx,
|
||
|
UART_WaitTX,
|
||
|
UART_WaitRX,
|
||
|
UART_GetDriverVersion,
|
||
|
};
|