in hw/mcu/nxp/src/ext/nxp-kinetis-sdk/drivers/fsl_lpuart.c [1440:1665]
void LPUART_TransferHandleIRQ(LPUART_Type *base, lpuart_handle_t *handle)
{
assert(NULL != handle);
uint8_t count;
uint8_t tempCount;
uint32_t status = LPUART_GetStatusFlags(base);
uint32_t enabledInterrupts = LPUART_GetEnabledInterrupts(base);
uint16_t tpmRxRingBufferHead;
uint32_t tpmData;
/* If RX overrun. */
if ((uint32_t)kLPUART_RxOverrunFlag == ((uint32_t)kLPUART_RxOverrunFlag & status))
{
/* Clear overrun flag, otherwise the RX does not work. */
base->STAT = ((base->STAT & 0x3FE00000U) | LPUART_STAT_OR_MASK);
/* Trigger callback. */
if (NULL != (handle->callback))
{
handle->callback(base, handle, kStatus_LPUART_RxHardwareOverrun, handle->userData);
}
}
/* If IDLE flag is set and the IDLE interrupt is enabled. */
if ((0U != ((uint32_t)kLPUART_IdleLineFlag & status)) &&
(0U != ((uint32_t)kLPUART_IdleLineInterruptEnable & enabledInterrupts)))
{
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
count = ((uint8_t)((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT));
while ((0U != handle->rxDataSize) && (0U != count))
{
tempCount = (uint8_t)MIN(handle->rxDataSize, count);
/* Using non block API to read the data from the registers. */
LPUART_ReadNonBlocking(base, handle->rxData, tempCount);
handle->rxData += tempCount;
handle->rxDataSize -= tempCount;
count -= tempCount;
/* If rxDataSize is 0, disable idle line interrupt.*/
if (0U == (handle->rxDataSize))
{
handle->rxState = (uint8_t)kLPUART_RxIdle;
LPUART_DisableInterrupts(
base, (uint32_t)kLPUART_RxDataRegFullInterruptEnable | (uint32_t)kLPUART_RxOverrunInterruptEnable);
if (NULL != handle->callback)
{
handle->callback(base, handle, kStatus_LPUART_RxIdle, handle->userData);
}
}
}
#endif
/* Clear IDLE flag.*/
base->STAT |= LPUART_STAT_IDLE_MASK;
/* If rxDataSize is 0, disable idle line interrupt.*/
if (0U != (handle->rxDataSize))
{
LPUART_DisableInterrupts(base, (uint32_t)kLPUART_IdleLineInterruptEnable);
}
/* If callback is not NULL and rxDataSize is not 0. */
if ((0U != handle->rxDataSize) && (NULL != handle->callback))
{
handle->callback(base, handle, kStatus_LPUART_IdleLineDetected, handle->userData);
}
}
/* Receive data register full */
if ((0U != ((uint32_t)kLPUART_RxDataRegFullFlag & status)) &&
(0U != ((uint32_t)kLPUART_RxDataRegFullInterruptEnable & enabledInterrupts)))
{
/* Get the size that can be stored into buffer for this interrupt. */
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
count = ((uint8_t)((base->WATER & LPUART_WATER_RXCOUNT_MASK) >> LPUART_WATER_RXCOUNT_SHIFT));
#else
count = 1;
#endif
/* If handle->rxDataSize is not 0, first save data to handle->rxData. */
while ((0U != handle->rxDataSize) && (0U != count))
{
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
tempCount = (uint8_t)MIN(handle->rxDataSize, count);
#else
tempCount = 1;
#endif
/* Using non block API to read the data from the registers. */
LPUART_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 (0U == handle->rxDataSize)
{
handle->rxState = (uint8_t)kLPUART_RxIdle;
if (NULL != handle->callback)
{
handle->callback(base, handle, kStatus_LPUART_RxIdle, handle->userData);
}
}
}
/* If use RX ring buffer, receive data to ring buffer. */
if (NULL != handle->rxRingBuffer)
{
while (0U != count--)
{
/* If RX ring buffer is full, trigger callback to notify over run. */
if (LPUART_TransferIsRxRingBufferFull(base, handle))
{
if (NULL != handle->callback)
{
handle->callback(base, handle, kStatus_LPUART_RxRingBufferOverrun, handle->userData);
}
}
/* If ring buffer is still full after callback function, the oldest data is overridden. */
if (LPUART_TransferIsRxRingBufferFull(base, handle))
{
/* Increase handle->rxRingBufferTail to make room for new data. */
if (((uint32_t)handle->rxRingBufferTail + 1U) == handle->rxRingBufferSize)
{
handle->rxRingBufferTail = 0U;
}
else
{
handle->rxRingBufferTail++;
}
}
/* Read data. */
tpmRxRingBufferHead = handle->rxRingBufferHead;
tpmData = base->DATA;
#if defined(FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT) && FSL_FEATURE_LPUART_HAS_7BIT_DATA_SUPPORT
if (handle->isSevenDataBits)
{
handle->rxRingBuffer[tpmRxRingBufferHead] = (uint8_t)(tpmData & 0x7FU);
}
else
{
handle->rxRingBuffer[tpmRxRingBufferHead] = (uint8_t)tpmData;
}
#else
handle->rxRingBuffer[tpmRxRingBufferHead] = (uint8_t)tpmData;
#endif
/* Increase handle->rxRingBufferHead. */
if (((uint32_t)handle->rxRingBufferHead + 1U) == handle->rxRingBufferSize)
{
handle->rxRingBufferHead = 0U;
}
else
{
handle->rxRingBufferHead++;
}
}
}
/* If no receive requst pending, stop RX interrupt. */
else if (0U == handle->rxDataSize)
{
LPUART_DisableInterrupts(
base, (uint32_t)kLPUART_RxDataRegFullInterruptEnable | (uint32_t)kLPUART_RxOverrunInterruptEnable);
}
else
{
}
}
/* Send data register empty and the interrupt is enabled. */
if ((0U != ((uint32_t)kLPUART_TxDataRegEmptyFlag & status)) &&
(0U != ((uint32_t)kLPUART_TxDataRegEmptyInterruptEnable & enabledInterrupts)))
{
/* Get the bytes that available at this moment. */
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
count = (uint8_t)FSL_FEATURE_LPUART_FIFO_SIZEn(base) -
(uint8_t)((base->WATER & LPUART_WATER_TXCOUNT_MASK) >> LPUART_WATER_TXCOUNT_SHIFT);
#else
count = 1;
#endif
while ((0U != handle->txDataSize) && (0U != count))
{
#if defined(FSL_FEATURE_LPUART_HAS_FIFO) && FSL_FEATURE_LPUART_HAS_FIFO
tempCount = (uint8_t)MIN(handle->txDataSize, count);
#else
tempCount = 1;
#endif
/* Using non block API to write the data to the registers. */
LPUART_WriteNonBlocking(base, handle->txData, tempCount);
handle->txData += tempCount;
handle->txDataSize -= tempCount;
count -= tempCount;
/* If all the data are written to data register, notify user with the callback, then TX finished. */
if (0U == handle->txDataSize)
{
/* Disable TX register empty interrupt. */
base->CTRL = (base->CTRL & ~LPUART_CTRL_TIE_MASK);
/* Enable transmission complete interrupt. */
LPUART_EnableInterrupts(base, (uint32_t)kLPUART_TransmissionCompleteInterruptEnable);
}
}
}
/* Transmission complete and the interrupt is enabled. */
if ((0U != ((uint32_t)kLPUART_TransmissionCompleteFlag & status)) &&
(0U != ((uint32_t)kLPUART_TransmissionCompleteInterruptEnable & enabledInterrupts)))
{
/* Set txState to idle only when all data has been sent out to bus. */
handle->txState = (uint8_t)kLPUART_TxIdle;
/* Disable transmission complete interrupt. */
LPUART_DisableInterrupts(base, (uint32_t)kLPUART_TransmissionCompleteInterruptEnable);
/* Trigger callback. */
if (NULL != handle->callback)
{
handle->callback(base, handle, kStatus_LPUART_TxIdle, handle->userData);
}
}
}