blob: 35d56df5f93160600617886d13f586e3fb75e365 [file] [log] [blame]
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016-2020 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_uart.h"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.iuart"
#endif
/* UART transfer state. */
enum _uart_tansfer_states
{
kUART_TxIdle, /* TX idle. */
kUART_TxBusy, /* TX busy. */
kUART_RxIdle, /* RX idle. */
kUART_RxBusy, /* RX busy. */
kUART_RxFramingError, /* Rx framing error */
kUART_RxParityError /* Rx parity error */
};
/* Typedef for interrupt handler. */
typedef void (*uart_isr_t)(UART_Type *base, uart_handle_t *handle);
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief Check whether the RX ring buffer is full.
*
* @param handle UART handle pointer.
* @retval true RX ring buffer is full.
* @retval false RX ring buffer is not full.
*/
static bool UART_TransferIsRxRingBufferFull(uart_handle_t *handle);
/*!
* @brief Read RX register using non-blocking method.
*
* This function reads data from the TX register directly, upper layer must make
* sure the RX register is full or TX FIFO has data before calling this function.
*
* @param base UART peripheral base address.
* @param data Start address of the buffer to store the received data.
* @param length Size of the buffer.
*/
static void UART_ReadNonBlocking(UART_Type *base, uint8_t *data, size_t length);
/*!
* @brief Write to TX register using non-blocking method.
*
* This function writes data to the TX register directly, upper layer must make
* sure the TX register is empty or TX FIFO has empty room before calling this function.
*
* @note This function does not check whether all the data has been sent out to bus,
* so before disable TX, check kUART_TransmissionCompleteFlag to ensure the TX is
* finished.
*
* @param base UART peripheral base address.
* @param data Start address of the data to write.
* @param length Size of the buffer to be sent.
*/
static void UART_WriteNonBlocking(UART_Type *base, const uint8_t *data, size_t length);
/*******************************************************************************
* Variables
******************************************************************************/
/* Array of UART peripheral base address. */
static UART_Type *const s_uartBases[] = UART_BASE_PTRS;
/* Array of UART IRQ number. */
static const IRQn_Type s_uartIRQ[] = UART_IRQS;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Array of UART clock name. */
static const clock_ip_name_t s_uartClock[] = UART_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* UART ISR for transactional APIs. */
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
static uart_isr_t s_uartIsr = (uart_isr_t)DefaultISR;
#else
static uart_isr_t s_uartIsr;
#endif
static uart_handle_t *s_uartHandle[ARRAY_SIZE(s_uartBases)];
/*******************************************************************************
* Code
******************************************************************************/
/*!
* brief Get the UART instance from peripheral base address.
*
* param base UART peripheral base address.
* return UART instance.
*/
uint32_t UART_GetInstance(UART_Type *base)
{
uint32_t instance;
uint32_t uartArrayCount = (sizeof(s_uartBases) / sizeof(s_uartBases[0]));
/* Find the instance index from base address mappings. */
for (instance = 0; instance < uartArrayCount; instance++)
{
if (s_uartBases[instance] == base)
{
break;
}
}
assert(instance < uartArrayCount);
return instance;
}
/*!
* brief Get the length of received data in RX ring buffer.
*
* param handle UART handle pointer.
* return Length of received data in RX ring buffer.
*/
size_t UART_TransferGetRxRingBufferLength(uart_handle_t *handle)
{
assert(handle != NULL);
size_t size;
if (handle->rxRingBufferTail > handle->rxRingBufferHead)
{
size = (size_t)handle->rxRingBufferHead + handle->rxRingBufferSize - (size_t)handle->rxRingBufferTail;
}
else
{
size = (size_t)handle->rxRingBufferHead - (size_t)handle->rxRingBufferTail;
}
return size;
}
static bool UART_TransferIsRxRingBufferFull(uart_handle_t *handle)
{
assert(handle != NULL);
bool full;
if (UART_TransferGetRxRingBufferLength(handle) == (handle->rxRingBufferSize - 1U))
{
full = true;
}
else
{
full = false;
}
return full;
}
/*!
* brief Initializes an UART instance with the user configuration structure and the peripheral clock.
*
* This function configures the UART module with user-defined settings. Call the UART_GetDefaultConfig() function
* to configure the configuration structure and get the default configuration.
* The example below shows how to use this API to configure the UART.
* code
* uart_config_t uartConfig;
* uartConfig.baudRate_Bps = 115200U;
* uartConfig.parityMode = kUART_ParityDisabled;
* uartConfig.dataBitsCount = kUART_EightDataBits;
* uartConfig.stopBitCount = kUART_OneStopBit;
* uartConfig.txFifoWatermark = 2;
* uartConfig.rxFifoWatermark = 1;
* uartConfig.enableAutoBaudrate = false;
* uartConfig.enableTx = true;
* uartConfig.enableRx = true;
* UART_Init(UART1, &uartConfig, 24000000U);
* endcode
*
* param base UART peripheral base address.
* param config Pointer to a user-defined configuration structure.
* param srcClock_Hz UART clock source frequency in HZ.
* retval kStatus_Success UART initialize succeed
*/
status_t UART_Init(UART_Type *base, const uart_config_t *config, uint32_t srcClock_Hz)
{
/* Check argument */
assert(!((NULL == base) || (NULL == config) || (0U == srcClock_Hz)));
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Enable uart clock */
CLOCK_EnableClock(s_uartClock[UART_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
/* Disable UART Module. */
UART_Disable(base);
/* Reset the transmit and receive state machines, all FIFOs and register
* USR1, USR2, UBIR, UBMR, UBRC, URXD, UTXD and UTS[6-3]. */
UART_SoftwareReset(base);
/* Set UART Module Register content to default value */
base->UCR1 = 0x0;
base->UCR2 = UART_UCR2_SRST_MASK;
base->UCR3 = UART_UCR3_DSR_MASK | UART_UCR3_DCD_MASK | UART_UCR3_RI_MASK;
base->UCR4 = UART_UCR4_CTSTL(32);
base->UFCR = UART_UFCR_TXTL(2) | UART_UFCR_RXTL(1);
base->UESC = UART_UESC_ESC_CHAR(0x2B);
base->UTIM = 0x0;
base->ONEMS = 0x0;
base->UTS = UART_UTS_TXEMPTY_MASK | UART_UTS_RXEMPTY_MASK;
base->UMCR = 0x0;
/* Set UART data word length, stop bit count, parity mode and communication
* direction according to uart init struct, disable RTS hardware flow control.
*/
base->UCR2 |=
((uint32_t)UART_UCR2_WS(config->dataBitsCount) | (uint32_t)UART_UCR2_STPB(config->stopBitCount) |
(((uint32_t)(config->parityMode) << UART_UCR2_PROE_SHIFT) & (UART_UCR2_PREN_MASK | UART_UCR2_PROE_MASK)) |
(uint32_t)UART_UCR2_TXEN(config->enableTx) | (uint32_t)UART_UCR2_RXEN(config->enableRx) | UART_UCR2_IRTS_MASK);
#if (defined(FSL_FEATURE_IUART_RXDMUXSEL) && FSL_FEATURE_IUART_RXDMUXSEL)
/* For imx family device, UARTs are used in MUXED mode, so that this bit should always be set.*/
base->UCR3 |= UART_UCR3_RXDMUXSEL_MASK;
#endif /* FSL_FEATURE_IUART_RXDMUXSEL */
/* Set TX/RX fifo water mark */
UART_SetTxFifoWatermark(base, config->txFifoWatermark);
UART_SetRxFifoWatermark(base, config->rxFifoWatermark);
if (config->enableAutoBaudRate)
{
/* Start automatic baud rate detection */
UART_EnableAutoBaudRate(base, true);
}
else if (config->baudRate_Bps != 0U)
{
/* Stop automatic baud rate detection */
UART_EnableAutoBaudRate(base, false);
/* Set BaudRate according to uart initialize struct. Baud Rate = Ref Freq / (16 * (UBMR + 1)/(UBIR+1)) */
if (kStatus_Success != UART_SetBaudRate(base, config->baudRate_Bps, srcClock_Hz))
{
return kStatus_UART_BaudrateNotSupport;
}
}
else
{
/* Stop automatic baud rate detection */
UART_EnableAutoBaudRate(base, false);
}
/* Enable UART module */
UART_Enable(base);
return kStatus_Success;
}
/*!
* brief Deinitializes a UART instance.
*
* This function waits for transmit to complete, disables TX and RX, and disables the UART clock.
*
* param base UART peripheral base address.
*/
void UART_Deinit(UART_Type *base)
{
/* Wait transmit FIFO buffer and shift register empty */
while (UART_USR2_TXDC_MASK != (base->USR2 & UART_USR2_TXDC_MASK))
{
}
/* Disable UART Module */
UART_Disable(base);
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Disable uart clock */
CLOCK_DisableClock(s_uartClock[UART_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}
/*!l
* brief Gets the default configuration structure.
*
* This function initializes the UART configuration structure to a default value. The default
* values are:
* uartConfig->baudRate_Bps = 115200U;
* uartConfig->parityMode = kUART_ParityDisabled;
* uartConfig->dataBitsCount = kUART_EightDataBits;
* uartConfig->stopBitCount = kUART_OneStopBit;
* uartConfig->txFifoWatermark = 2;
* uartConfig->rxFifoWatermark = 1;
* uartConfig->enableAutoBaudrate = flase;
* uartConfig->enableTx = false;
* uartConfig->enableRx = false;
*
* param config Pointer to a configuration structure.
*/
void UART_GetDefaultConfig(uart_config_t *config)
{
assert(config != NULL);
/* Initializes the configure structure to zero. */
(void)memset(config, 0, sizeof(*config));
config->baudRate_Bps = 115200U;
config->parityMode = kUART_ParityDisabled;
config->dataBitsCount = kUART_EightDataBits;
config->stopBitCount = kUART_OneStopBit;
config->txFifoWatermark = 2;
config->rxFifoWatermark = 1;
config->enableAutoBaudRate = false;
config->enableTx = false;
config->enableRx = false;
}
/* This UART instantiation uses a slightly different baud rate calculation.
* Baud Rate = Ref Freq / (16 * (UBMR + 1)/(UBIR+1)).
* To get a baud rate, three register need to be writen, UFCR,UBMR and UBIR
* At first, find the approximately maximum divisor of src_Clock and baudRate_Bps.
* If the numerator and denominator are larger then register maximum value(0xFFFF),
* both of numerator and denominator will be divided by the same value, which
* will ensure numerator and denominator range from 0~maximum value(0xFFFF).
* Then calculate UFCR and UBIR value from numerator, and get UBMR value from denominator.
*/
/*!
* brief Sets the UART instance baud rate.
*
* This function configures the UART module baud rate. This function is used to update
* the UART module baud rate after the UART module is initialized by the UART_Init.
* code
* UART_SetBaudRate(UART1, 115200U, 20000000U);
* endcode
*
* param base UART peripheral base address.
* param baudRate_Bps UART baudrate to be set.
* param srcClock_Hz UART clock source frequency in Hz.
* retval kStatus_UART_BaudrateNotSupport Baudrate is not support in the current clock source.
* retval kStatus_Success Set baudrate succeeded.
*/
status_t UART_SetBaudRate(UART_Type *base, uint32_t baudRate_Bps, uint32_t srcClock_Hz)
{
uint32_t numerator = 0u;
uint32_t denominator = 0U;
uint32_t divisor = 0U;
uint32_t refFreqDiv = 0U;
uint32_t divider = 1U;
uint64_t baudDiff = 0U;
uint64_t tempNumerator = 0U;
uint32_t tempDenominator = 0u;
/* get the approximately maximum divisor */
numerator = srcClock_Hz;
denominator = baudRate_Bps << 4U;
divisor = 1U;
while (denominator != 0U)
{
divisor = denominator;
denominator = numerator % denominator;
numerator = divisor;
}
numerator = srcClock_Hz / divisor;
denominator = (baudRate_Bps << 4U) / divisor;
/* numerator ranges from 1 ~ 7 * 64k */
/* denominator ranges from 1 ~ 64k */
if ((numerator > (UART_UBIR_INC_MASK * 7U)) || (denominator > UART_UBIR_INC_MASK))
{
uint32_t m = (numerator - 1U) / (UART_UBIR_INC_MASK * 7U) + 1U;
uint32_t n = (denominator - 1U) / UART_UBIR_INC_MASK + 1U;
uint32_t max = m > n ? m : n;
numerator /= max;
denominator /= max;
if (0U == numerator)
{
numerator = 1U;
}
if (0U == denominator)
{
denominator = 1U;
}
}
divider = (numerator - 1U) / UART_UBIR_INC_MASK + 1U;
switch (divider)
{
case 1:
refFreqDiv = 0x05U;
break;
case 2:
refFreqDiv = 0x04U;
break;
case 3:
refFreqDiv = 0x03U;
break;
case 4:
refFreqDiv = 0x02U;
break;
case 5:
refFreqDiv = 0x01U;
break;
case 6:
refFreqDiv = 0x00U;
break;
case 7:
refFreqDiv = 0x06U;
break;
default:
refFreqDiv = 0x05U;
break;
}
/* Compare the difference between baudRate_Bps and calculated baud rate.
* Baud Rate = Ref Freq / (16 * (UBMR + 1)/(UBIR+1)).
* baudDiff = (srcClock_Hz/divider)/( 16 * ((numerator / divider)/ denominator).
*/
tempNumerator = (uint64_t)srcClock_Hz;
tempDenominator = (numerator << 4U);
divisor = 1U;
/* get the approximately maximum divisor */
while (tempDenominator != 0U)
{
divisor = tempDenominator;
tempDenominator = (uint32_t)(tempNumerator % tempDenominator);
tempNumerator = (uint64_t)divisor;
}
tempNumerator = (uint64_t)srcClock_Hz / (uint64_t)divisor;
tempDenominator = (numerator << 4U) / divisor;
baudDiff = (tempNumerator * (uint64_t)denominator) / (uint64_t)tempDenominator;
baudDiff = (baudDiff >= (uint64_t)baudRate_Bps) ? (baudDiff - (uint64_t)baudRate_Bps) :
((uint64_t)baudRate_Bps - baudDiff);
if (baudDiff < ((uint64_t)baudRate_Bps / 100UL * 3UL))
{
base->UFCR &= ~UART_UFCR_RFDIV_MASK;
base->UFCR |= UART_UFCR_RFDIV(refFreqDiv);
base->UBIR = UART_UBIR_INC(denominator - 1U);
base->UBMR = UART_UBMR_MOD(numerator / divider - 1U);
base->ONEMS = UART_ONEMS_ONEMS(srcClock_Hz / (1000U * divider));
return kStatus_Success;
}
else
{
return kStatus_UART_BaudrateNotSupport;
}
}
/*!
* brief Enables UART interrupts according to the provided mask.
*
* This function enables the UART interrupts according to the provided mask. The mask
* is a logical OR of enumeration members. See ref _uart_interrupt_enable.
* For example, to enable TX empty interrupt and RX data ready interrupt, do the following.
* code
* UART_EnableInterrupts(UART1,kUART_TxEmptyEnable | kUART_RxDataReadyEnable);
* endcode
*
* param base UART peripheral base address.
* param mask The interrupts to enable. Logical OR of ref _uart_interrupt_enable.
*/
void UART_EnableInterrupts(UART_Type *base, uint32_t mask)
{
assert((0x7F3FF73FU & mask) != 0U);
if ((0X3FU & mask) != 0U)
{
base->UCR1 |= ((mask << UART_UCR1_ADEN_SHIFT) & UART_UCR1_ADEN_MASK) |
(((mask >> 1) << UART_UCR1_TRDYEN_SHIFT) & UART_UCR1_TRDYEN_MASK) |
(((mask >> 2) << UART_UCR1_IDEN_SHIFT) & UART_UCR1_IDEN_MASK) |
(((mask >> 3) << UART_UCR1_RRDYEN_SHIFT) & UART_UCR1_RRDYEN_MASK) |
(((mask >> 4) << UART_UCR1_TXMPTYEN_SHIFT) & UART_UCR1_TXMPTYEN_MASK) |
(((mask >> 5) << UART_UCR1_RTSDEN_SHIFT) & UART_UCR1_RTSDEN_MASK);
}
if ((0X700U & mask) != 0U)
{
base->UCR2 |= (((mask >> 8) << UART_UCR2_ESCI_SHIFT) & UART_UCR2_ESCI_MASK) |
(((mask >> 9) << UART_UCR2_RTSEN_SHIFT) & UART_UCR2_RTSEN_MASK) |
(((mask >> 10) << UART_UCR2_ATEN_SHIFT) & UART_UCR2_ATEN_MASK);
}
if ((0x3FF000U & mask) != 0U)
{
base->UCR3 |= (((mask >> 12) << UART_UCR3_DTREN_SHIFT) & UART_UCR3_DTREN_MASK) |
(((mask >> 13) << UART_UCR3_PARERREN_SHIFT) & UART_UCR3_PARERREN_MASK) |
(((mask >> 14) << UART_UCR3_FRAERREN_SHIFT) & UART_UCR3_FRAERREN_MASK) |
(((mask >> 15) << UART_UCR3_DCD_SHIFT) & UART_UCR3_DCD_MASK) |
(((mask >> 16) << UART_UCR3_RI_SHIFT) & UART_UCR3_RI_MASK) |
(((mask >> 17) << UART_UCR3_RXDSEN_SHIFT) & UART_UCR3_RXDSEN_MASK) |
(((mask >> 18) << UART_UCR3_AIRINTEN_SHIFT) & UART_UCR3_AIRINTEN_MASK) |
(((mask >> 19) << UART_UCR3_AWAKEN_SHIFT) & UART_UCR3_AWAKEN_MASK) |
(((mask >> 20) << UART_UCR3_DTRDEN_SHIFT) & UART_UCR3_DTRDEN_MASK) |
(((mask >> 21) << UART_UCR3_ACIEN_SHIFT) & UART_UCR3_ACIEN_MASK);
}
if ((0x7F000000U & mask) != 0U)
{
base->UCR4 |= (((mask >> 24) << UART_UCR4_ENIRI_SHIFT) & UART_UCR4_ENIRI_MASK) |
(((mask >> 25) << UART_UCR4_WKEN_SHIFT) & UART_UCR4_WKEN_MASK) |
(((mask >> 26) << UART_UCR4_TCEN_SHIFT) & UART_UCR4_TCEN_MASK) |
(((mask >> 27) << UART_UCR4_BKEN_SHIFT) & UART_UCR4_BKEN_MASK) |
(((mask >> 28) << UART_UCR4_OREN_SHIFT) & UART_UCR4_OREN_MASK) |
(((mask >> 29) << UART_UCR4_DREN_SHIFT) & UART_UCR4_DREN_MASK) |
(((mask >> 30) << UART_UCR4_IDDMAEN_SHIFT) & UART_UCR4_IDDMAEN_MASK);
}
}
/*!
* brief Disables the UART interrupts according to the provided mask.
*
* This function disables the UART interrupts according to the provided mask. The mask
* is a logical OR of enumeration members. See ref _uart_interrupt_enable.
* For example, to disable TX empty interrupt and RX data ready interrupt do the following.
* code
* UART_EnableInterrupts(UART1,kUART_TxEmptyEnable | kUART_RxDataReadyEnable);
* endcode
*
* param base UART peripheral base address.
* param mask The interrupts to disable. Logical OR of ref _uart_interrupt_enable.
*/
void UART_DisableInterrupts(UART_Type *base, uint32_t mask)
{
assert((0x7F3FF73FU & mask) != 0U);
if ((0X3FU & mask) != 0U)
{
base->UCR1 &= ~(((mask << UART_UCR1_ADEN_SHIFT) & UART_UCR1_ADEN_MASK) |
(((mask >> 1) << UART_UCR1_TRDYEN_SHIFT) & UART_UCR1_TRDYEN_MASK) |
(((mask >> 2) << UART_UCR1_IDEN_SHIFT) & UART_UCR1_IDEN_MASK) |
(((mask >> 3) << UART_UCR1_RRDYEN_SHIFT) & UART_UCR1_RRDYEN_MASK) |
(((mask >> 4) << UART_UCR1_TXMPTYEN_SHIFT) & UART_UCR1_TXMPTYEN_MASK) |
(((mask >> 5) << UART_UCR1_RTSDEN_SHIFT) & UART_UCR1_RTSDEN_MASK));
}
if ((0X700U & mask) != 0U)
{
base->UCR2 &= ~((((mask >> 8) << UART_UCR2_ESCI_SHIFT) & UART_UCR2_ESCI_MASK) |
(((mask >> 9) << UART_UCR2_RTSEN_SHIFT) & UART_UCR2_RTSEN_MASK) |
(((mask >> 10) << UART_UCR2_ATEN_SHIFT) & UART_UCR2_ATEN_MASK));
}
if ((0x3FF000U & mask) != 0U)
{
base->UCR3 &= ~((((mask >> 12) << UART_UCR3_DTREN_SHIFT) & UART_UCR3_DTREN_MASK) |
(((mask >> 13) << UART_UCR3_PARERREN_SHIFT) & UART_UCR3_PARERREN_MASK) |
(((mask >> 14) << UART_UCR3_FRAERREN_SHIFT) & UART_UCR3_FRAERREN_MASK) |
(((mask >> 15) << UART_UCR3_DCD_SHIFT) & UART_UCR3_DCD_MASK) |
(((mask >> 16) << UART_UCR3_RI_SHIFT) & UART_UCR3_RI_MASK) |
(((mask >> 17) << UART_UCR3_RXDSEN_SHIFT) & UART_UCR3_RXDSEN_MASK) |
(((mask >> 18) << UART_UCR3_AIRINTEN_SHIFT) & UART_UCR3_AIRINTEN_MASK) |
(((mask >> 19) << UART_UCR3_AWAKEN_SHIFT) & UART_UCR3_AWAKEN_MASK) |
(((mask >> 20) << UART_UCR3_DTRDEN_SHIFT) & UART_UCR3_DTRDEN_MASK) |
(((mask >> 21) << UART_UCR3_ACIEN_SHIFT) & UART_UCR3_ACIEN_MASK));
}
if ((0x7F000000U & mask) != 0U)
{
base->UCR4 &= ~((((mask >> 24) << UART_UCR4_ENIRI_SHIFT) & UART_UCR4_ENIRI_MASK) |
(((mask >> 25) << UART_UCR4_WKEN_SHIFT) & UART_UCR4_WKEN_MASK) |
(((mask >> 26) << UART_UCR4_TCEN_SHIFT) & UART_UCR4_TCEN_MASK) |
(((mask >> 27) << UART_UCR4_BKEN_SHIFT) & UART_UCR4_BKEN_MASK) |
(((mask >> 28) << UART_UCR4_OREN_SHIFT) & UART_UCR4_OREN_MASK) |
(((mask >> 29) << UART_UCR4_DREN_SHIFT) & UART_UCR4_DREN_MASK) |
(((mask >> 30) << UART_UCR4_IDDMAEN_SHIFT) & UART_UCR4_IDDMAEN_MASK));
}
}
/*!
* brief Gets enabled UART interrupts.
*
* This function gets the enabled UART interrupts. The enabled interrupts are returned
* as the logical OR value of the enumerators ref _uart_interrupt_enable. To check
* a specific interrupt enable status, compare the return value with enumerators
* in ref _uart_interrupt_enable.
* For example, to check whether the TX empty interrupt is enabled:
* code
* uint32_t enabledInterrupts = UART_GetEnabledInterrupts(UART1);
*
* if (kUART_TxEmptyEnable & enabledInterrupts)
* {
* ...
* }
* endcode
*
* param base UART peripheral base address.
* return UART interrupt flags which are logical OR of the enumerators in ref _uart_interrupt_enable.
*/
uint32_t UART_GetEnabledInterrupts(UART_Type *base)
{
assert(base != NULL);
uint32_t temp = 0U;
/* Get enabled interrupts from UCR1 */
temp |= ((base->UCR1 & UART_UCR1_ADEN_MASK) >> UART_UCR1_ADEN_SHIFT) |
(((base->UCR1 & UART_UCR1_TRDYEN_MASK) >> UART_UCR1_TRDYEN_SHIFT) << 1) |
(((base->UCR1 & UART_UCR1_IDEN_MASK) >> UART_UCR1_IDEN_SHIFT) << 2) |
(((base->UCR1 & UART_UCR1_RRDYEN_MASK) >> UART_UCR1_RRDYEN_SHIFT) << 3) |
(((base->UCR1 & UART_UCR1_TXMPTYEN_MASK) >> UART_UCR1_TXMPTYEN_SHIFT) << 4) |
(((base->UCR1 & UART_UCR1_RTSDEN_MASK) >> UART_UCR1_RTSDEN_SHIFT) << 5);
/* Get enabled interrupts from UCR2 */
temp |= (((base->UCR2 & UART_UCR2_ESCI_MASK) >> UART_UCR2_ESCI_SHIFT) << 8) |
(((base->UCR2 & UART_UCR2_RTSEN_MASK) >> UART_UCR2_RTSEN_SHIFT) << 9) |
(((base->UCR2 & UART_UCR2_ATEN_MASK) >> UART_UCR2_ATEN_SHIFT) << 10);
/* Get enabled interrupts from UCR3 */
temp |= (((base->UCR3 & UART_UCR3_DTREN_MASK) >> UART_UCR3_DTREN_SHIFT) << 12) |
(((base->UCR3 & UART_UCR3_PARERREN_MASK) >> UART_UCR3_PARERREN_SHIFT) << 13) |
(((base->UCR3 & UART_UCR3_FRAERREN_MASK) >> UART_UCR3_FRAERREN_SHIFT) << 14) |
(((base->UCR3 & UART_UCR3_DCD_MASK) >> UART_UCR3_DCD_SHIFT) << 15) |
(((base->UCR3 & UART_UCR3_RI_MASK) >> UART_UCR3_RI_SHIFT) << 16) |
(((base->UCR3 & UART_UCR3_RXDSEN_MASK) >> UART_UCR3_RXDSEN_SHIFT) << 17) |
(((base->UCR3 & UART_UCR3_AIRINTEN_MASK) >> UART_UCR3_AIRINTEN_SHIFT) << 18) |
(((base->UCR3 & UART_UCR3_AWAKEN_MASK) >> UART_UCR3_AWAKEN_SHIFT) << 19) |
(((base->UCR3 & UART_UCR3_DTRDEN_MASK) >> UART_UCR3_DTRDEN_SHIFT) << 20) |
(((base->UCR3 & UART_UCR3_ACIEN_MASK) >> UART_UCR3_ACIEN_SHIFT) << 21);
/* Get enabled interrupts from UCR4 */
temp |= (((base->UCR4 & UART_UCR4_ENIRI_MASK) >> UART_UCR4_ENIRI_SHIFT) << 24) |
(((base->UCR4 & UART_UCR4_WKEN_MASK) >> UART_UCR4_WKEN_SHIFT) << 25) |
(((base->UCR4 & UART_UCR4_TCEN_MASK) >> UART_UCR4_TCEN_SHIFT) << 26) |
(((base->UCR4 & UART_UCR4_BKEN_MASK) >> UART_UCR4_BKEN_SHIFT) << 27) |
(((base->UCR4 & UART_UCR4_OREN_MASK) >> UART_UCR4_OREN_SHIFT) << 28) |
(((base->UCR4 & UART_UCR4_DREN_MASK) >> UART_UCR4_DREN_SHIFT) << 29) |
(((base->UCR4 & UART_UCR4_IDDMAEN_MASK) >> UART_UCR4_IDDMAEN_SHIFT) << 30);
return temp;
}
/*!
* brief This function is used to get the current status of specific
* UART status flag(including interrupt flag). The available
* status flag can be select from ref uart_status_flag_t enumeration.
*
* param base UART base pointer.
* param flag Status flag to check.
* retval current state of corresponding status flag.
*/
bool UART_GetStatusFlag(UART_Type *base, uint32_t flag)
{
volatile uint32_t *uart_reg;
uart_reg = (uint32_t *)((uint32_t)base + (flag >> 16));
return (bool)(((*uart_reg) >> (flag & 0x1FU)) & 0x1U);
}
/*!
* brief This function is used to clear the current status
* of specific UART status flag. The available status
* flag can be select from ref uart_status_flag_t enumeration.
*
* param base UART base pointer.
* param flag Status flag to clear.
*/
void UART_ClearStatusFlag(UART_Type *base, uint32_t flag)
{
volatile uint32_t *uart_reg = NULL;
uint32_t uart_mask = 0;
uart_reg = (uint32_t *)((uint32_t)base + (flag >> 16));
uart_mask = (1UL << (flag & 0x0000001FU));
*uart_reg = uart_mask;
}
void UART_EnableDMA(UART_Type *base, uint32_t dmaSource, bool enable)
{
volatile uint32_t *uart_reg = NULL;
uint32_t uart_mask = 0;
uart_reg = (uint32_t *)((uint32_t)base + (dmaSource >> 16));
uart_mask = (1UL << (dmaSource & 0x0000001FU));
if (enable)
{
*uart_reg |= uart_mask;
}
else
{
*uart_reg &= ~uart_mask;
}
}
/*!
* brief Writes to the TX register using a blocking method.
*
* This function polls the TX register, waits for the TX register to be empty or for the TX FIFO
* to have room and writes data to the TX buffer.
*
* param base UART peripheral base address.
* param data Start address of the data to write.
* param length Size of the data to write.
* retval kStatus_UART_Timeout Transmission timed out and was aborted.
* retval kStatus_Success Successfully wrote all data.
*/
status_t UART_WriteBlocking(UART_Type *base, const uint8_t *data, size_t length)
{
assert(data != NULL);
#if UART_RETRY_TIMES
uint32_t waitTimes;
#endif
while (length-- != 0U)
{
/* Wait for TX fifo valid. */
#if UART_RETRY_TIMES
waitTimes = UART_RETRY_TIMES;
while ((0U == (base->USR1 & UART_USR1_TRDY_MASK)) && (0U != --waitTimes))
#else
while (0U == (base->USR1 & UART_USR1_TRDY_MASK))
#endif
{
}
#if UART_RETRY_TIMES
if (0U == waitTimes)
{
return kStatus_UART_Timeout;
}
#endif
UART_WriteByte(base, *(data++));
}
#if UART_RETRY_TIMES
waitTimes = UART_RETRY_TIMES;
while ((0U == (base->USR2 & UART_USR2_TXDC_MASK)) && (0U != --waitTimes))
#else
while (0U == (base->USR2 & UART_USR2_TXDC_MASK))
#endif
{
}
#if UART_RETRY_TIMES
if (0U == waitTimes)
{
return kStatus_UART_Timeout;
}
#endif
return kStatus_Success;
}
/*!
* brief Read RX data register using a blocking method.
*
* This function polls the RX register, waits for the RX register to be full or for RX FIFO to
* have data, and reads data from the TX register.
*
* param base UART peripheral base address.
* param data Start address of the buffer to store the received data.
* param length Size of the buffer.
* retval kStatus_UART_RxHardwareOverrun Receiver overrun occurred while receiving data.
* retval kStatus_UART_NoiseError A noise error occurred while receiving data.
* retval kStatus_UART_FramingError A framing error occurred while receiving data.
* retval kStatus_UART_ParityError A parity error occurred while receiving data.
* retval kStatus_UART_Timeout Transmission timed out and was aborted.
* retval kStatus_Success Successfully received all data.
*/
status_t UART_ReadBlocking(UART_Type *base, uint8_t *data, size_t length)
{
assert(data != NULL);
status_t status = kStatus_Success;
#if UART_RETRY_TIMES
uint32_t waitTimes;
#endif
while (length-- != 0U)
{
#if UART_RETRY_TIMES
waitTimes = UART_RETRY_TIMES;
#endif
/* Wait for receive data in URXD register is ready */
while ((base->USR2 & UART_USR2_RDR_MASK) == 0U)
{
#if UART_RETRY_TIMES
if (--waitTimes == 0U)
{
status = kStatus_UART_Timeout;
break;
}
#endif
/* Over run check for receiving character */
if ((base->USR2 & UART_USR2_ORE_MASK) != 0U)
{
UART_ClearStatusFlag(base, (uint32_t)kUART_RxOverrunFlag);
status = kStatus_UART_RxHardwareOverrun;
break;
}
/* Parity error check for receiving character */
if ((base->USR1 & UART_USR1_PARITYERR_MASK) != 0U)
{
UART_ClearStatusFlag(base, (uint32_t)kUART_ParityErrorFlag);
status = kStatus_UART_ParityError;
}
/* Framing error check for receiving character */
if ((base->USR1 & UART_USR1_FRAMERR_MASK) != 0U)
{
UART_ClearStatusFlag(base, (uint32_t)kUART_FrameErrorFlag);
status = kStatus_UART_FramingError;
}
if (status != kStatus_Success)
{
break;
}
}
if (kStatus_Success == status)
{
/* Read data from URXD */
*(data++) = UART_ReadByte(base);
}
else
{
break;
}
}
return status;
}
static void UART_WriteNonBlocking(UART_Type *base, const uint8_t *data, size_t length)
{
assert(data != NULL);
size_t i;
/* The Non Blocking write data API assume user have ensured there is enough space in
* peripheral to write. UTXD register holds the parallel transmit data inputs. In 7-bit mode,
* D7 is ignored. In 8-bit mode, all bits are used.
*/
for (i = 0; i < length; i++)
{
base->UTXD = (uint32_t)data[i] & UART_UTXD_TX_DATA_MASK;
}
}
static void UART_ReadNonBlocking(UART_Type *base, uint8_t *data, size_t length)
{
assert(data != NULL);
size_t i;
/* The Non Blocking read data API assume user have ensured there is enough space in
* peripheral to write. The URXD holds the received character,In 7-bit mode,
* the most significant bit (MSB) is forced to 0.In 8-bit mode, all bits are active.
*/
for (i = 0; i < length; i++)
{
data[i] = (uint8_t)((base->URXD & UART_URXD_RX_DATA_MASK) >> UART_URXD_RX_DATA_SHIFT);
}
}
/*!
* brief Initializes the UART handle.
*
* This function initializes the UART handle which can be used for other UART
* transactional APIs. Usually, for a specified UART instance,
* call this API once to get the initialized handle.
*
* param base UART peripheral base address.
* param handle UART handle pointer.
* param callback The callback function.
* param userData The parameter of the callback function.
*/
void UART_TransferCreateHandle(UART_Type *base,
uart_handle_t *handle,
uart_transfer_callback_t callback,
void *userData)
{
assert(handle != NULL);
uint32_t instance;
/* Zero the handle. */
(void)memset(handle, 0, sizeof(*handle));
/* Set the TX/RX state. */
handle->rxState = (uint8_t)kUART_RxIdle;
handle->txState = (uint8_t)kUART_TxIdle;
/* Set the callback and user data. */
handle->callback = callback;
handle->userData = userData;
/* Get instance from peripheral base address. */
instance = UART_GetInstance(base);
/* Save the handle in global variables to support the double weak mechanism. */
s_uartHandle[instance] = handle;
s_uartIsr = UART_TransferHandleIRQ;
/* Enable interrupt in NVIC. */
(void)EnableIRQ(s_uartIRQ[instance]);
}
/*!
* brief Sets up the RX ring buffer.
*
* This function sets up the RX ring buffer to a specific UART handle.
*
* When the RX ring buffer is used, data received are stored into the ring buffer even when the
* user doesn't call the UART_TransferReceiveNonBlocking() API. If data is already received
* in the ring buffer, the user can get the received data from the ring buffer directly.
*
* note When using the RX ring buffer, one byte is reserved for internal use. In other
* words, if p ringBufferSize is 32, only 31 bytes are used for saving data.
*
* param base UART peripheral base address.
* param handle UART handle pointer.
* param ringBuffer Start address of the ring buffer for background receiving. Pass NULL to disable the ring buffer.
* param ringBufferSize Size of the ring buffer.
*/
void UART_TransferStartRingBuffer(UART_Type *base, uart_handle_t *handle, uint8_t *ringBuffer, size_t ringBufferSize)
{
assert(handle != NULL);
assert(ringBuffer != NULL);
/* Setup the ringbuffer address */
handle->rxRingBuffer = ringBuffer;
handle->rxRingBufferSize = ringBufferSize;
handle->rxRingBufferHead = 0U;
handle->rxRingBufferTail = 0U;
/* Enable the interrupt to accept the data when user need the ring buffer. */
UART_EnableInterrupts(base, (uint32_t)kUART_RxReadyEnable | (uint32_t)kUART_AgingTimerEnable |
(uint32_t)kUART_RxOverrunEnable | (uint32_t)kUART_ParityErrorEnable |
(uint32_t)kUART_FrameErrorEnable);
}
/*!
* brief Aborts the background transfer and uninstalls the ring buffer.
*
* This function aborts the background transfer and uninstalls the ring buffer.
*
* param base UART peripheral base address.
* param handle UART handle pointer.
*/
void UART_TransferStopRingBuffer(UART_Type *base, uart_handle_t *handle)
{
assert(handle != NULL);
if (handle->rxState == (uint8_t)kUART_RxIdle)
{
UART_DisableInterrupts(base, (uint32_t)kUART_RxReadyEnable | (uint32_t)kUART_AgingTimerEnable |
(uint32_t)kUART_RxOverrunEnable | (uint32_t)kUART_ParityErrorEnable |
(uint32_t)kUART_FrameErrorEnable);
}
handle->rxRingBuffer = NULL;
handle->rxRingBufferSize = 0U;
handle->rxRingBufferHead = 0U;
handle->rxRingBufferTail = 0U;
}
/*!
* brief Transmits a buffer of data using the interrupt method.
*
* This function sends data using an interrupt method. This is a non-blocking function, which
* returns directly without waiting for all data to be written to the TX register. When
* all data is written to the TX register in the ISR, the UART driver calls the callback
* function and passes the ref kStatus_UART_TxIdle as status parameter.
*
* note The kStatus_UART_TxIdle is passed to the upper layer when all data is written
* to the TX register. However, it does not ensure that all data is sent out. Before disabling the TX,
* check the kUART_TransmissionCompleteFlag to ensure that the TX is finished.
*
* param base UART peripheral base address.
* param handle UART handle pointer.
* param xfer UART transfer structure. See #uart_transfer_t.
* retval kStatus_Success Successfully start the data transmission.
* retval kStatus_UART_TxBusy Previous transmission still not finished; data not all written to TX register yet.
* retval kStatus_InvalidArgument Invalid argument.
*/
status_t UART_TransferSendNonBlocking(UART_Type *base, uart_handle_t *handle, uart_transfer_t *xfer)
{
assert(handle != NULL);
assert(xfer != NULL);
assert(xfer->dataSize != 0U);
assert(xfer->data != NULL);
status_t status;
/* Return error if current TX busy. */
if ((uint8_t)kUART_TxBusy == handle->txState)
{
status = kStatus_UART_TxBusy;
}
else
{
handle->txData = xfer->data;
handle->txDataSize = xfer->dataSize;
handle->txDataSizeAll = xfer->dataSize;
handle->txState = (uint8_t)kUART_TxBusy;
/* Enable transmiter interrupt. */
UART_EnableInterrupts(base, (uint32_t)kUART_TxReadyEnable);
status = kStatus_Success;
}
return status;
}
/*!
* brief Aborts the interrupt-driven data transmit.
*
* This function aborts the interrupt-driven data sending. The user can get the remainBytes to find out
* how many bytes are not sent out.
*
* param base UART peripheral base address.
* param handle UART handle pointer.
*/
void UART_TransferAbortSend(UART_Type *base, uart_handle_t *handle)
{
assert(handle != NULL);
UART_DisableInterrupts(base, (uint32_t)kUART_TxEmptyEnable);
handle->txDataSize = 0;
handle->txState = (uint8_t)kUART_TxIdle;
}
/*!
* brief Gets the number of bytes written to the UART TX register.
*
* This function gets the number of bytes written to the UART TX
* register by using the interrupt method.
*
* param base UART peripheral base address.
* param handle UART handle pointer.
* param count Send bytes count.
* retval kStatus_NoTransferInProgress No send in progress.
* retval kStatus_InvalidArgument The parameter is invalid.
* retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t UART_TransferGetSendCount(UART_Type *base, uart_handle_t *handle, uint32_t *count)
{
assert(handle != NULL);
assert(count != NULL);
if ((uint8_t)kUART_TxIdle == handle->txState)
{
return kStatus_NoTransferInProgress;
}
*count = handle->txDataSizeAll - handle->txDataSize;
return kStatus_Success;
}
/*!
* brief Receives a buffer of data using an interrupt method.
*
* This function receives data using an interrupt method. This is a non-blocking function, which
* returns without waiting for all data to be received.
* If the RX ring buffer is used and not empty, the data in the ring buffer is copied and
* the parameter p receivedBytes shows how many bytes are copied from the ring buffer.
* After copying, if the data in the ring buffer is not enough to read, the receive
* request is saved by the UART driver. When the new data arrives, the receive request
* is serviced first. When all data is received, the UART driver notifies the upper layer
* through a callback function and passes the status parameter ref kStatus_UART_RxIdle.
* For example, the upper layer needs 10 bytes but there are only 5 bytes in the ring buffer.
* The 5 bytes are copied to the xfer->data and this function returns with the
* parameter p receivedBytes set to 5. For the left 5 bytes, newly arrived data is
* saved from the xfer->data[5]. When 5 bytes are received, the UART driver notifies the upper layer.
* If the RX ring buffer is not enabled, this function enables the RX and RX interrupt
* to receive data to the xfer->data. When all data is received, the upper layer is notified.
*
* param base UART peripheral base address.
* param handle UART handle pointer.
* param xfer UART transfer structure, see #uart_transfer_t.
* param receivedBytes Bytes received from the ring buffer directly.
* retval kStatus_Success Successfully queue the transfer into transmit queue.
* retval kStatus_UART_RxBusy Previous receive request is not finished.
* retval kStatus_InvalidArgument Invalid argument.
*/
status_t UART_TransferReceiveNonBlocking(UART_Type *base,
uart_handle_t *handle,
uart_transfer_t *xfer,
size_t *receivedBytes)
{
assert(handle != NULL);
assert(xfer != NULL);
assert(xfer->data != NULL);
assert(xfer->dataSize != 0U);
uint32_t i;
status_t status;
/* How many bytes to copy from ring buffer to user memory. */
size_t bytesToCopy = 0U;
/* How many bytes to receive. */
size_t bytesToReceive;
/* How many bytes currently have received. */
size_t bytesCurrentReceived;
/* How to get data:
1. If RX ring buffer is not enabled, then save xfer->data and xfer->dataSize
to uart handle, enable interrupt to store received data to xfer->data. When
all data received, trigger callback.
2. If RX ring buffer is enabled and not empty, get data from ring buffer first.
If there are enough data in ring buffer, copy them to xfer->data and return.
If there are not enough data in ring buffer, copy all of them to xfer->data,
save the xfer->data remained empty space to uart handle, receive data
to this empty space and trigger callback when finished. */
if ((uint8_t)kUART_RxBusy == handle->rxState)
{
status = kStatus_UART_RxBusy;
}
else
{
bytesToReceive = xfer->dataSize;
bytesCurrentReceived = 0U;
/* If RX ring buffer is used. */
if (handle->rxRingBuffer != NULL)
{
/* Disable UART RX IRQ, protect ring buffer. */
UART_DisableInterrupts(base, (uint32_t)kUART_RxReadyEnable | (uint32_t)kUART_AgingTimerEnable);
/* How many bytes in RX ring buffer currently. */
bytesToCopy = UART_TransferGetRxRingBufferLength(handle);
if (bytesToCopy != 0U)
{
bytesToCopy = MIN(bytesToReceive, bytesToCopy);
bytesToReceive -= bytesToCopy;
/* Copy data from ring buffer to user memory. */
for (i = 0U; i < bytesToCopy; i++)
{
xfer->data[bytesCurrentReceived++] = handle->rxRingBuffer[handle->rxRingBufferTail];
/* Wrap to 0. Not use modulo (%) because it might be large and slow. */
if (handle->rxRingBufferTail + 1U == (uint16_t)handle->rxRingBufferSize)
{
handle->rxRingBufferTail = 0U;
}
else
{
handle->rxRingBufferTail++;
}
}
}
/* If ring buffer does not have enough data, still need to read more data. */
if (bytesToReceive != 0U)
{
/* No data in ring buffer, save the request to UART handle. */
handle->rxData = xfer->data + bytesCurrentReceived;
handle->rxDataSize = bytesToReceive;
handle->rxDataSizeAll = bytesToReceive;
handle->rxState = (uint8_t)kUART_RxBusy;
}
/* Enable UART RX IRQ if previously enabled. */
UART_EnableInterrupts(base, (uint32_t)kUART_RxReadyEnable | (uint32_t)kUART_AgingTimerEnable);
/* Call user callback since all data are received. */
if (0U == bytesToReceive)
{
if ((handle->callback) != NULL)
{
handle->callback(base, handle, kStatus_UART_RxIdle, handle->userData);
}
}
}
/* Ring buffer not used. */
else
{
handle->rxData = xfer->data + bytesCurrentReceived;
handle->rxDataSize = bytesToReceive;
handle->rxDataSizeAll = bytesToReceive;
handle->rxState = (uint8_t)kUART_RxBusy;
/* Enable RX/Rx overrun/framing error interrupt. */
UART_EnableInterrupts(base, (uint32_t)kUART_RxReadyEnable | (uint32_t)kUART_AgingTimerEnable |
(uint32_t)kUART_RxOverrunEnable | (uint32_t)kUART_ParityErrorEnable |
(uint32_t)kUART_FrameErrorEnable);
}
/* Return the how many bytes have read. */
if (receivedBytes != NULL)
{
*receivedBytes = bytesCurrentReceived;
}
status = kStatus_Success;
}
return status;
}
/*!
* brief Aborts the interrupt-driven data receiving.
*
* This function aborts the interrupt-driven data receiving. The user can get the remainBytes to know
* how many bytes are not received yet.
*
* param base UART peripheral base address.
* param handle UART handle pointer.
*/
void UART_TransferAbortReceive(UART_Type *base, uart_handle_t *handle)
{
assert(handle != NULL);
/* Only abort the receive to handle->rxData, the RX ring buffer is still working. */
if (handle->rxRingBuffer == NULL)
{
/* Disable RX interrupt. */
UART_DisableInterrupts(base, (uint32_t)kUART_RxReadyEnable | (uint32_t)kUART_AgingTimerEnable |
(uint32_t)kUART_RxOverrunEnable | (uint32_t)kUART_ParityErrorEnable |
(uint32_t)kUART_FrameErrorEnable);
}
handle->rxDataSize = 0U;
handle->rxState = (uint8_t)kUART_RxIdle;
}
/*!
* brief Gets the number of bytes that have been received.
*
* This function gets the number of bytes that have been received.
*
* param base UART peripheral base address.
* param handle UART handle pointer.
* param count Receive bytes count.
* retval kStatus_NoTransferInProgress No receive in progress.
* retval kStatus_InvalidArgument Parameter is invalid.
* retval kStatus_Success Get successfully through the parameter \p count;
*/
status_t UART_TransferGetReceiveCount(UART_Type *base, uart_handle_t *handle, uint32_t *count)
{
assert(handle != NULL);
assert(count != NULL);
if ((uint8_t)kUART_RxIdle == handle->rxState)
{
return kStatus_NoTransferInProgress;
}
if (count == NULL)
{
return kStatus_InvalidArgument;
}
*count = handle->rxDataSizeAll - handle->rxDataSize;
return kStatus_Success;
}
/*!
* brief UART IRQ handle function.
*
* This function handles the UART transmit and receive IRQ request.
*
* param base UART peripheral base address.
* param handle UART handle pointer.
*/
void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle)
{
assert(handle != NULL);
uint8_t count;
uint8_t tempCount;
/* If RX framing error */
if ((UART_USR1_FRAMERR_MASK & base->USR1) != 0U)
{
/* Write 1 to clear framing error flag */
base->USR1 |= UART_USR1_FRAMERR_MASK;
handle->rxState = (uint8_t)kUART_RxFramingError;
handle->rxDataSize = 0U;
/* Trigger callback. */
if ((handle->callback) != NULL)
{
handle->callback(base, handle, kStatus_UART_FramingError, handle->userData);
}
}
/* If RX parity error */
if ((UART_USR1_PARITYERR_MASK & base->USR1) != 0U)
{
/* Write 1 to clear parity error flag. */
base->USR1 |= UART_USR1_PARITYERR_MASK;
handle->rxState = (uint8_t)kUART_RxParityError;
handle->rxDataSize = 0U;
/* Trigger callback. */
if ((handle->callback) != NULL)
{
handle->callback(base, handle, kStatus_UART_ParityError, handle->userData);
}
}
/* If RX overrun. */
if ((UART_USR2_ORE_MASK & base->USR2) != 0U)
{
/* Write 1 to clear overrun flag. */
base->USR2 |= UART_USR2_ORE_MASK;
/* Trigger callback. */
if ((handle->callback) != NULL)
{
handle->callback(base, handle, kStatus_UART_RxHardwareOverrun, handle->userData);
}
}
/* Receive data FIFO buffer reach the trigger level */
if (((UART_USR1_RRDY_MASK & base->USR1) != 0U) && ((UART_UCR1_RRDYEN_MASK & base->UCR1) != 0U))
{
/* Get the size that stored in receive FIFO buffer for this interrupt. */
count = (uint8_t)((base->UFCR & UART_UFCR_RXTL_MASK) >> UART_UFCR_RXTL_SHIFT);
/* If count and handle->rxDataSize are not 0, first save data to handle->rxData. */
while ((count != 0U) && (handle->rxDataSize != 0U))
{
tempCount = (uint8_t)MIN(handle->rxDataSize, count);
/* Using non block API to read the data from the registers. */
UART_ReadNonBlocking(base, handle->rxData, tempCount);
handle->rxData += tempCount;
handle->rxDataSize -= tempCount;
count -= tempCount;
/* If all the data required for upper layer is ready, trigger callback. */
if (handle->rxDataSize == 0U)
{
handle->rxState = (uint8_t)kUART_RxIdle;
if ((handle->callback) != NULL)
{
handle->callback(base, handle, kStatus_UART_RxIdle, handle->userData);
}
}
}
/* If use RX ring buffer, receive data to ring buffer. */
if (handle->rxRingBuffer != NULL)
{
while (count-- != 0U)
{
/* If RX ring buffer is full, trigger callback to notify over run. */
if (UART_TransferIsRxRingBufferFull(handle))
{
if ((handle->callback) != NULL)
{
handle->callback(base, handle, kStatus_UART_RxRingBufferOverrun, handle->userData);
}
}
/* If ring buffer is still full after callback function, the oldest data is overridden. */
if (UART_TransferIsRxRingBufferFull(handle))
{
/* Increase handle->rxRingBufferTail to make room for new data. */
if (handle->rxRingBufferTail + 1U == (uint16_t)handle->rxRingBufferSize)
{
handle->rxRingBufferTail = 0U;
}
else
{
handle->rxRingBufferTail++;
}
}
/* Read data. */
handle->rxRingBuffer[handle->rxRingBufferHead] =
(uint8_t)((base->URXD & UART_URXD_RX_DATA_MASK) >> UART_URXD_RX_DATA_SHIFT);
/* Increase handle->rxRingBufferHead. */
if (handle->rxRingBufferHead + 1U == (uint16_t)handle->rxRingBufferSize)
{
handle->rxRingBufferHead = 0U;
}
else
{
handle->rxRingBufferHead++;
}
}
}
else if (handle->rxDataSize == 0U)
{
/* Disable RX interrupt/overrun interrupt/framing error interrupt */
UART_DisableInterrupts(base, (uint32_t)kUART_RxReadyEnable | (uint32_t)kUART_AgingTimerEnable |
(uint32_t)kUART_RxOverrunEnable | (uint32_t)kUART_ParityErrorEnable |
(uint32_t)kUART_FrameErrorEnable);
}
else
{
}
}
/* Receive FIFO buffer has been idle for a time of 8 characters, and FIFO data level
* is less than RxFIFO threshold level.
*/
if (((UART_USR1_AGTIM_MASK & base->USR1) != 0U) && ((UART_UCR2_ATEN_MASK & base->UCR2) != 0U))
{
/* If count and handle->rxDataSize are not 0, first save data to handle->rxData. */
while (((base->USR2 & UART_USR2_RDR_MASK) != 0U) && (handle->rxDataSize != 0U))
{
/* Read one data from the URXD registers. */
*handle->rxData = UART_ReadByte(base);
handle->rxData += 1U;
handle->rxDataSize -= 1U;
/* If all the data required for upper layer is ready, trigger callback. */
if (handle->rxDataSize == 0U)
{
handle->rxState = (uint8_t)kUART_RxIdle;
if ((handle->callback) != NULL)
{
handle->callback(base, handle, kStatus_UART_RxIdle, handle->userData);
}
}
}
/* If use RX ring buffer, receive data to ring buffer. */
if (handle->rxRingBuffer != NULL)
{
while ((base->USR2 & UART_USR2_RDR_MASK) != 0U)
{
/* If RX ring buffer is full, trigger callback to notify over run. */
if (UART_TransferIsRxRingBufferFull(handle))
{
if ((handle->callback) != NULL)
{
handle->callback(base, handle, kStatus_UART_RxRingBufferOverrun, handle->userData);
}
}
/* If ring buffer is still full after callback function, the oldest data is overridden. */
if (UART_TransferIsRxRingBufferFull(handle))
{
/* Increase handle->rxRingBufferTail to make room for new data. */
if (handle->rxRingBufferTail + 1U == (uint16_t)handle->rxRingBufferSize)
{
handle->rxRingBufferTail = 0U;
}
else
{
handle->rxRingBufferTail++;
}
}
/* Read one data from URXD register. */
handle->rxRingBuffer[handle->rxRingBufferHead] = UART_ReadByte(base);
/* Increase handle->rxRingBufferHead. */
if (handle->rxRingBufferHead + 1U == (uint16_t)handle->rxRingBufferSize)
{
handle->rxRingBufferHead = 0U;
}
else
{
handle->rxRingBufferHead++;
}
}
}
/* If ring buffer is not used and rxDataSize is 0 */
else if (handle->rxDataSize == 0U)
{
/* Disable RX interrupt/overrun interrupt/framing error interrupt */
UART_DisableInterrupts(base, (uint32_t)kUART_RxReadyEnable | (uint32_t)kUART_AgingTimerEnable |
(uint32_t)kUART_RxOverrunEnable | (uint32_t)kUART_ParityErrorEnable |
(uint32_t)kUART_FrameErrorEnable);
}
else
{
}
/* Clear aging timer flag for next interrupt */
UART_ClearStatusFlag(base, (uint32_t)kUART_AgingTimerFlag);
}
/* If frame error or parity error happened, stop the RX interrupt when use no ring buffer */
if (((handle->rxState == (uint8_t)kUART_RxFramingError) || (handle->rxState == (uint8_t)kUART_RxParityError)) &&
(handle->rxRingBuffer == NULL))
{
/* Disable Receive ready interrupt, aging timer interrupt, receive over run interrupt,
* parity error interrupt and frame error interrupt.
*/
UART_DisableInterrupts(base, (uint32_t)kUART_RxReadyEnable | (uint32_t)kUART_AgingTimerEnable |
(uint32_t)kUART_RxOverrunEnable | (uint32_t)kUART_ParityErrorEnable |
(uint32_t)kUART_FrameErrorEnable);
}
/* Send data register empty and the interrupt is enabled. */
if (((UART_USR1_TRDY_MASK & base->USR1) != 0U) && ((UART_UCR1_TRDYEN_MASK & base->UCR1) != 0U))
{
/* Get the bytes that available at this moment. */
if (0U != ((base->UFCR & UART_UFCR_TXTL_MASK) >> UART_UFCR_TXTL_SHIFT))
{
if ((UART_UTS_TXEMPTY_MASK & base->UTS) != 0U)
{
count = FSL_FEATURE_IUART_FIFO_SIZEn(base);
}
else
{
count = (uint8_t)FSL_FEATURE_IUART_FIFO_SIZEn(base) -
(uint8_t)((base->UFCR & UART_UFCR_TXTL_MASK) >> UART_UFCR_TXTL_SHIFT);
}
}
else
{
count = 1U;
}
while ((count != 0U) && (handle->txDataSize != 0U))
{
if (0U != ((base->UFCR & UART_UFCR_TXTL_MASK) >> UART_UFCR_TXTL_SHIFT))
{
tempCount = (uint8_t)MIN(handle->txDataSize, count);
}
else
{
tempCount = 1U;
}
/* Using non block API to write the data to the registers. */
UART_WriteNonBlocking(base, handle->txData, tempCount);
handle->txData += tempCount;
handle->txDataSize -= tempCount;
count -= tempCount;
/* If all the data are written to data register, TX finished. */
if (handle->txDataSize == 0U)
{
handle->txState = (uint8_t)kUART_TxIdle;
/* Disable TX FIFO buffer empty interrupt. */
UART_DisableInterrupts(base, (uint32_t)kUART_TxReadyEnable);
/* Enable TX complete interrupt. */
UART_EnableInterrupts(base, (uint32_t)kUART_TxCompleteEnable);
}
}
}
/* TX complete and the interrupt is enabled. */
if ((0U != (UART_USR2_TXDC_MASK & base->USR2)) && (0U != (UART_UCR4_TCEN_MASK & base->UCR4)) &&
(handle->txState == (uint8_t)kUART_TxIdle))
{
/* Disable TX complete interrupt. */
UART_DisableInterrupts(base, (uint32_t)kUART_TxCompleteEnable);
/* Trigger callback. */
if ((handle->callback) != NULL)
{
handle->callback(base, handle, kStatus_UART_TxIdle, handle->userData);
}
}
}
#if defined(UART1)
void UART1_DriverIRQHandler(void)
{
s_uartIsr(UART1, s_uartHandle[1]);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(UART2)
void UART2_DriverIRQHandler(void)
{
s_uartIsr(UART2, s_uartHandle[2]);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(UART3)
void UART3_DriverIRQHandler(void)
{
s_uartIsr(UART3, s_uartHandle[3]);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(UART4)
void UART4_DriverIRQHandler(void)
{
s_uartIsr(UART4, s_uartHandle[4]);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(UART5)
void UART5_DriverIRQHandler(void)
{
s_uartIsr(UART5, s_uartHandle[5]);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(UART6)
void UART6_DriverIRQHandler(void)
{
s_uartIsr(UART6, s_uartHandle[6]);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(UART7)
void UART7_DriverIRQHandler(void)
{
s_uartIsr(UART7, s_uartHandle[7]);
SDK_ISR_EXIT_BARRIER;
}
#endif
#if defined(UART8)
void UART8_DriverIRQHandler(void)
{
s_uartIsr(UART8, s_uartHandle[8]);
SDK_ISR_EXIT_BARRIER;
}
#endif