/**
 * \file    drv_uart.c
 * \brief   MCU UART driver
 *
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-03-05
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-03-05  Original Creation
 * 
 */

#include "arch.h"
#include "libc.h"
#include "drv_interrupt.h"
#include "drv_uart.h"
#include "drv_reg_intf.h"
#include "reg_def_uart.h"
#include "sync.h"
#include "drv_chip.h"

#if SYS_FREERTOS_ENABLED
extern QueueHandle_t xUartRxQueue;
#endif

#ifndef SYSTEM_CLOCK_FREQ_FOR_UART
#define SYSTEM_CLOCK_FREQ_FOR_UART              33177600UL
#endif

#define BAUDRATE_DIV_CONST      (4)

char g_uart_char_LF = '\n';
char g_uart_char_CR = '\r';

u32_t g_uart_addr_offset_map[DRV_UART_ID_MAX] = 
{
    0,
    0x100
};

#if 0  /* modified by James Gan - 2019-05-28 */
volatile DRV_UART_ID_t g_default_std_uart = DRV_UART_ID_1;
volatile DRV_UART_ID_t g_default_second_uart = DRV_UART_ID_0;
#else
volatile DRV_UART_ID_t g_default_std_uart = DRV_UART_ID_0;
volatile DRV_UART_ID_t g_default_second_uart = DRV_UART_ID_1;
#endif /* #if 1 */

// UART RX Queue item size 17 bytes, Length(1Byte) + Data(16Bytes)
UART_RX_DATA_t g_uart_rx_data[DRV_UART_ID_MAX] = 
{
    {DRV_UART_ID_0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
    {DRV_UART_ID_1, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
};

#if UART_INTR_ENABLED
/**
 * The UART interrupt service
 *
 * \see
 */
void drv_uart_isr(u32_t arg)
{
    arg = (arg == IPIC_CFG_INTR_IDX_UART_INT) ? DRV_UART_ID_0 : DRV_UART_ID_1;

    g_uart_rx_data[arg].ucLength = 0;

    if (DRV_UART_ID_0 == arg)
    {
	    while (DRV_REG_GET(UART_LSR_REG) & UART_LSR_REG_DR_FLDSET)
        {
	    	g_uart_rx_data[arg].ucData[g_uart_rx_data[arg].ucLength++] = (u8_t)DRV_REG_GET(UART_PBR_REG);
            if (g_uart_rx_data[arg].ucLength == UART_RX_FIFO_SIZE)
                break;
        }
    }
    else {
        while (DRV_REG_GET(SEC_UART_LSR_REG) & SEC_UART_LSR_REG_DR_FLDSET)
        {
        	g_uart_rx_data[arg].ucData[g_uart_rx_data[arg].ucLength++] = (u8_t)DRV_REG_GET(SEC_UART_PBR_REG);
			if (g_uart_rx_data[arg].ucLength == UART_RX_FIFO_SIZE)
				break;
        }
    }
#if (!SYS_FREERTOS_ENABLED)
    int len = g_uart_rx_data[arg].ucLength;
    int msq_sent_cnt = 0;
    while (len > 0)
    {
        if (len >= 3)
        {
            msq_push_msg(arg + SAL_MSQ_UART, 0x7,
                        g_uart_rx_data[arg].ucData[msq_sent_cnt],
                        g_uart_rx_data[arg].ucData[msq_sent_cnt + 1],
                        g_uart_rx_data[arg].ucData[msq_sent_cnt + 2]);
            msq_sent_cnt += 3;
            len -= 3;
        }
        else if (len == 2)
        {
            msq_push_msg(arg + SAL_MSQ_UART, 0x3, 
                g_uart_rx_data[arg].ucData[msq_sent_cnt],
                g_uart_rx_data[arg].ucData[msq_sent_cnt+1],
                0);
            len -= 2;
        }
        else
        {
            msq_push_msg(arg + SAL_MSQ_UART, 0x1,
                g_uart_rx_data[arg].ucData[msq_sent_cnt],
                0,
                0);
            len--;
        }
    }
#else /* SYS_FREERTOS_ENABLED  */
    if (xUartRxQueue)
    {
        // UART RX Queue item size 17 bytes, Length(1Byte) + Data(16Bytes)
        xQueueSendFromISR(xUartRxQueue, (void *)&g_uart_rx_data[arg], NULL);
    }
#endif /* SYS_FREERTOS_ENABLED */
}
#endif /* UART_INTR_ENABLED */


void drv_uart_common_init(DRV_UART_ID_t uart_id)
{
    volatile u32_t val, baud;
    //clear fifo
    drv_uart_common_fifo_clear(uart_id);
    // Configure Flow control, Parity, Stop, Data bits
    val = DRV_REG_GET(UART_LCR_REG+g_uart_addr_offset_map[uart_id]);
    SAL_FIELD_SET(val,UART_LCR_REG,FCTL_EN,FALSE);
    SAL_FIELD_SET(val,UART_LCR_REG,PEN,FALSE);
    SAL_FIELD_SET(val,UART_LCR_REG,DLS,DRV_UART_DATA_BITS_8);
    //DRV_REG_SET(UART_LCR_REG+g_uart_addr_offset_map[uart_id],val);

    // Configure Baud rate
    SAL_FIELD_SET(val,UART_LCR_REG,DLAB,TRUE);
    DRV_REG_SET(UART_LCR_REG+g_uart_addr_offset_map[uart_id],val);
    baud = drv_chip_freq_to_baudrate_get() / (BAUDRATE_DIV_CONST * DRV_UART_DEF_BAUDRATE);
    DRV_REG_SET(UART_DLH_REG+g_uart_addr_offset_map[uart_id], (baud >> 8) & 0xFF);
    DRV_REG_SET(UART_DLL_REG+g_uart_addr_offset_map[uart_id], baud & 0xFF);

    SAL_FIELD_SET(val,UART_LCR_REG,DLAB,FALSE);
    DRV_REG_SET(UART_LCR_REG+g_uart_addr_offset_map[uart_id],val);

#if UART_INTR_ENABLED
    // Disable interrupt when uart init
    DRV_REG_SET(UART_IER_REG+g_uart_addr_offset_map[uart_id], 0);
    // clear FIFO
    while (DRV_REG_GET(UART_LSR_REG+g_uart_addr_offset_map[uart_id]) & UART_LSR_REG_DR_FLDSET)
    {
    	val = DRV_REG_GET(UART_PBR_REG+g_uart_addr_offset_map[uart_id]);
        //drv_uart_common_puthex32(uart_id, val);
    }
    drv_intr_ext_set(IPIC_CFG_INTR_IDX_UART_INT+uart_id, TRUE, IPIC_INTR_PRI_4+uart_id, drv_uart_isr);
#endif /* UART_INTR_ENABLED */
}

void drv_uart_customize_init(DRV_UART_ID_t uart_id,u32_t baud_set)
{
    volatile u32_t val, baud;
    //clear fifo
    drv_uart_common_fifo_clear(uart_id);
    // Configure Flow control, Parity, Stop, Data bits
    val = DRV_REG_GET(UART_LCR_REG+g_uart_addr_offset_map[uart_id]);
    SAL_FIELD_SET(val,UART_LCR_REG,FCTL_EN,FALSE);
    SAL_FIELD_SET(val,UART_LCR_REG,PEN,FALSE);
    SAL_FIELD_SET(val,UART_LCR_REG,DLS,DRV_UART_DATA_BITS_8);
    //DRV_REG_SET(UART_LCR_REG+g_uart_addr_offset_map[uart_id],val);

    // Configure Baud rate
    SAL_FIELD_SET(val,UART_LCR_REG,DLAB,TRUE);
    DRV_REG_SET(UART_LCR_REG+g_uart_addr_offset_map[uart_id],val);
    baud = drv_chip_freq_to_baudrate_get() / (BAUDRATE_DIV_CONST * baud_set);
    DRV_REG_SET(UART_DLH_REG+g_uart_addr_offset_map[uart_id], (baud >> 8) & 0xFF);
    DRV_REG_SET(UART_DLL_REG+g_uart_addr_offset_map[uart_id], baud & 0xFF);

    SAL_FIELD_SET(val,UART_LCR_REG,DLAB,FALSE);
    DRV_REG_SET(UART_LCR_REG+g_uart_addr_offset_map[uart_id],val);

#if UART_INTR_ENABLED
    // Disable interrupt when uart init
    DRV_REG_SET(UART_IER_REG+g_uart_addr_offset_map[uart_id], 0);
    // clear FIFO
    while (DRV_REG_GET(UART_LSR_REG+g_uart_addr_offset_map[uart_id]) & UART_LSR_REG_DR_FLDSET)
    {
    	val = DRV_REG_GET(UART_PBR_REG+g_uart_addr_offset_map[uart_id]);
        //drv_uart_common_puthex32(uart_id, val);
    }
    drv_intr_ext_set(IPIC_CFG_INTR_IDX_UART_INT+uart_id, TRUE, IPIC_INTR_PRI_4+uart_id, drv_uart_isr);
#endif /* UART_INTR_ENABLED */
}

void drv_uart_common_fifo_clear(DRV_UART_ID_t uart_id)
{
    u8_t i, val;
    for (i = 0; i < UART_RX_FIFO_SIZE; i++)
    {
        drv_uart_common_getbyte(uart_id, &val);
    }
}


void drv_uart_default_set(DRV_UART_ID_t uart_id)
{
    g_default_std_uart = uart_id;
    if (uart_id == DRV_UART_ID_1)
    {
        g_default_second_uart = DRV_UART_ID_0;
    }
    else {
        g_default_second_uart = DRV_UART_ID_1;
    }
}

DRV_UART_ID_t drv_uart_default_get()
{
    return g_default_std_uart;
}

DRV_UART_ID_t drv_uart_second_get()
{
    return g_default_second_uart;
}

void drv_uart_common_baud_rate_set(DRV_UART_ID_t uart_id, u32_t baudrate)
{
    volatile u32_t val, baud;

    sync_enter_critical();

    drv_uart_common_fifo_clear(uart_id);

    // Configure Flow control, Parity, Stop, Data bits
    val = DRV_REG_GET(UART_LCR_REG+g_uart_addr_offset_map[uart_id]);
    SAL_FIELD_SET(val,UART_LCR_REG,DLAB,TRUE);
    DRV_REG_SET(UART_LCR_REG+g_uart_addr_offset_map[uart_id],val);
    baud = drv_chip_freq_to_baudrate_get() / (BAUDRATE_DIV_CONST * baudrate);
    DRV_REG_SET(UART_DLH_REG+g_uart_addr_offset_map[uart_id], (baud >> 8) & 0xFF);
    DRV_REG_SET(UART_DLL_REG+g_uart_addr_offset_map[uart_id], baud & 0xFF);

    SAL_FIELD_SET(val,UART_LCR_REG,DLAB,FALSE);
    DRV_REG_SET(UART_LCR_REG+g_uart_addr_offset_map[uart_id],val);

    sync_exit_critical();
}

u32_t drv_uart_common_baud_rate_get(DRV_UART_ID_t uart_id)
{
    volatile u32_t val, baud;

    // Configure Flow control, Parity, Stop, Data bits
    val = DRV_REG_GET(UART_LCR_REG+g_uart_addr_offset_map[uart_id]);
    SAL_FIELD_SET(val,UART_LCR_REG,DLAB,TRUE);
    DRV_REG_SET(UART_LCR_REG+g_uart_addr_offset_map[uart_id],val);
    baud = ((DRV_REG_GET(UART_DLH_REG+g_uart_addr_offset_map[uart_id]) & 0xFF) << 8) + (DRV_REG_GET(UART_DLL_REG+g_uart_addr_offset_map[uart_id]) & 0xFF);

    SAL_FIELD_SET(val,UART_LCR_REG,DLAB,FALSE);
    DRV_REG_SET(UART_LCR_REG+g_uart_addr_offset_map[uart_id],val);

    return drv_chip_freq_to_baudrate_get() / (BAUDRATE_DIV_CONST * baud);
}


u8_t drv_uart_common_getbyte(DRV_UART_ID_t uart_id, u8_t *c)
{
    if (DRV_REG_GET(UART_LSR_REG+g_uart_addr_offset_map[uart_id]) & UART_LSR_REG_DR_FLDSET)
    {
        *c = DRV_REG_GET(UART_PBR_REG+g_uart_addr_offset_map[uart_id]);
        return 1;
    }
    return 0;
}


u8_t drv_uart_common_waitbyte(DRV_UART_ID_t uart_id)
{
    u8_t rcv;

    while (0 == drv_uart_common_getbyte(uart_id, &rcv));

    return rcv;
}


void drv_uart_common_putbyte(DRV_UART_ID_t uart_id, u8_t c)
{
    sync_enter_critical();

    while(!(DRV_REG_GET(UART_LSR_REG+g_uart_addr_offset_map[uart_id]) & UART_LSR_REG_THRE_FLDSET));
    DRV_REG_SET(UART_THR_REG+g_uart_addr_offset_map[uart_id],c);

    sync_exit_critical();
}

int drv_uart_common_putchar (DRV_UART_ID_t uart_id, char c)
{
    sync_enter_critical();

	if (c == UART_LF)
    {
        while(!(DRV_REG_GET(UART_LSR_REG+g_uart_addr_offset_map[uart_id]) & UART_LSR_REG_THRE_FLDSET));
        DRV_REG_SET(UART_THR_REG+g_uart_addr_offset_map[uart_id],UART_CR);
    }
    while(!(DRV_REG_GET(UART_LSR_REG+g_uart_addr_offset_map[uart_id]) & UART_LSR_REG_THRE_FLDSET));
    DRV_REG_SET(UART_THR_REG+g_uart_addr_offset_map[uart_id],c);

    sync_exit_critical();

    return(1);
}

int putchar(int c)
{
    sync_enter_critical();

    if (drv_uart_default_get())
    {
        if (c == UART_LF)
        {
            while(!(DRV_REG_GET(SEC_UART_LSR_REG) & SEC_UART_LSR_REG_THRE_FLDSET));
            DRV_REG_SET(SEC_UART_THR_REG,UART_CR);
        }
        while(!(DRV_REG_GET(SEC_UART_LSR_REG) & SEC_UART_LSR_REG_THRE_FLDSET));
        DRV_REG_SET(SEC_UART_THR_REG,c);
    }
    else {
    	if (c == UART_LF)
        {
            while(!(DRV_REG_GET(UART_LSR_REG) & UART_LSR_REG_THRE_FLDSET));
            DRV_REG_SET(UART_THR_REG,UART_CR);
        }
        while(!(DRV_REG_GET(UART_LSR_REG) & UART_LSR_REG_THRE_FLDSET));
        DRV_REG_SET(UART_THR_REG,c);
    }

    sync_exit_critical();


	return (1);
}

void drv_uart_common_putstr(DRV_UART_ID_t uart_id, const char *ptr)
{
    while (*ptr)
    {
        drv_uart_common_putchar(uart_id, *ptr++);
    }
}


void drv_uart_common_puts(DRV_UART_ID_t uart_id, const char *ptr)
{
    while (*ptr)
	{
		drv_uart_common_putchar(uart_id, *ptr++);
	}
    drv_uart_common_putchar(uart_id, UART_LF);
}

void drv_uart_common_puthex64(DRV_UART_ID_t uart_id, u64_t val)
{
	drv_uart_common_puthex32(uart_id, val >> 32);
    drv_uart_common_puthex32(uart_id, val);
}

void drv_uart_common_puthex32(DRV_UART_ID_t uart_id, u32_t val)
{
	drv_uart_common_puthex16(uart_id, val >> 16);
    drv_uart_common_puthex16(uart_id, val);
}

void drv_uart_common_puthex16(DRV_UART_ID_t uart_id, u16_t val)
{
	drv_uart_common_puthex8(uart_id, val >> 8);
    drv_uart_common_puthex8(uart_id, val);
}

void drv_uart_common_puthex8(DRV_UART_ID_t uart_id, u8_t val)
{
	drv_uart_common_puthex4(uart_id, val >> 4);
    drv_uart_common_puthex4(uart_id, val);
}

void drv_uart_common_puthex4(DRV_UART_ID_t uart_id, u8_t val)
{
    u8_t c = val & 0xf;
    drv_uart_common_putchar(uart_id, c + (c > 9 ? ('A' - 10) : '0'));
}

void drv_uart_common_putdec(DRV_UART_ID_t uart_id, u32_t v)
{
    unsigned long res0 = 0;
    unsigned long i0 = 0;

    if (!v) {
    	drv_uart_common_putchar(uart_id, '0');
        return;
    }

    sync_enter_critical();
    for (; i0 < 8 && v; ++i0) {
        res0 = (res0 << 4) | v % 10;
        v /= 10;
    }

    if (v) {
        unsigned long res1 = 0;
        unsigned long i1 = 0;
        for (; i1 < 2 && v; ++i1) {
            res1 = (res1 << 4) | v % 10;
            v /= 10;
        }
        while (i1--) {
        	drv_uart_common_putchar(uart_id, (res1 & 0xf) + '0');
            res1 >>= 4;
        }
    }
    while (i0--) {
    	drv_uart_common_putchar(uart_id, (res0 & 0xf) + '0');
        res0 >>= 4;
    }
    sync_exit_critical();
}

void drv_uart_common_putdouble(DRV_UART_ID_t uart_id, double v)
{
    union mydouble_u
	{
        double d;
        u64_t u64;
    } *u;

    sync_enter_critical();
    u = (union mydouble_u *)&v;

    if (u->u64 & (1ULL << 63)) {
        drv_uart_common_putchar(uart_id, '-');
        u->u64 &= ~(1ULL << 63);
    }

    // put whole part
    drv_uart_common_putdec(uart_id, (unsigned long)u->d);

    drv_uart_common_putchar(uart_id, '.');

    double frac = u->d - (unsigned long)u->d;

    //default prec is 6
    frac *= 1000000;
    if (frac < 10)
    {
        drv_uart_common_putstr(uart_id, "00000");
    }
    else if (frac < 100)
    {
        drv_uart_common_putstr(uart_id, "0000");
    }
    else if (frac < 1000)
    {
        drv_uart_common_putstr(uart_id, "000");
    }
    else if (frac < 10000)
    {
        drv_uart_common_putstr(uart_id, "00");
    }
    else if (frac < 100000)
    {
        drv_uart_common_putchar(uart_id, '0');
    }
    drv_uart_common_putdec(uart_id, (unsigned long)frac);
    sync_exit_critical();
}


void drv_uart_common_puthex(DRV_UART_ID_t uart_id, u8_t *pval, int len, bool_t with_addr)
{
    sync_enter_critical();
    while(len > 0) {
        drv_uart_common_putbyte(uart_id, ' ');
        if (with_addr)
        {
            drv_uart_common_puthex32(uart_id, (u32_t)pval);
            drv_uart_common_putstr(uart_id, ": ");
        }
        int size;
        if (len > 16)
            size = 16;
        else
            size = len;

        for(int i = 0; i < size; i++) {
            drv_uart_common_puthex8(uart_id, *(u8_t volatile *)(pval));
            drv_uart_common_putbyte(uart_id, ' ');
            pval++;
        }
        drv_uart_common_putchar(uart_id, UART_LF);
        len -= size;
    }
    sync_exit_critical();
}

#if UART1_DMA_ENABLED
u32_t g_uart1_dma_next_offset = 0;
static void drv_uart1_dma_handler(u32_t arg)
{
    UART_RX_DATA_t rx_data;
    
    drv_dma1_intr_en_set(FALSE);

    rx_data.ucId = drv_uart_second_get();
    
    if (drv_dma1_dst_addr_get() == g_uart1_dma_next_offset)
    {
        rx_data.ucLength = UART_RX_FIFO_SIZE;
        if ((u32_t)&(g_uart_rx_data[rx_data.ucId].ucData[0]) == g_uart1_dma_next_offset)
        {
            memcpy((void *)&(rx_data.ucData[0]), 
                (const void *)&(g_uart_rx_data[rx_data.ucId].ucData[0]), 
                UART_RX_FIFO_SIZE);
        }
        else {
            memcpy((void *)&(rx_data.ucData[0]), 
                (const void *)g_uart1_dma_next_offset, 
                ((u32_t)&(g_uart_rx_data[rx_data.ucId].ucData[UART_RX_FIFO_SIZE-1]) - g_uart1_dma_next_offset));
            memcpy((void *)&(rx_data.ucData[((u32_t)&(g_uart_rx_data[rx_data.ucId].ucData[UART_RX_FIFO_SIZE-1]) - g_uart1_dma_next_offset)]), 
                (const void *)&(g_uart_rx_data[rx_data.ucId].ucData[0]), 
                (g_uart1_dma_next_offset - (u32_t)&(g_uart_rx_data[rx_data.ucId].ucData[0])));
        }
    }
    else if (drv_dma1_dst_addr_get() > g_uart1_dma_next_offset) 
    {
        rx_data.ucLength = (drv_dma1_dst_addr_get() - g_uart1_dma_next_offset);
        memcpy((void *)&(rx_data.ucData[0]), (const void *)g_uart1_dma_next_offset, rx_data.ucLength);
    }
    else {
        rx_data.ucLength = UART_RX_FIFO_SIZE - (g_uart1_dma_next_offset - drv_dma1_dst_addr_get());
        memcpy((void *)&(rx_data.ucData[0]), 
            (const void *)g_uart1_dma_next_offset, 
            ((u32_t)&(g_uart_rx_data[rx_data.ucId].ucData[UART_RX_FIFO_SIZE-1]) - g_uart1_dma_next_offset));
        memcpy((void *)&(rx_data.ucData[((u32_t)&(g_uart_rx_data[rx_data.ucId].ucData[UART_RX_FIFO_SIZE-1]) - g_uart1_dma_next_offset)]), 
            (const void *)&(g_uart_rx_data[rx_data.ucId].ucData[0]), 
            (drv_dma1_dst_addr_get() - (u32_t)&(g_uart_rx_data[rx_data.ucId].ucData[0])));
    }
#if (!SYS_FREERTOS_ENABLED)
    int msq_sent_cnt = 0;
    int len = rx_data.ucLength;
    while (len > 0)
    {
        if (len >= 3)
        {
            msq_push_msg(SAL_MSQ_UART1, 0x7, 
                        rx_data.ucData[msq_sent_cnt],
                        rx_data.ucData[msq_sent_cnt+1],
                        rx_data.ucData[msq_sent_cnt+2]);
            msq_sent_cnt += 3;
            len -= 3;
        }
        else if (len == 2)
        {
            msq_push_msg(SAL_MSQ_UART1, 0x3, 
                rx_data.ucData[msq_sent_cnt],
                rx_data.ucData[msq_sent_cnt+1],
                0);
            len -= 2;
        }
        else
        {
            msq_push_msg(SAL_MSQ_UART1, 0x1, 
                rx_data.ucData[msq_sent_cnt],
                0,
                0);
            len--;
        }
    }
#else /* SYS_FREERTOS_ENABLED  */
    if (xUartRxQueue)
    {
        // UART RX Queue item size 17 bytes, Length(1Byte) + Data(16Bytes)
        xQueueSendFromISR(xUartRxQueue, (void *)&rx_data, NULL);
    }
#endif /* SYS_FREERTOS_ENABLED */
    g_uart1_dma_next_offset = drv_dma1_dst_addr_get();
    drv_dma1_intr_en_set(TRUE);
}

void drv_uart1_dma_en_set(bool_t en)
{
    DRV_UART_ID_t uartId = drv_uart_second_get();
    if (uartId)
    {
        if (en)
        {
            drv_intr_ext_set(IPIC_CFG_INTR_IDX_SEC_UART_INT, FALSE, IPIC_INTR_PRI_5, NULL);
            g_uart1_dma_next_offset = (u32_t)&(g_uart_rx_data[uartId].ucData[0]);
            drv_dma1_memcpy((void *)&(g_uart_rx_data[uartId].ucData[0]), 
                (const void *)(SEC_UART_PBR_REG), 
                UART_RX_FIFO_SIZE, DRV_DMA_MODE_SRC_ADDR_HOLD, TRUE, drv_uart1_dma_handler);
        }
        else {
            drv_dma1_stop();
            drv_intr_ext_set(IPIC_CFG_INTR_IDX_SEC_UART_INT, TRUE, IPIC_INTR_PRI_5, drv_uart_isr);
        }
    }
    else {
        if (en)
        {
            drv_intr_ext_set(IPIC_CFG_INTR_IDX_UART_INT, FALSE, IPIC_INTR_PRI_4, NULL);
            g_uart1_dma_next_offset = (u32_t)&(g_uart_rx_data[uartId].ucData[0]);
            drv_dma1_memcpy((void *)&(g_uart_rx_data[uartId].ucData[0]), 
                (const void *)(UART_PBR_REG), 
                UART_RX_FIFO_SIZE, DRV_DMA_MODE_SRC_ADDR_HOLD, TRUE, drv_uart1_dma_handler);
        }
        else {
            drv_dma1_stop();
            drv_intr_ext_set(IPIC_CFG_INTR_IDX_UART_INT, TRUE, IPIC_INTR_PRI_4, drv_uart_isr);
        }
    }
}
#endif /* UART1_DMA_ENABLED */


