1 /*
2  * Copyright (c) 2006-2020, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2020-04-22     hqfang       First version
9  */
10 
11 #include <drv_uart.h>
12 
13 #ifdef RT_USING_SERIAL
14 
15 #if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1)
16     #error "Please define at least one BSP_USING_UARTx"
17     /* this driver can be enabled at menuconfig ->
18     Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable UART */
19 #endif
20 
21 enum
22 {
23 #ifdef BSP_USING_UART0
24     UART0_INDEX,
25 #endif
26 #ifdef BSP_USING_UART1
27     UART1_INDEX,
28 #endif
29 };
30 
31 static struct hbird_uart_config uart_config[] =
32 {
33 #ifdef BSP_USING_UART0
34     {
35         "uart0",
36         UART0,
37         SOC_INT19_IRQn,
38     },
39 #endif
40 #ifdef BSP_USING_UART1
41     {
42         "uart1",
43         UART1,
44         SOC_INT20_IRQn,
45     },
46 #endif
47 };
48 
49 static struct hbird_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0};
50 
hbird_configure(struct rt_serial_device * serial,struct serial_configure * cfg)51 static rt_err_t hbird_configure(struct rt_serial_device *serial,
52                                struct serial_configure *cfg)
53 {
54     struct hbird_uart *uart_obj;
55     struct hbird_uart_config *uart_cfg;
56     RT_ASSERT(serial != RT_NULL);
57     RT_ASSERT(cfg != RT_NULL);
58 
59     uart_obj = (struct hbird_uart *) serial->parent.user_data;
60     uart_cfg = uart_obj->config;
61     RT_ASSERT(uart_cfg != RT_NULL);
62 
63     uart_init(uart_cfg->uart, cfg->baud_rate);
64 
65     switch (cfg->stop_bits)
66     {
67     case STOP_BITS_1:
68         uart_config_stopbit(uart_cfg->uart, UART_STOP_BIT_1);
69         break;
70     case STOP_BITS_2:
71         uart_config_stopbit(uart_cfg->uart, UART_STOP_BIT_2);
72         break;
73     default:
74         uart_config_stopbit(uart_cfg->uart, UART_STOP_BIT_1);
75         break;
76     }
77 
78     return RT_EOK;
79 }
80 
hbird_control(struct rt_serial_device * serial,int cmd,void * arg)81 static rt_err_t hbird_control(struct rt_serial_device *serial, int cmd,
82                              void *arg)
83 {
84     struct hbird_uart *uart_obj;
85     struct hbird_uart_config *uart_cfg;
86 
87     RT_ASSERT(serial != RT_NULL);
88     uart_obj = (struct hbird_uart *) serial->parent.user_data;
89     uart_cfg = uart_obj->config;
90     RT_ASSERT(uart_cfg != RT_NULL);
91 
92     switch (cmd)
93     {
94     case RT_DEVICE_CTRL_CLR_INT:
95         ECLIC_DisableIRQ(uart_cfg->irqn);
96         uart_disable_rxint(uart_cfg->uart);
97         break;
98     case RT_DEVICE_CTRL_SET_INT:
99         ECLIC_EnableIRQ(uart_cfg->irqn);
100         ECLIC_SetShvIRQ(uart_cfg->irqn, ECLIC_NON_VECTOR_INTERRUPT);
101         ECLIC_SetLevelIRQ(uart_cfg->irqn, 1);
102         uart_enable_rxint(uart_cfg->uart);
103         break;
104     }
105 
106     return RT_EOK;
107 }
108 
hbird_putc(struct rt_serial_device * serial,char ch)109 static int hbird_putc(struct rt_serial_device *serial, char ch)
110 {
111     struct hbird_uart *uart_obj;
112     struct hbird_uart_config *uart_cfg;
113 
114     RT_ASSERT(serial != RT_NULL);
115     uart_obj = (struct hbird_uart *) serial->parent.user_data;
116     uart_cfg = uart_obj->config;
117     RT_ASSERT(uart_cfg != RT_NULL);
118 
119     uart_write(uart_cfg->uart, ch);
120 
121     return 1;
122 }
123 
hbird_getc(struct rt_serial_device * serial)124 static int hbird_getc(struct rt_serial_device *serial)
125 {
126     int ch;
127     uint32_t rxfifo;
128     struct hbird_uart *uart_obj;
129     struct hbird_uart_config *uart_cfg;
130 
131     RT_ASSERT(serial != RT_NULL);
132     uart_obj = (struct hbird_uart *) serial->parent.user_data;
133     uart_cfg = uart_obj->config;
134     RT_ASSERT(uart_cfg != RT_NULL);
135 
136     ch = -1;
137     rxfifo = uart_cfg->uart->RXFIFO;
138     if ((rxfifo & UART_RXFIFO_EMPTY) != UART_RXFIFO_EMPTY) {
139         ch = (int)(uint8_t)(rxfifo);
140     }
141     return ch;
142 }
143 
144 static const struct rt_uart_ops hbird_uart_ops = { hbird_configure, hbird_control,
145            hbird_putc, hbird_getc,
146            RT_NULL
147 };
148 
gd32_uart_isr(struct rt_serial_device * serial)149 static void gd32_uart_isr(struct rt_serial_device *serial)
150 {
151     struct hbird_uart *uart_obj;
152     struct hbird_uart_config *uart_cfg;
153 
154     RT_ASSERT(serial != RT_NULL);
155     uart_obj = (struct hbird_uart *) serial->parent.user_data;
156     uart_cfg = uart_obj->config;
157     RT_ASSERT(uart_cfg != RT_NULL);
158 
159     if (uart_cfg->uart->IP & UART_IP_RXIP_MASK) {
160         rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
161     }
162 }
163 
164 #ifdef BSP_USING_UART0
165 
eclic_irq19_handler(void)166 void eclic_irq19_handler(void)
167 {
168     rt_interrupt_enter();
169 
170     gd32_uart_isr(&uart_obj[UART0_INDEX].serial);
171 
172     rt_interrupt_leave();
173 }
174 
175 #endif
176 
177 #ifdef BSP_USING_UART1
178 
eclic_irq20_handler(void)179 void eclic_irq20_handler(void)
180 {
181     rt_interrupt_enter();
182 
183     gd32_uart_isr(&uart_obj[UART1_INDEX].serial);
184 
185     rt_interrupt_leave();
186 }
187 
188 #endif
189 
190 /* For Nuclei demosoc Uart, when CPU freq is lower than 8M
191    The uart read will only work on baudrate <= 57600.
192    Nowadays, we usually distribute FPGA bitsteam with CPU Freq 16MHz */
193 #define DRV_UART_BAUDRATE       BAUD_RATE_115200
194 
rt_hw_uart_init(void)195 int rt_hw_uart_init(void)
196 {
197     rt_size_t obj_num;
198     int index;
199 
200     obj_num = sizeof(uart_obj) / sizeof(struct hbird_uart);
201     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
202     config.baud_rate = DRV_UART_BAUDRATE;
203     rt_err_t result = 0;
204 
205     for (index = 0; index < obj_num; index++)
206     {
207         /* init UART object */
208         uart_obj[index].config = &uart_config[index];
209         uart_obj[index].serial.ops = &hbird_uart_ops;
210         uart_obj[index].serial.config = config;
211 
212         /* register UART device */
213         result = rt_hw_serial_register(&uart_obj[index].serial,
214                                        uart_obj[index].config->name,
215                                        RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
216                                        &uart_obj[index]);
217         RT_ASSERT(result == RT_EOK);
218     }
219 
220     return result;
221 }
222 
rt_hw_serial_rcvtsk(void * parameter)223 void rt_hw_serial_rcvtsk(void *parameter)
224 {
225     struct hbird_uart_config *uart_cfg;
226 
227     while (1) {
228 #ifdef BSP_USING_UART0
229     uart_cfg = uart_obj[UART0_INDEX].config;
230     if (uart_cfg->uart->IP & UART_IP_RXIP_MASK) {
231         gd32_uart_isr(&uart_obj[UART0_INDEX].serial);
232     }
233 #endif
234 #ifdef BSP_USING_UART1
235     uart_cfg = uart_obj[UART1_INDEX].config;
236     if (uart_cfg->uart->IP & UART_IP_RXIP_MASK) {
237         gd32_uart_isr(&uart_obj[UART1_INDEX].serial);
238     }
239 #endif
240         rt_thread_mdelay(50);
241     }
242 }
243 
244 #endif /* RT_USING_SERIAL */
245 
246 /******************** end of file *******************/
247