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