void UART_TransferHandleIRQ()

in hw/mcu/nxp/src/ext/nxp-kinetis-sdk/drivers/fsl_uart.c [1452:1746]


void UART_TransferHandleIRQ(UART_Type *base, uart_handle_t *handle)
{
    assert(handle);

    uint8_t count;
    uint8_t tempCount;
    uint32_t status = UART_GetStatusFlags(base);
    uint8_t tmpdata;

    /* If RX framing error */
    if (((uint32_t)kUART_FramingErrorFlag & status) != 0U)
    {
        /* Read base->D to clear framing error flag, otherwise the RX does not work. */
        while ((base->S1 & UART_S1_RDRF_MASK) != 0U)
        {
            (void)base->D;
        }
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
        /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */
        base->CFIFO |= UART_CFIFO_RXFLUSH_MASK;
#endif

        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 (((uint32_t)kUART_ParityErrorFlag & status) != 0U)
    {
        /* Read base->D to clear parity error flag, otherwise the RX does not work. */
        while ((base->S1 & UART_S1_RDRF_MASK) != 0U)
        {
            (void)base->D;
        }
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
        /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */
        base->CFIFO |= UART_CFIFO_RXFLUSH_MASK;
#endif

        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 (((uint32_t)kUART_RxOverrunFlag & status) != 0U)
    {
        /* Read base->D to clear overrun flag, otherwise the RX does not work. */
        while ((base->S1 & UART_S1_RDRF_MASK) != 0U)
        {
            (void)base->D;
        }
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
        /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */
        base->CFIFO |= UART_CFIFO_RXFLUSH_MASK;
#endif
        /* Trigger callback. */
        if (handle->callback != NULL)
        {
            handle->callback(base, handle, kStatus_UART_RxHardwareOverrun, handle->userData);
        }
    }

    /* If IDLE line was detected. */
    if ((((uint32_t)kUART_IdleLineFlag & status) != 0U) && ((UART_C2_ILIE_MASK & base->C2) != 0U))
    {
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
        /* If still some data in the FIFO, read out these data to user data buffer. */
        count = base->RCFIFO;
        /* If handle->rxDataSize is not 0, first save data to handle->rxData. */
        while ((count != 0U) && (handle->rxDataSize != 0U))
        {
            tempCount = (uint8_t)MIN(handle->rxDataSize, (uint32_t)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 (0U == handle->rxDataSize)
            {
                handle->rxState = (uint8_t)kUART_RxIdle;

                /* Disable RX interrupt/overrun interrupt/fram error/idle line detected interrupt */
                UART_DisableInterrupts(base, (uint32_t)kUART_RxDataRegFullInterruptEnable |
                                                 (uint32_t)kUART_RxOverrunInterruptEnable |
                                                 (uint32_t)kUART_FramingErrorInterruptEnable);

                /* Disable parity error interrupt when parity mode is enable*/
                if ((UART_C1_PE_MASK & base->C1) != 0U)
                {
                    UART_DisableInterrupts(base, (uint32_t)kUART_ParityErrorInterruptEnable);
                }

                if (handle->callback != NULL)
                {
                    handle->callback(base, handle, kStatus_UART_RxIdle, handle->userData);
                }
            }
        }
#endif
        /* To clear IDLE, read UART status S1 with IDLE set and then read D.*/
        while ((UART_S1_IDLE_MASK & base->S1) != 0U)
        {
            (void)base->D;
        }
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
        /* Flush FIFO date, otherwise FIFO pointer will be in unknown state. */
        base->CFIFO |= UART_CFIFO_RXFLUSH_MASK;
#endif
        /* If rxDataSize is 0, disable idle line interrupt.*/
        if (0U == (handle->rxDataSize))
        {
            UART_DisableInterrupts(base, (uint32_t)kUART_IdleLineInterruptEnable);
        }
        /* If callback is not NULL and rxDataSize is not 0. */
        if ((handle->callback != NULL) && (handle->rxDataSize != 0U))
        {
            handle->callback(base, handle, kStatus_UART_IdleLineDetected, handle->userData);
        }
    }
    /* Receive data register full */
    if ((((uint32_t)kUART_RxDataRegFullFlag & status) != 0U) && ((UART_C2_RIE_MASK & base->C2) != 0U))
    {
/* Get the size that can be stored into buffer for this interrupt. */
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
        count = base->RCFIFO;
#else
        count = 1;
#endif

        /* If handle->rxDataSize is not 0, first save data to handle->rxData. */
        while ((count != 0U) && (handle->rxDataSize != 0U))
        {
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
            tempCount = (uint8_t)MIN(handle->rxDataSize, (uint32_t)count);
#else
            tempCount = 1;
#endif

            /* 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 (0U == handle->rxDataSize)
            {
                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 (0U != count--)
            {
                /* 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 ((size_t)handle->rxRingBufferTail + 1U == handle->rxRingBufferSize)
                    {
                        handle->rxRingBufferTail = 0U;
                    }
                    else
                    {
                        handle->rxRingBufferTail++;
                    }
                }

                /* Read data. */
                tmpdata                                        = base->D;
                handle->rxRingBuffer[handle->rxRingBufferHead] = tmpdata;

                /* Increase handle->rxRingBufferHead. */
                if ((size_t)handle->rxRingBufferHead + 1U == handle->rxRingBufferSize)
                {
                    handle->rxRingBufferHead = 0U;
                }
                else
                {
                    handle->rxRingBufferHead++;
                }
            }
        }

        else if (0U == handle->rxDataSize)
        {
            /* Disable RX interrupt/overrun interrupt/fram error/idle line detected interrupt */
            UART_DisableInterrupts(base, (uint32_t)kUART_RxDataRegFullInterruptEnable |
                                             (uint32_t)kUART_RxOverrunInterruptEnable |
                                             (uint32_t)kUART_FramingErrorInterruptEnable);

            /* Disable parity error interrupt when parity mode is enable*/
            if ((UART_C1_PE_MASK & base->C1) != 0U)
            {
                UART_DisableInterrupts(base, (uint32_t)kUART_ParityErrorInterruptEnable);
            }
        }
        else
        {
        }
    }

    /* If framing 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)) &&
        (NULL == handle->rxRingBuffer))
    {
        UART_DisableInterrupts(
            base, (uint32_t)kUART_RxDataRegFullInterruptEnable | (uint32_t)kUART_RxOverrunInterruptEnable |
                      (uint32_t)kUART_FramingErrorInterruptEnable | (uint32_t)kUART_IdleLineInterruptEnable);

        /* Disable parity error interrupt when parity mode is enable*/
        if ((UART_C1_PE_MASK & base->C1) != 0U)
        {
            UART_DisableInterrupts(base, (uint32_t)kUART_ParityErrorInterruptEnable);
        }
    }

    /* Send data register empty and the interrupt is enabled. */
    if ((((uint32_t)kUART_TxDataRegEmptyFlag & status) != 0U) && ((base->C2 & UART_C2_TIE_MASK) != 0U))
    {
/* Get the bytes that available at this moment. */
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
        count = (uint8_t)FSL_FEATURE_UART_FIFO_SIZEn(base) - base->TCFIFO;
#else
        count = 1;
#endif

        while ((count != 0U) && (handle->txDataSize != 0U))
        {
#if defined(FSL_FEATURE_UART_HAS_FIFO) && FSL_FEATURE_UART_HAS_FIFO
            tempCount = (uint8_t)MIN(handle->txDataSize, (uint32_t)count);
#else
            tempCount = 1;
#endif

            /* 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 (0U == handle->txDataSize)
            {
                /* Disable TX register empty interrupt. */
                base->C2 = (base->C2 & ~(uint8_t)UART_C2_TIE_MASK);
                /* Enable transmission complete interrupt. */
                base->C2 = (base->C2 | (uint8_t)UART_C2_TCIE_MASK);
            }
        }
    }

    /* Transmission complete and the interrupt is enabled. */
    if ((0U != ((uint32_t)kUART_TransmissionCompleteFlag & status)) && (0U != (base->C2 & UART_C2_TCIE_MASK)))
    {
        /* Set txState to idle only when all data has been sent out to bus. */
        handle->txState = (uint8_t)kUART_TxIdle;
        /* Disable transmission complete interrupt. */
        base->C2 = (base->C2 & ~(uint8_t)UART_C2_TCIE_MASK);
        /* Trigger callback. */
        if (handle->callback != NULL)
        {
            handle->callback(base, handle, kStatus_UART_TxIdle, handle->userData);
        }
    }
}