#include #include "gtypes.h" #include "gh_uart.h" #include "gh_debug_rct.h" #include "gd_uart.h" #include "gd_int.h" /*---------------------------------------------------------------------------*/ /* local defines */ /*---------------------------------------------------------------------------*/ #define UART_IRQ_CLEAR_ALL 0x3 /* IRQ CLR Register: rx_IRQ, rx_parity_IRQ */ #define UART_RISING_TXE_RXE 0x3 /* for UART_control register: */ /* clock edge polarity = rising, */ /* TX = enable, RX = enable */ /* UART[x]_FC_REG */ #define UART_FC_RX_ONECHAR 0x0 /* RCVR_Trigger: FIFO has 1 char */ #define UART_FC_RX_QUARTER_FULL 0x1 /* RCVR_Trigger: FIFO is one-fourth to full */ #define UART_FC_RX_HALF_FULL 0x2 /* RCVR_Trigger: FIFO is half to full */ #define UART_FC_RX_2_TO_FULL 0x3 /* RCVR_Trigger: FIFO is 2 char to full */ #define UART_FC_TX_EMPTY 0x0 /* TX_Empty_Trigger: FIFO is empty */ #define UART_FC_TX_2_IN_FIFO 0x1 /* TX_Empty_Trigger: FIFO has 2 char */ #define UART_FC_TX_QUATER_IN_FIFO 0x2 /* TX_Empty_Trigger: FIFO is one-fourth to full */ #define UART_FC_TX_HALF_IN_FIFO 0x3 /* TX_Empty_Trigger: FIFO is half to full */ /* UART[x]_II_REG */ #define UART_II_MODEM_STATUS_CHANGED 0x0 #define UART_II_NO_INT_PENDING 0x1 #define UART_II_THR_EMPTY 0x2 #define UART_II_RCV_DATA_AVAIL 0x4 #define UART_II_RCV_STATUS 0x6 #define UART_II_CHAR_TIMEOUT 0xc #define MAX_UART_CNT (3) /*---------------------------------------------------------------------------*/ /* local data types */ /*---------------------------------------------------------------------------*/ struct gk_uart { u8 index; }; /*---------------------------------------------------------------------------*/ /* local data */ /*---------------------------------------------------------------------------*/ static struct gk_uart uart[MAX_UART_CNT] = { {0},{1},{2} }; static GD_HANDLE intHandle[MAX_UART_CNT]; static struct rt_serial_device serial[MAX_UART_CNT]; /*---------------------------------------------------------------------------*/ /* local functions */ /*---------------------------------------------------------------------------*/ static void uartSetBaudrate(U32 index, U32 baudRate) { U32 brdi; GH_PLL_set_SCALER_UART(0x01); brdi = (48000000/2) * 10 / baudRate / 16; if (brdi % 10 >= 5) brdi = (brdi / 10) + 1; else brdi = (brdi / 10); GH_UART_set_LCR_dlab(index, 1); GH_UART_set_DLL_BaudDivint_L(index, brdi & 0xff); GH_UART_set_DLH_BaudDivint_H(index, (brdi >> 8) & 0xff); GH_UART_set_LCR_dlab(index, 0); } static void uartSetDataBits(U32 index, U32 dataBits) { U32 data_bits = dataBits; // 0 = use 5 data bits // 1 = use 6 data bits // 2 = use 7 data bits // 3 = use 8 data bits //data_bits -= GD_UART_5_DATATBITS; if(GH_UART_get_LCR_cls(index) != data_bits) { GH_UART_set_LCR_cls(index, data_bits); } } static void uartSetStopBits(U32 index, U32 stopBits) { // 0 = use 1 stop bit // 1 = use 2 stop bits if(GH_UART_get_LCR_stop(index) != stopBits) { GH_UART_set_LCR_stop(index, stopBits); } } static void uartSetParity(U32 index, U32 parity) { switch(parity) { case GD_UART_NO_PARITY: if(GH_UART_get_LCR_pen(index)) { GH_UART_set_LCR_pen(index, 0); } break; case GD_UART_ODD_PARITY: if(!GH_UART_get_LCR_pen(index)) { GH_UART_set_LCR_pen(index, 1); } if(GH_UART_get_LCR_eps(index)) { GH_UART_set_LCR_eps(index, 0); } break; case GD_UART_EVEN_PARITY: if(!GH_UART_get_LCR_pen(index)) { GH_UART_set_LCR_pen(index, 1); } if(!GH_UART_get_LCR_eps(index)) { GH_UART_set_LCR_eps(index, 1); } break; default: break; } } static void uartSetFlowControl(U32 index, U32 flowCtrl) { if(index == 0) { // In UART0, only the Loopback bit is used and flow control is not supported. // In UART1, all the bits are used. if((flowCtrl == 0) || (flowCtrl == 0x10)) { if(GH_UART_get_MCR(index) != flowCtrl) { GH_UART_set_MCR(index, flowCtrl); } } return; } if(GH_UART_get_MCR(index) != flowCtrl) { GH_UART_set_MCR(index, flowCtrl); } } static void uartISR(void) { U8 interruptID; interruptID = GH_UART_get_IIR_interrupt_id(0); switch (interruptID) { case UART_II_MODEM_STATUS_CHANGED: case UART_II_NO_INT_PENDING: break; case UART_II_THR_EMPTY: rt_hw_serial_isr(&serial[0], RT_SERIAL_EVENT_TX_DONE); break; case UART_II_RCV_DATA_AVAIL: case UART_II_RCV_STATUS: rt_hw_serial_isr(&serial[0], RT_SERIAL_EVENT_RX_IND); break; case UART_II_CHAR_TIMEOUT: GH_UART_get_RBR_Data(0); rt_hw_serial_isr(&serial[0], RT_SERIAL_EVENT_RX_TIMEOUT); break; default: break; } } static void uartISR1(void) { U8 interruptID; interruptID = GH_UART_get_IIR_interrupt_id(1); switch (interruptID) { case UART_II_MODEM_STATUS_CHANGED: case UART_II_NO_INT_PENDING: break; case UART_II_THR_EMPTY: rt_hw_serial_isr(&serial[1], RT_SERIAL_EVENT_TX_DONE); break; case UART_II_RCV_DATA_AVAIL: case UART_II_RCV_STATUS: rt_hw_serial_isr(&serial[1], RT_SERIAL_EVENT_RX_IND); break; case UART_II_CHAR_TIMEOUT: GH_UART_get_RBR_Data(1); rt_hw_serial_isr(&serial[1], RT_SERIAL_EVENT_RX_TIMEOUT); break; default: break; } } static void uartISR2(void) { U8 interruptID; interruptID = GH_UART_get_IIR_interrupt_id(2); switch (interruptID) { case UART_II_MODEM_STATUS_CHANGED: case UART_II_NO_INT_PENDING: break; case UART_II_THR_EMPTY: rt_hw_serial_isr(&serial[2], RT_SERIAL_EVENT_TX_DONE); break; case UART_II_RCV_DATA_AVAIL: case UART_II_RCV_STATUS: rt_hw_serial_isr(&serial[2], RT_SERIAL_EVENT_RX_IND); break; case UART_II_CHAR_TIMEOUT: GH_UART_get_RBR_Data(2); rt_hw_serial_isr(&serial[2], RT_SERIAL_EVENT_RX_TIMEOUT); break; default: break; } } static GERR uartSetIntMode(U8 channel) { GD_UART_STATE_MACHINE_S* uart_handle_ptr = NULL; GD_INT_OPEN_PARAMS_S intParams; GERR ret = GD_OK; intParams.sensitivity = GD_INT_LEVEL_HIGH; //hhl note: check this value. intParams.active = GD_INT_INVERT_IRQ; intParams.priority = GD_INT_MID_PRIORITY; if(channel == 0) { intParams.type = (S8)GD_INT_UART_IRQ; intParams.isrFct.lowPrio = uartISR; ret = GD_INT_Open(&intParams, &intHandle[0]); } else if(channel == 1) { intParams.type = (S8)GD_INT_UART1_IRQ; intParams.isrFct.lowPrio = uartISR1; ret = GD_INT_Open(&intParams, &intHandle[1]); } else { intParams.type = (S8)GD_INT_UART2_IRQ; intParams.isrFct.lowPrio = uartISR2; ret = GD_INT_Open(&intParams, &intHandle[2]); } return ret; } /** * UART device in RT-Thread */ static rt_err_t gk_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) { int div; GD_UART_DATABITS_E data_mode; GD_UART_STOPBITS_E stop_mode; GD_UART_PARITY_E parity_mode; struct gk_uart *uart; RT_ASSERT(serial != RT_NULL); RT_ASSERT(cfg != RT_NULL); uart = (struct gk_uart *)serial->parent.user_data; switch (cfg->data_bits) { case DATA_BITS_8: data_mode = GD_UART_8_DATATBITS; break; case DATA_BITS_7: data_mode = GD_UART_7_DATATBITS; break; case DATA_BITS_6: data_mode = GD_UART_6_DATATBITS; break; case DATA_BITS_5: data_mode = GD_UART_5_DATATBITS; break; default: data_mode = GD_UART_8_DATATBITS; break; } switch (cfg->stop_bits) { case STOP_BITS_2: stop_mode = GD_UART_20_STOPBITS;//UART_STOP_BIT2; break; case STOP_BITS_1: default: stop_mode = GD_UART_10_STOPBITS; break; } switch (cfg->parity) { case PARITY_ODD: parity_mode = GD_UART_ODD_PARITY; break; case PARITY_EVEN: parity_mode = GD_UART_EVEN_PARITY; break; case PARITY_NONE: default: parity_mode = GD_UART_NO_PARITY; break; } uartSetBaudrate(uart->index,cfg->baud_rate); uartSetDataBits(uart->index, data_mode); uartSetParity(uart->index, parity_mode); uartSetStopBits(uart->index, stop_mode); uartSetFlowControl(uart->index,0); return RT_EOK; } #define RT_DEVICE_CTRL_GET_CONFIG 0xFF static rt_err_t gk_uart_control(struct rt_serial_device *serial, int cmd, void *arg) { struct gk_uart* uart; RT_ASSERT(serial != RT_NULL); uart = (struct gk_uart *)serial->parent.user_data; switch (cmd) { case RT_DEVICE_CTRL_CLR_INT: /* disable rx irq */ GD_INT_Enable(&intHandle[uart->index],0); GH_UART_set_IER_erbfi(uart->index, 0); break; case RT_DEVICE_CTRL_SET_INT: /* enable rx irq */ GH_UART_set_FCR_FIFO_Enable(uart->index, 1); GH_UART_set_FCR_RCVR_Trigger(uart->index, UART_FC_RX_ONECHAR); GH_UART_set_FCR_TX_Empty_Trigger(uart->index, UART_FC_TX_EMPTY); GH_UART_set_FCR_XMIT_FIFO_Reset(uart->index, 1); GH_UART_set_FCR_RCVR_FIFO_Reset(uart->index, 1); GH_UART_set_IER_etbei(uart->index, 0); //Turn off THRE interrupt uartSetIntMode(uart->index); GD_INT_Enable(&intHandle[uart->index],1); GH_UART_set_IER_erbfi(uart->index,1); GH_UART_set_IER_elsi(uart->index,1); break; case RT_DEVICE_CTRL_GET_CONFIG: if(!arg) { rt_kprintf("%s,line=%d,param is NULL!\n",__FUNCTION__,__LINE__); return RT_ERROR; } *((struct serial_configure *)arg) = serial->config; break; default: break; } return RT_EOK; } static int gk_uart_putc(struct rt_serial_device *serial, char c) { struct gk_uart *uart = serial->parent.user_data; unsigned int ret; ret = GH_UART_get_LSR_temt(uart->index); if(serial->parent.open_flag & RT_DEVICE_FLAG_INT_TX){ GH_UART_set_THR_Data(uart->index, c); if (GH_UART_get_IER_etbei(uart->index) == 0) { GH_UART_set_IER_etbei(uart->index, 1); //Turn on THRE interrupt } return 1; } else { while(!GH_UART_get_LSR_temt(uart->index)); GH_UART_set_THR_Data(uart->index, c); return 1; } } static int gk_uart_getc(struct rt_serial_device *serial) { struct gk_uart *uart = serial->parent.user_data; if(!GH_UART_get_LSR_dr(uart->index)) return -1; return GH_UART_get_RBR_Data(uart->index); } static const struct rt_uart_ops gk_uart_ops = { gk_uart_configure, gk_uart_control, gk_uart_putc, gk_uart_getc, }; /** * This function will handle init uart */ void rt_hw_uart_init(void) { struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; int i; char devname[6]; for(i=0; i