01_SDK/modules/hal/panchip/panplat/pan1070/bsp/peripheral/src/pan_hal_uart.c
@@ -7,81 +7,91 @@
* @note
* Copyright (C) 2023 Panchip Technology Corp. All rights reserved.
*****************************************************************************/
#include "pan_hal.h"
#if (BLE_EN == 1)
#define PAN_HAL_BLE_IRQ_SPLIT_CALLBACK      1
#endif
UART_HandleTypeDef UART_Handle_Array[2] =
    {
        {.pUartx = UART0,
         .initObj = {0},
         .interruptObj = {0},
         .pTxBuffPtr = NULL,
         .txXferSize = 0,
         .txXferCount = 0,
         .pRxBuffPtr = NULL,
         .rxXferSize = 0,
         .rxXferCount = 0,
         .IRQn = UART0_IRQn,
         .rxIntCallback = NULL,
         .txIntCallback = NULL,
         .dmaSrc = DMAC_Peripheral_UART0_Rx,
         .dmaDst = DMAC_Peripheral_UART0_Tx,
         .errorCode = 0},
        {.pUartx = UART1,
         .initObj = {0},
         .interruptObj = {0},
         .pTxBuffPtr = NULL,
         .txXferSize = 0,
         .txXferCount = 0,
         .pRxBuffPtr = NULL,
         .rxXferSize = 0,
         .rxXferCount = 0,
         .IRQn = UART1_IRQn,
         .rxIntCallback = NULL,
         .txIntCallback = NULL,
         .dmaSrc = DMAC_Peripheral_UART1_Rx,
         .dmaDst = DMAC_Peripheral_UART1_Tx,
         .errorCode = 0}};
void HAL_DelayMs(uint32_t t)
HAL_UART_HandleTypeDef UART_Handle_Array[PAN_HAL_UART_INST_COUNT] =
{
    for (uint32_t i = 0; i < t; i++)
    {
        SYS_delay_10nop(0x1080);
        .pUartx = UART0,
        .initObj = {0},
        .interruptObj =
        {
            .txTrigLevel = HAL_UART_TX_FIFO_HALF_FULL,
            .rxTrigLevel = HAL_UART_RX_FIFO_HALF_FULL,
            .IrqPriority = 2,
            .IRQn = UART0_IRQn,
        },
        .pTxBuffPtr = NULL,
        .txXferSize = 0,
        .txXferCount = 0,
        .pRxBuffPtr = NULL,
        .rxXferSize = 0,
        .rxXferCount = 0,
        .isTxBusy = false,
        .isRxBusy = false,
        .dmaSrc = DMAC_Peripheral_UART0_Rx,
        .dmaDst = DMAC_Peripheral_UART0_Tx,
    },
    {
        .pUartx = UART1,
        .initObj = {0},
        .interruptObj =
        {
            .txTrigLevel = HAL_UART_TX_FIFO_HALF_FULL,
            .rxTrigLevel = HAL_UART_RX_FIFO_HALF_FULL,
            .IrqPriority = 2,
            .IRQn = UART1_IRQn,
        },
        .pTxBuffPtr = NULL,
        .txXferSize = 0,
        .txXferCount = 0,
        .pRxBuffPtr = NULL,
        .rxXferSize = 0,
        .rxXferCount = 0,
        .isTxBusy = false,
        .isRxBusy = false,
        .dmaSrc = DMAC_Peripheral_UART1_Rx,
        .dmaDst = DMAC_Peripheral_UART1_Tx,
    }
}
};
bool HAL_UART_Init(UART_HandleTypeDef *pUart)
HAL_Status HAL_UART_Init(HAL_UART_HandleTypeDef *pUart)
{
    if (pUart == NULL)
    {
        return HAL_ERROR;
    }
    uint32_t tmpreg = 0x00;
    uint32_t integerdivider = 0x00;
    uint32_t fractionaldivider = 0x00;
    uint64_t apbclock = 0x00;
   if(pUart->pUartx == UART0)
   {
      CLK_APB1PeriphClockCmd(CLK_APB1Periph_UART0, ENABLE);
   }
   else if(pUart->pUartx == UART1)
   {
      CLK_APB2PeriphClockCmd(CLK_APB2Periph_UART1, ENABLE);
   }
    if(pUart->pUartx == UART0)
    {
        CLK_APB1PeriphClockCmd(CLK_APB1Periph_UART0, ENABLE);
    }
    else if(pUart->pUartx == UART1)
    {
        CLK_APB2PeriphClockCmd(CLK_APB2Periph_UART1, ENABLE);
    }
    /*---------------------------- UART BRR Configuration -----------------------*/
    /* Configure the UART Baud Rate */
    apbclock = CLK_GetPeripheralFreq((void *)pUart->pUartx);
    /*unlock to enable write & read divisor register*/
    /* Unlock to enable write & read divisor register */
    pUart->pUartx->LCR |= UART_LCR_DLAB_Msk;
    /* Determine the integer part baud_rate_divisor =  PCLK*100 / (16*required_baud_rate)*/
    /* Determine the integer part baud_rate_divisor =  PCLK*100 / (16*required_baud_rate) */
    integerdivider = ((25 * apbclock) / (4 * (pUart->initObj.baudRate)));
    // Too high baudrate (too small divider) would cause DLL/DLH be all 0 which means UART disabled,
    // thus return false if this happens.
    if (integerdivider < 100)
        return false;
        return HAL_ERROR;
    tmpreg = (integerdivider / 100);
    pUart->pUartx->RBR_THR_DLL = tmpreg & 0xFF;
@@ -101,239 +111,621 @@
    pUart->pUartx->LCR = tmpreg;
    /*-------------------------------enable fifo----------------------------------*/
    pUart->pUartx->SCR |= UART_FCR_FIFOE_Msk;
    pUart->pUartx->IIR_FCR = pUart->pUartx->SCR;
    UART_EnableFifo(pUart->pUartx);
    return true;
    return HAL_OK;
}
void HAL_UART_SendData(UART_HandleTypeDef *pUart, uint8_t *pbuf, size_t size)
HAL_Status HAL_UART_SendData(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t size, uint32_t timeout)
{
    pUart->pTxBuffPtr = pbuf;
    if (pUart->isTxBusy)
    {
        return HAL_BUSY;
    }
    if ((pUart == NULL) || (pBuf == NULL) || (size == 0U))
    {
        return HAL_ERROR;
    }
    uint32_t timeout_tick = HAL_TimeConvMsToTick(timeout);
    uint32_t uptime_ref = HAL_TimeGetCurrTick();
    pUart->isTxBusy = true;
    pUart->pTxBuffPtr = pBuf;
    pUart->txXferSize = size;
    pUart->txXferCount = 0;
    while (pUart->txXferCount < pUart->txXferSize)
    {
        UART_SendData(pUart->pUartx, pUart->pTxBuffPtr[pUart->txXferCount++]);
        // Wait until Transmitter Shift Register and Tx FIFO are both empty
        while (!(UART_GetLineStatus(pUart->pUartx) & UART_LSR_TEMT_Msk))
            ;
        {
            if (timeout_tick != HAL_TIME_FOREVER)
            {
                if (HAL_TimeGetCurrTick() - uptime_ref >= timeout_tick)
                {
                    pUart->isTxBusy = false;
                    return HAL_TIMEOUT;
                }
            }
        }
        // Put a byte to Tx FIFO
        UART_SendData(pUart->pUartx, pUart->pTxBuffPtr[pUart->txXferCount++]);
    }
    pUart->isTxBusy = false;
    return HAL_OK;
}
void HAL_UART_ReceiveData(UART_HandleTypeDef *pUart, uint8_t *pbuf, size_t size, uint32_t timeout)
HAL_Status HAL_UART_ReceiveData(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t size, uint32_t timeout)
{
    UART_SetRxTrigger(pUart->pUartx, UART_RX_FIFO_HALF_FULL);
    if (pUart->isRxBusy)
    {
        return HAL_BUSY;
    }
    pUart->pRxBuffPtr = pbuf;
    if ((pUart == NULL) || (pBuf == NULL) || (size == 0U))
    {
        return HAL_ERROR;
    }
    uint32_t timeout_tick = HAL_TimeConvMsToTick(timeout);
    uint32_t uptime_ref = HAL_TimeGetCurrTick();
    pUart->isRxBusy = true;
    pUart->pRxBuffPtr = pBuf;
    pUart->rxXferSize = size;
    pUart->rxXferCount = 0;
    while (pUart->rxXferCount < pUart->rxXferSize)
    {
        while ((UART_GetLineStatus(pUart->pUartx) & UART_LSR_DR_Msk))
        // Check if there is at least one byte in Rx Data Register or Rx FIFO
        if (UART_GetLineStatus(pUart->pUartx) & UART_LSR_DR_Msk)
        {
            // Get a byte from Rx FIFO
            pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx);
        }
        if (timeout_tick != HAL_TIME_FOREVER)
        {
            if (HAL_TimeGetCurrTick() - uptime_ref >= timeout_tick)
            {
                pUart->isRxBusy = false;
                return HAL_TIMEOUT;
            }
        }
    }
    pUart->isRxBusy = false;
    return HAL_OK;
}
#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
#include "pan_ble_stack.h"
void ble_irq_split_callback(void)
{
    HAL_UART_HandleTypeDef *pUart;
    for (size_t i = 0; i < PAN_HAL_UART_INST_COUNT; i++)
    {
        pUart = &UART_Handle_Array[i];
        if (pUart->isRxBusy)
        {
            __disable_irq(); // To avoid swiching to the possible higher priority UART ISR
            if (pUart->interruptObj.continuousRxMode)
            {
                while (UART_GetRxFifoLevel(pUart->pUartx) > 1)
                {
                    if (pUart->rxXferCount < pUart->rxXferSize)
                    {
                        pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx);
                    }
                    else
                    {
                        // Set UART pending irq manually to trigger uart rx continuous buff full error callback
                        NVIC_SetPendingIRQ(pUart->interruptObj.IRQn);
                        break;
                    }
                }
            }
            else
            {
                while (!UART_IsRxFifoEmpty(pUart->pUartx))
                {
                    if (pUart->rxXferCount < pUart->rxXferSize)
                    {
                        pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx);
                    }
                    else
                    {
                        break;
                    }
                }
                if (pUart->rxXferCount == pUart->rxXferSize)
                {
                    // Set UART pending irq manually to trigger uart rx finish callback
                    NVIC_SetPendingIRQ(pUart->interruptObj.IRQn);
                }
            }
            __enable_irq();
        }
    }
}
#endif // PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
void HAL_UART_SendData_INT(UART_HandleTypeDef *pUart, uint8_t *pbuf, size_t size, UART_CallbackFunc callback)
HAL_Status HAL_UART_Init_INT(HAL_UART_HandleTypeDef *pUart)
{
    pUart->pTxBuffPtr = pbuf;
    pUart->txXferSize = size;
    pUart->txXferCount = 0;
    pUart->txIntCallback = callback;
    UART_SetTxTrigger(pUart->pUartx, UART_TX_FIFO_EMPTY);
    if (pUart == NULL)
    {
        return HAL_ERROR;
    }
    pUart->interruptObj.switchFlag = ENABLE;
    pUart->interruptObj.interruptMode = HAL_UART_INT_THR_EMPTY;
    HAL_UART_Init_INT(pUart);
    NVIC_EnableIRQ(pUart->IRQn);
}
#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
    pan_misc_register_app_irq_handler_cb(ble_irq_split_callback);
#endif // PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
void HAL_UART_ReceiveData_INT(UART_HandleTypeDef *pUart, uint8_t *pbuf, size_t size,uint32_t timeout,UART_CallbackFunc callback)
{
    pUart->pRxBuffPtr = pbuf;
    pUart->rxXferSize = size;
    pUart->rxXferCount = 0;
    pUart->rxIntCallback = callback;
   UART_SetRxTrigger(pUart->pUartx, UART_RX_FIFO_TWO_LESS_THAN_FULL);
    pUart->interruptObj.switchFlag = ENABLE;
    pUart->interruptObj.interruptMode = HAL_UART_INT_RECV_DATA_AVL;
    HAL_UART_Init_INT(pUart);
    pUart->interruptObj.interruptMode = HAL_UART_INT_LINE_STATUS;
    HAL_UART_Init_INT(pUart);
    pUart->interruptObj.interruptMode = HAL_UART_INT_ALL;
    HAL_UART_Init_INT(pUart);
    NVIC_EnableIRQ(pUart->IRQn);
}
void HAL_UART_SendData_DMA(UART_HandleTypeDef *pUart, uint8_t *pbuf, size_t size, UART_CallbackFunc callback)
{
    pUart->interruptObj.switchFlag = ENABLE;
    pUart->interruptObj.interruptMode = HAL_UART_INT_THR_EMPTY;
    HAL_UART_Init_INT(pUart);
    pUart->pTxBuffPtr = pbuf;
    pUart->txXferSize = size;
    pUart->txXferCount = 0;
    // Flush UART FIFOs
    UART_ResetTxFifo(pUart->pUartx);
    UART_SetTxTrigger(pUart->pUartx, UART_TX_FIFO_HALF_FULL);
    UART_EnablePtime(pUart->pUartx); //Enable Programmable THRE Interrupt Mode
    uint32_t txChNum = 0xFF;
    // Initialize the DMA controller
    DMAC_Init(DMA);
    NVIC_EnableIRQ(DMA_IRQn);
    /* Get free DMA channel */
    txChNum = DMAC_AcquireChannel(DMA);
    /* Enable DMA transfer interrupt */
    DMAC_ClrIntFlagMsk(DMA, txChNum, DMAC_FLAG_INDEX_TFR);
    DMAC_ClrIntFlagMsk(DMA, txChNum, DMAC_FLAG_INDEX_DSTTFR);
    DMAC_ClrIntFlagMsk(DMA, txChNum, DMAC_FLAG_INDEX_BLK);
    DMAC_ClrIntFlagMsk(DMA, txChNum, DMAC_FLAG_INDEX_ERR);
    dma_mem2uart_config.PeripheralDst = pUart->dmaDst;
    DMAC_Channel_Array[txChNum].ConfigTmp = dma_mem2uart_config;
    DMAC_Channel_Array[txChNum].CallbackUart = callback;
    DMAC_Channel_Array[txChNum].PeriMode = DMAC_Peri_UART;
    DMAC_Channel_Array[txChNum].pBuffPtr = (uint32_t*)pUart->pTxBuffPtr;
    DMAC_Channel_Array[txChNum].XferSize = pUart->txXferSize;
    DMAC_SetChannelConfig(DMA, txChNum, &DMAC_Channel_Array[txChNum].ConfigTmp);
    /* Condition check */
    uint32_t DataWidthInByteSrc = 1 << DMAC_Channel_Array[txChNum].ConfigTmp.DataWidthSrc;
    uint32_t BlockSize = size / DataWidthInByteSrc; // BlockSize = DataLen / DataWidthInByteSrc
    /* Start DMA Tx channel */
    DMAC_StartChannel(DMA, txChNum, pbuf, (void *)&(pUart->pUartx->RBR_THR_DLL), BlockSize);
}
void HAL_UART_ReceiveData_DMA(UART_HandleTypeDef *pUart, uint8_t *pbuf, size_t size, uint32_t timeout,UART_CallbackFunc callback)
{
    pUart->pRxBuffPtr = pbuf;
    pUart->rxXferSize = size;
    pUart->rxXferCount = 0;
    UART_ResetRxFifo(pUart->pUartx);
    UART_SetRxTrigger(pUart->pUartx, UART_RX_FIFO_HALF_FULL);
    uint32_t rxChNum = 0xFF;
    // Initialize the DMA controller
    DMAC_Init(DMA);
    NVIC_EnableIRQ(DMA_IRQn);
    rxChNum = DMAC_AcquireChannel(DMA);
    /* Enable DMA transfer interrupt */
    DMAC_ClrIntFlagMsk(DMA, rxChNum, DMAC_FLAG_INDEX_TFR);
    DMAC_ClrIntFlagMsk(DMA, rxChNum, DMAC_FLAG_INDEX_SRCTFR);
    DMAC_ClrIntFlagMsk(DMA, rxChNum, DMAC_FLAG_INDEX_BLK);
    DMAC_ClrIntFlagMsk(DMA, rxChNum, DMAC_FLAG_INDEX_ERR);
    // Set UART IRQ trigger level
    UART_SetTxTrigger(pUart->pUartx, (UART_TxTriggerDef)pUart->interruptObj.txTrigLevel);
    UART_SetRxTrigger(pUart->pUartx, (UART_RxTriggerDef)pUart->interruptObj.rxTrigLevel);
    // dma_uart2mem_config.PeripheralDst = pUart->dmaSrc;
    DMAC_Channel_Array[rxChNum].ConfigTmp = dma_uart2mem_config;
    DMAC_Channel_Array[rxChNum].ConfigTmp.PeripheralSrc = pUart->dmaSrc;
    DMAC_Channel_Array[rxChNum].CallbackUart = callback;
    DMAC_Channel_Array[rxChNum].PeriMode = DMAC_Peri_UART;
    DMAC_Channel_Array[rxChNum].pBuffPtr = (uint32_t*)pUart->pRxBuffPtr;
    DMAC_Channel_Array[rxChNum].XferSize = pUart->rxXferSize;
    DMAC_SetChannelConfig(DMA, rxChNum, &DMAC_Channel_Array[rxChNum].ConfigTmp);
    // Enable THRE Interrupt Mode
    UART_EnablePtime(pUart->pUartx);
    /* Condition check */
    uint32_t dataWidthInByteSrc = 1 <<DMAC_Channel_Array[rxChNum].ConfigTmp.DataWidthSrc;
    uint32_t blockSize = size / dataWidthInByteSrc;    //blockSize = DataLen / dataWidthInByteSrc
    /* Start DMA Rx channel */
    DMAC_StartChannel(DMA, rxChNum, (void*)&(pUart->pUartx->RBR_THR_DLL), pUart->pRxBuffPtr, blockSize);
    // Set UART IRQ Priority and enable UART IRQ
    NVIC_SetPriority(pUart->interruptObj.IRQn, pUart->interruptObj.IrqPriority);
    NVIC_EnableIRQ(pUart->interruptObj.IRQn);
    return HAL_OK;
}
void HAL_UART_Init_INT(UART_HandleTypeDef *pUart)
HAL_Status HAL_UART_SendData_INT(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t size)
{
    if (pUart->interruptObj.switchFlag == ENABLE)
    if (pUart->isTxBusy)
    {
        pUart->pUartx->IER_DLH |= ((pUart->interruptObj.interruptMode << UART_IER_ALL_IRQ_Pos) & UART_IER_ALL_IRQ_Msk);
        return HAL_BUSY;
    }
    else if (pUart->interruptObj.switchFlag == DISABLE)
    if ((pUart == NULL) || (pBuf == NULL) || (size == 0U))
    {
        pUart->pUartx->IER_DLH &= ~((pUart->interruptObj.interruptMode << UART_IER_ALL_IRQ_Pos) & UART_IER_ALL_IRQ_Msk);
        return HAL_ERROR;
    }
    pUart->isTxBusy = true;
    pUart->pTxBuffPtr = pBuf;
    pUart->txXferSize = size;
    pUart->txXferCount = 0;
    // Enable Transmit Trigger interupt to start sending
    UART_EnableIrq(pUart->pUartx, UART_IRQ_THR_EMPTY);
    return HAL_OK;
}
static void UART_HandleLineStatus(UART_HandleTypeDef *pUart)
HAL_Status HAL_UART_ReceiveData_INT(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t size)
{
    if (pUart->isRxBusy)
    {
        return HAL_BUSY;
    }
    if ((pUart == NULL) || (pBuf == NULL) || (size == 0U))
    {
        return HAL_ERROR;
    }
    pUart->isRxBusy = true;
    pUart->pRxBuffPtr = pBuf;
    pUart->rxXferSize = size;
    pUart->rxXferCount = 0;
    // Enable Data Available and Rx Line Status interrupt to start receiving
    UART_EnableIrq(pUart->pUartx, UART_IRQ_RECV_DATA_AVL);
    UART_EnableIrq(pUart->pUartx, UART_IRQ_LINE_STATUS);
    return HAL_OK;
}
HAL_Status HAL_UART_ReceiveDataContinuously_INT(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t bufSize)
{
    if (pUart->isRxBusy)
    {
        return HAL_BUSY;
    }
    if ((pUart == NULL) || (pBuf == NULL) || (bufSize == 0U))
    {
        return HAL_ERROR;
    }
    // The continuous Rx mode does not support Rx FIFO trigger level set to 1 char
    if ((UART_RxTriggerDef)pUart->interruptObj.rxTrigLevel == UART_RX_FIFO_ONE_CHAR)
    {
        return HAL_ERROR;
    }
    pUart->interruptObj.continuousRxMode = true;
    pUart->isRxBusy = true;
    pUart->pRxBuffPtr = pBuf;
    pUart->rxXferSize = bufSize;
    pUart->rxXferCount = 0;
    // Enable Data Available and Rx Line Status interrupt to start receiving
    UART_EnableIrq(pUart->pUartx, UART_IRQ_RECV_DATA_AVL);
    UART_EnableIrq(pUart->pUartx, UART_IRQ_LINE_STATUS);
    return HAL_OK;
}
HAL_Status HAL_UART_SendDataAbort_INT(HAL_UART_HandleTypeDef *pUart)
{
    if (pUart == NULL)
    {
        return HAL_ERROR;
    }
    // Disable Transmit Trigger interupt to abort sending
    UART_DisableIrq(pUart->pUartx, UART_IRQ_THR_EMPTY);
    // Flush Tx FIFO
    UART_ResetTxFifo(pUart->pUartx);
    pUart->isTxBusy = false;
    return HAL_OK;
}
HAL_Status HAL_UART_ReceiveDataAbort_INT(HAL_UART_HandleTypeDef *pUart)
{
    if (pUart == NULL)
    {
        return HAL_ERROR;
    }
    // Disable Data Available and Rx Line Status interrupt to abort receiving
    UART_DisableIrq(pUart->pUartx, UART_IRQ_RECV_DATA_AVL);
    UART_DisableIrq(pUart->pUartx, UART_IRQ_LINE_STATUS);
    // Flush Rx FIFO
    UART_ResetRxFifo(pUart->pUartx);
    pUart->isRxBusy = false;
    pUart->interruptObj.continuousRxMode = false;
    return HAL_OK;
}
HAL_Status HAL_UART_Init_DMA(HAL_UART_HandleTypeDef *pUart, HAL_UART_DmaDirOpt dmaDir, UART_CallbackFunc callback)
{
    uint32_t dmaCh;
    if ((pUart == NULL) || (callback == NULL))
    {
        return HAL_ERROR;
    }
    if (dmaDir == HAL_UART_DMA_TX)
    {
        // Configure UART Tx FIFO
        UART_ResetTxFifo(pUart->pUartx);
        UART_SetTxTrigger(pUart->pUartx, UART_TX_FIFO_HALF_FULL);
        UART_EnablePtime(pUart->pUartx); //Enable Programmable THRE Interrupt Mode
        /* Get free DMA channel */
        dmaCh = DMAC_AcquireChannel(DMA);
        if (dmaCh == DMA_INVLID_CHANNEL)
        {
            return HAL_ERROR;
        }
        pUart->txDmaCh = dmaCh;
        DMAC_Channel_Array[dmaCh].ConfigTmp = dma_mem2uart_config;
        DMAC_Channel_Array[dmaCh].ConfigTmp.PeripheralDst = pUart->dmaDst;
    }
    else if (dmaDir == HAL_UART_DMA_RX)
    {
        // Configure UART Rx FIFO
        UART_ResetRxFifo(pUart->pUartx);
        UART_SetRxTrigger(pUart->pUartx, UART_RX_FIFO_HALF_FULL);
        /* Get free DMA channel */
        dmaCh = DMAC_AcquireChannel(DMA);
        if (dmaCh == DMA_INVLID_CHANNEL)
        {
            return HAL_ERROR;
        }
        pUart->rxDmaCh = dmaCh;
        DMAC_Channel_Array[dmaCh].ConfigTmp = dma_uart2mem_config;
        DMAC_Channel_Array[dmaCh].ConfigTmp.PeripheralSrc = pUart->dmaSrc;
    }
    /* Enable DMA transfer interrupt */
    DMAC_ClrIntFlagMsk(DMA, dmaCh, DMAC_FLAG_INDEX_TFR);
//    DMAC_ClrIntFlagMsk(DMA, dmaCh, DMAC_FLAG_INDEX_ERR);
    DMAC_Channel_Array[dmaCh].periph = pUart;
    DMAC_Channel_Array[dmaCh].CallbackUart = callback;
    DMAC_Channel_Array[dmaCh].PeriMode = DMAC_Peri_UART;
    DMAC_SetChannelConfig(DMA, dmaCh, &DMAC_Channel_Array[dmaCh].ConfigTmp);
    return HAL_OK;
}
HAL_Status HAL_UART_SendData_DMA(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t size)
{
    if (pUart->isTxBusy)
    {
        return HAL_BUSY;
    }
    if ((pUart == NULL) || (pBuf == NULL) || (size == 0U))
    {
        return HAL_ERROR;
    }
    pUart->isTxBusy = true;
    DMAC_Channel_Array[pUart->txDmaCh].pBuffPtr = (uint32_t*)pBuf;
    DMAC_Channel_Array[pUart->txDmaCh].XferSize = size;
    DMAC_Channel_Array[pUart->txDmaCh].XferCount = 0;
    if (size < 1024)
    {
        DMAC_StartChannel(DMA, pUart->txDmaCh, pBuf, (void *)&(pUart->pUartx->RBR_THR_DLL), size);
    }
    else
    {
        DMAC_StartChannel(DMA, pUart->txDmaCh, pBuf, (void *)&(pUart->pUartx->RBR_THR_DLL), 1023);
    }
    return HAL_OK;
}
HAL_Status HAL_UART_ReceiveData_DMA(HAL_UART_HandleTypeDef *pUart, uint8_t *pBuf, uint16_t size)
{
    if (pUart->isRxBusy)
    {
        return HAL_BUSY;
    }
    if ((pUart == NULL) || (pBuf == NULL) || (size == 0U))
    {
        return HAL_ERROR;
    }
    pUart->isRxBusy = true;
    DMAC_Channel_Array[pUart->rxDmaCh].pBuffPtr = (uint32_t*)pBuf;
    DMAC_Channel_Array[pUart->rxDmaCh].XferSize = size;
    DMAC_Channel_Array[pUart->rxDmaCh].XferCount = 0;
    if (size < 1024)
    {
        DMAC_StartChannel(DMA, pUart->rxDmaCh, (void*)&(pUart->pUartx->RBR_THR_DLL), pBuf, size);
    }
    else
    {
        DMAC_StartChannel(DMA, pUart->rxDmaCh, (void*)&(pUart->pUartx->RBR_THR_DLL), pBuf, 1023);
    }
    return HAL_OK;
}
HAL_Status HAL_UART_SendDataAbort_DMA(HAL_UART_HandleTypeDef *pUart)
{
    if (pUart == NULL)
    {
        return HAL_ERROR;
    }
    // Stop current DMA channel
    DMAC_StopChannel(DMA, pUart->txDmaCh);
    // Flush Tx FIFO
    UART_ResetTxFifo(pUart->pUartx);
    pUart->isTxBusy = false;
    return HAL_OK;
}
HAL_Status HAL_UART_ReceiveDataAbort_DMA(HAL_UART_HandleTypeDef *pUart)
{
    if (pUart == NULL)
    {
        return HAL_ERROR;
    }
    // Stop current DMA channel
    DMAC_StopChannel(DMA, pUart->rxDmaCh);
    // Flush Rx FIFO
    UART_ResetRxFifo(pUart->pUartx);
    pUart->isRxBusy = false;
    return HAL_OK;
}
static void UART_HandleLineStatus(HAL_UART_HandleTypeDef *pUart)
{
    uint32_t lineStatus = UART_GetLineStatus(pUart->pUartx);
    // Filter line error
    if ((lineStatus & (UART_LINE_OVERRUN_ERR | UART_LINE_PARITY_ERR | UART_LINE_FRAME_ERR | UART_LINE_RECV_FIFO_EMPTY)) != 0x0)
    if (pUart->isRxBusy)
    {
    }
    // Handle THRE event
    if (lineStatus & UART_LINE_THRE)
    {
        if ((pUart->pUartx->IER_DLH & UART_IER_EPTI_Msk) == 0)
        // Report Rx error event
        if (pUart->interruptObj.callbackFunc != NULL)
        {
        }
        else if ((pUart->pUartx->IIR_FCR & UART_IIR_FIFOSE_Msk) != 0)
        {
        }
    }
}
static void UART_HandleModemStatus(UART_HandleTypeDef *pUart)
{
    uint32_t modemStatus = UART_GetModemStatus(pUart->pUartx);
}
static void UART_HandleReceivedData(UART_HandleTypeDef *pUart,UART_Cb_Flag_Opt flag)
{
    while (!UART_IsRxFifoEmpty(pUart->pUartx))
    {
        pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx);
    }
    if (flag == UART_CB_FLAG_RX_TIMEOUT)
    {
      if(pUart->rxXferCount >= pUart->rxXferSize)
      {
         pUart->rxXferCount = pUart->rxXferSize;
      }
        if (pUart->rxIntCallback != NULL)
        {
            pUart->rxIntCallback(flag,pUart->pRxBuffPtr,pUart->rxXferCount);
        }
        pUart->rxXferCount = 0;
    }
}
static void UART_HandleTransmittingData(UART_HandleTypeDef *pUart)
{
    while (!UART_IsTxFifoFull(pUart->pUartx))
    {
        if (pUart->txXferCount < pUart->txXferSize)
        {
            UART_SendData(pUart->pUartx, pUart->pTxBuffPtr[pUart->txXferCount++]);
        }
        else
        {
            UART_DisableIrq(pUart->pUartx, UART_IRQ_THR_EMPTY); // Disable THRE Interrupt after transmitting done
            if (pUart->txIntCallback != NULL)
            if (lineStatus & UART_LINE_PARITY_ERR)
            {
                pUart->txIntCallback(UART_CB_FLAG_TX_FINISH, pUart->pTxBuffPtr,pUart->txXferCount);
                pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_RX_ERR_PARITY, pUart->pRxBuffPtr, pUart->rxXferCount);
            }
            break;
            if (lineStatus & UART_LINE_FRAME_ERR)
            {
                pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_RX_ERR_FRAME, pUart->pRxBuffPtr, pUart->rxXferCount);
            }
            if (lineStatus & UART_LINE_OVERRUN_ERR)
            {
                pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_RX_ERR_OVERRUN, pUart->pRxBuffPtr, pUart->rxXferCount);
            }
        }
    }
    }
}
static void UART_HandleProc(UART_HandleTypeDef *pUart)
static void UART_HandleReceivedData(HAL_UART_HandleTypeDef *pUart, UART_EventDef flag)
{
    if (pUart->isRxBusy)
    {
        if (pUart->interruptObj.continuousRxMode)
        {
            if (flag != UART_EVENT_TIMEOUT)
            {
#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
                __disable_irq(); // To avoid swiching to higher priority LL IRQ
#endif
                // Read data from UART Rx FIFO and remains 1 byte in it
                while (UART_GetRxFifoLevel(pUart->pUartx) > 1)
                {
                    if (pUart->rxXferCount < pUart->rxXferSize)
                    {
                        pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx);
                    }
                    else
                    {
                        break;
                    }
                }
#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
                __enable_irq();
#endif
            }
            else
            {
#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
                __disable_irq(); // To avoid swiching to higher priority LL IRQ
#endif
                // Read all data from UART Rx FIFO due to timeout occurred
                while (!UART_IsRxFifoEmpty(pUart->pUartx))
                {
                    if (pUart->rxXferCount < pUart->rxXferSize)
                    {
                        pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx);
                    }
                    else
                    {
                        break;
                    }
                }
#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
                __enable_irq();
#endif
                // End current rx flow and trigger Continuous Rx Timeout callback if Rx FIFO is already empty
                if (UART_IsRxFifoEmpty(pUart->pUartx))
                {
                    // Disable Data Available and Rx Line Status interrupt to abort receiving
                    UART_DisableIrq(pUart->pUartx, UART_IRQ_RECV_DATA_AVL);
                    UART_DisableIrq(pUart->pUartx, UART_IRQ_LINE_STATUS);
#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
                    __disable_irq(); // To avoid swiching to higher priority LL IRQ
#endif
                    pUart->isRxBusy = false;
                    pUart->interruptObj.continuousRxMode = false;
#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
                    __enable_irq();
#endif
                    // Trigger Continuous Rx Timeout callback
                    if (pUart->interruptObj.callbackFunc != NULL)
                    {
                        pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_CONTI_RX_TIMEOUT, pUart->pRxBuffPtr, pUart->rxXferCount);
                    }
                }
            }
            if (pUart->rxXferCount >= pUart->rxXferSize)
            {
                // Trigger Rx Buffer Full callback
                if (pUart->interruptObj.callbackFunc != NULL)
                {
                    pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_CONTI_RX_BUFF_FULL, pUart->pRxBuffPtr, pUart->rxXferCount);
                }
            }
        }
        else // Normal Rx Mode (Not Continuous Rx Mode)
        {
#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
            __disable_irq(); // To avoid swiching to higher priority LL IRQ
#endif
            while (!UART_IsRxFifoEmpty(pUart->pUartx))
            {
                if (pUart->rxXferCount < pUart->rxXferSize)
                {
                    pUart->pRxBuffPtr[pUart->rxXferCount++] = UART_ReceiveData(pUart->pUartx);
                }
                else
                {
                    break;
                }
            }
#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
            __enable_irq();
#endif
            if (pUart->rxXferCount == pUart->rxXferSize)
            {
                // Disable Data Available and Rx Line Status interrupt to abort receiving
                UART_DisableIrq(pUart->pUartx, UART_IRQ_RECV_DATA_AVL);
                UART_DisableIrq(pUart->pUartx, UART_IRQ_LINE_STATUS);
#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
                __disable_irq(); // To avoid swiching to higher priority LL IRQ
#endif
                pUart->isRxBusy = false;
#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
                __enable_irq();
#endif
                // Report Rx finish event
                if (pUart->interruptObj.callbackFunc != NULL)
                {
                    pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_RX_FINISH, pUart->pRxBuffPtr, pUart->rxXferCount);
                }
            }
        }
    }
}
static void UART_HandleTransmittingData(HAL_UART_HandleTypeDef *pUart)
{
    if (pUart->isTxBusy)
    {
        while (!UART_IsTxFifoFull(pUart->pUartx))
        {
            if (pUart->txXferCount < pUart->txXferSize)
            {
                UART_SendData(pUart->pUartx, pUart->pTxBuffPtr[pUart->txXferCount++]);
            }
            else
            {
                break;
            }
        }
        if (pUart->txXferCount == pUart->txXferSize)
        {
            // Disable Transmit Trigger interupt after transmitting done
            UART_DisableIrq(pUart->pUartx, UART_IRQ_THR_EMPTY);
            pUart->isTxBusy = false;
            // Report Tx finish event
            if (pUart->interruptObj.callbackFunc != NULL)
            {
                pUart->interruptObj.callbackFunc(pUart, HAL_UART_EVT_TX_FINISH, pUart->pTxBuffPtr, pUart->txXferCount);
            }
        }
    }
}
static void UART_HandleProc(HAL_UART_HandleTypeDef *pUart)
{
    UART_EventDef event = UART_GetActiveEvent(pUart->pUartx);
@@ -343,34 +735,48 @@
        UART_HandleLineStatus(pUart);
        break;
    case UART_EVENT_DATA:
        UART_HandleReceivedData(pUart,UART_CB_FLAG_RX_FINISH);
        UART_HandleReceivedData(pUart, UART_EVENT_DATA);
        break;
    case UART_EVENT_TIMEOUT:
        UART_HandleReceivedData(pUart,UART_CB_FLAG_RX_TIMEOUT);
        UART_HandleReceivedData(pUart, UART_EVENT_TIMEOUT);
        break;
    case UART_EVENT_THR_EMPTY:
        UART_HandleTransmittingData(pUart);
        break;
    case UART_EVENT_MODEM:
        UART_HandleModemStatus(pUart);
        break;
    case UART_EVENT_NONE:
        /* Just ignore this event. */
#if PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
        UART_HandleReceivedData(pUart, UART_EVENT_NONE);
#endif // PAN_HAL_BLE_IRQ_SPLIT_CALLBACK
        break;
    default:
        break;
    }
}
void UART0_IRQHandler(void)
__WEAK void UART0_IRQHandlerOverlay(void)
{
    UART_HandleProc(&UART_Handle_Array[0]);
}
void UART1_IRQHandler(void)
__WEAK void UART1_IRQHandlerOverlay(void)
{
    UART_HandleProc(&UART_Handle_Array[1]);
}
void UART0_IRQHandler(void)
{
    PAN_IO_TIMING_TRACK_LEVEL(CONFIG_TRACK_PIN_UART0_IRQ, 1);
/*** (C) COPYRIGHT 2023 Panchip Technology Corp. ***/
    UART0_IRQHandlerOverlay();
    PAN_IO_TIMING_TRACK_LEVEL(CONFIG_TRACK_PIN_UART0_IRQ, 0);
}
void UART1_IRQHandler(void)
{
    PAN_IO_TIMING_TRACK_LEVEL(CONFIG_TRACK_PIN_UART1_IRQ, 1);
    UART1_IRQHandlerOverlay();
    PAN_IO_TIMING_TRACK_LEVEL(CONFIG_TRACK_PIN_UART1_IRQ, 0);
}