1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-02-16 Tuber first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "board.h"
14 #include "drv_uart.h"
15
16 #ifdef BSP_USING_UART
17
18 struct uart_device
19 {
20 struct rt_serial_device serial;
21 char *name;
22 };
23
24 #ifdef BSP_USING_UART0
25 static struct uart_device uart_device0 =
26 {
27 .name = "uart0",
28 };
29 #endif
30 #ifdef BSP_USING_UART1
31 static struct uart_device uart_device1 =
32 {
33 .name = "uart1",
34 };
35 #endif
36 #ifdef BSP_USING_UART2
37 static struct uart_device uart_device2 =
38 {
39 .name = "uart2",
40 };
41 #endif
42 #ifdef BSP_USING_UART3
43 static struct uart_device uart_device3 =
44 {
45 .name = "uart3",
46 };
47 #endif
48
uart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)49 static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
50 {
51 UINT32 x;
52 UINT8V R8_UARTx_FCR = 0, R8_UARTx_LCR = 0, R8_UARTx_IER = 0, R8_UARTx_DIV = 0;
53 UINT16V R16_UARTx_DL = 0;
54 struct uart_device *uart_device = serial->parent.user_data;
55
56 //设置波特率
57 x = 10 * GetSysClock() / 8 / cfg->baud_rate;
58 x = (x + 5) / 10;
59 R16_UARTx_DL = (UINT16)x;
60 //设置数据长度
61 switch (cfg->data_bits)
62 {
63 case DATA_BITS_5:
64 //R8_UARTx_LCR |= 0x00;
65 break;
66 case DATA_BITS_6:
67 R8_UARTx_LCR |= 0x01;
68 break;
69 case DATA_BITS_7:
70 R8_UARTx_LCR |= 0x02;
71 break;
72 case DATA_BITS_8:
73 default:
74 R8_UARTx_LCR |= 0x03;
75 break;
76 }
77 //设置停止位
78 switch (cfg->stop_bits)
79 {
80 case STOP_BITS_2:
81 R8_UARTx_LCR |= 0x04;
82 break;
83 case STOP_BITS_1:
84 default:
85 //R8_UARTx_LCR |= 0x00;
86 break;
87 }
88 //设置校验位
89 switch (cfg->parity)
90 {
91 case PARITY_ODD:
92 R8_UART1_LCR |= R8_LCR_PAR_EN;
93 //R8_UART1_LCR |= 0x00;
94 break;
95 case PARITY_EVEN:
96 R8_UART1_LCR |= R8_LCR_PAR_EN;
97 R8_UART1_LCR |= 0x10;
98 break;
99 case PARITY_NONE:
100 default:
101 //R8_UART1_LCR &= (~R8_UART1_LCR);
102 break;
103 }
104
105 #ifdef BSP_USING_UART0
106 if (uart_device == &uart_device0)
107 {
108 GPIOB_SetBits(GPIO_Pin_7);
109 GPIOB_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_PU); // RXD-配置上拉输入
110 GPIOB_ModeCfg(GPIO_Pin_7, GPIO_ModeOut_PP_5mA); // TXD-配置推挽输出,注意先让IO口输出高电平
111 R16_UART0_DL = R16_UARTx_DL;
112 R8_UART0_FCR = (2 << 6) | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO打开,触发点4字节
113 R8_UART0_LCR = R8_UARTx_LCR;
114 R8_UART0_IER = RB_IER_TXD_EN;
115 R8_UART0_DIV = 1;
116 }
117 #endif
118 #ifdef BSP_USING_UART1
119 if (uart_device == &uart_device1)
120 {
121 GPIOA_SetBits(GPIO_Pin_9);
122 GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU); // RXD-配置上拉输入
123 GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA); // TXD-配置推挽输出,注意先让IO口输出高电平
124 R16_UART1_DL = R16_UARTx_DL;
125 R8_UART1_FCR = (2 << 6) | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO打开,触发点4字节
126 R8_UART1_LCR = R8_UARTx_LCR;
127 R8_UART1_IER = RB_IER_TXD_EN;
128 R8_UART1_DIV = 1;
129 }
130 #endif
131 #ifdef BSP_USING_UART2
132 if (uart_device == &uart_device2)
133 {
134 GPIOA_SetBits(GPIO_Pin_7);
135 GPIOA_ModeCfg(GPIO_Pin_6, GPIO_ModeIN_PU); // RXD-配置上拉输入
136 GPIOA_ModeCfg(GPIO_Pin_7, GPIO_ModeOut_PP_5mA); // TXD-配置推挽输出,注意先让IO口输出高电平
137 R16_UART2_DL = R16_UARTx_DL;
138 R8_UART2_FCR = (2 << 6) | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO打开,触发点4字节
139 R8_UART2_LCR = R8_UARTx_LCR;
140 R8_UART2_IER = RB_IER_TXD_EN;
141 R8_UART2_DIV = 1;
142 }
143 #endif
144 #ifdef BSP_USING_UART3
145 if (uart_device == &uart_device3)
146 {
147 GPIOA_SetBits(GPIO_Pin_5);
148 GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_PU); // RXD-配置上拉输入
149 GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeOut_PP_5mA); // TXD-配置推挽输出,注意先让IO口输出高电平
150 R16_UART3_DL = R16_UARTx_DL;
151 R8_UART3_FCR = (2 << 6) | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; // FIFO打开,触发点4字节
152 R8_UART3_LCR = R8_UARTx_LCR;
153 R8_UART3_IER = RB_IER_TXD_EN;
154 R8_UART3_DIV = 1;
155 }
156 #endif
157
158 return RT_EOK;
159 }
160
uart_control(struct rt_serial_device * serial,int cmd,void * arg)161 static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
162 {
163 struct uart_device *uart_device = serial->parent.user_data;
164
165 switch (cmd)
166 {
167 case RT_DEVICE_CTRL_CLR_INT:
168 #ifdef BSP_USING_UART0
169 if (uart_device == &uart_device0)
170 {
171 UART0_INTCfg(DISABLE, RB_IER_RECV_RDY);
172 NVIC_EnableIRQ(UART0_IRQn);
173 }
174 #endif
175 #ifdef BSP_USING_UART1
176 if (uart_device == &uart_device1)
177 {
178 UART1_INTCfg(DISABLE, RB_IER_RECV_RDY);
179 NVIC_EnableIRQ(UART1_IRQn);
180 }
181 #endif
182 #ifdef BSP_USING_UART2
183 if (uart_device == &uart_device2)
184 {
185 UART2_INTCfg(DISABLE, RB_IER_RECV_RDY);
186 NVIC_EnableIRQ(UART2_IRQn);
187 }
188 #endif
189 #ifdef BSP_USING_UART3
190 if (uart_device == &uart_device3)
191 {
192 UART3_INTCfg(DISABLE, RB_IER_RECV_RDY);
193 NVIC_EnableIRQ(UART3_IRQn);
194 }
195 #endif
196 break;
197 case RT_DEVICE_CTRL_SET_INT:
198 #ifdef BSP_USING_UART0
199 if (uart_device == &uart_device0)
200 {
201 UART0_ByteTrigCfg(UART_1BYTE_TRIG);
202 UART0_INTCfg(ENABLE, RB_IER_RECV_RDY);
203 NVIC_EnableIRQ(UART0_IRQn);
204 }
205 #endif
206 #ifdef BSP_USING_UART1
207 if (uart_device == &uart_device1)
208 {
209 UART1_ByteTrigCfg(UART_1BYTE_TRIG);
210 UART1_INTCfg(ENABLE, RB_IER_RECV_RDY);
211 NVIC_EnableIRQ(UART1_IRQn);
212 }
213 #endif
214 #ifdef BSP_USING_UART2
215 if (uart_device == &uart_device2)
216 {
217 UART2_ByteTrigCfg(UART_1BYTE_TRIG);
218 UART2_INTCfg(ENABLE, RB_IER_RECV_RDY);
219 NVIC_EnableIRQ(UART2_IRQn);
220 }
221 #endif
222 #ifdef BSP_USING_UART3
223 if (uart_device == &uart_device3)
224 {
225 UART3_ByteTrigCfg(UART_1BYTE_TRIG);
226 UART3_INTCfg(ENABLE, RB_IER_RECV_RDY);
227 NVIC_EnableIRQ(UART3_IRQn);
228 }
229 #endif
230 break;
231 default:
232 break;
233 }
234
235 return RT_EOK;
236 }
237
uart_putc(struct rt_serial_device * serial,char ch)238 static int uart_putc(struct rt_serial_device *serial, char ch)
239 {
240 struct uart_device *uart_device = serial->parent.user_data;
241
242 #ifdef BSP_USING_UART0
243 if (uart_device == &uart_device0)
244 {
245 while (R8_UART0_TFC >= UART_FIFO_SIZE);
246 R8_UART0_THR = ch;
247 }
248 #endif
249 #ifdef BSP_USING_UART1
250 if (uart_device == &uart_device1)
251 {
252 while (R8_UART1_TFC >= UART_FIFO_SIZE);
253 R8_UART1_THR = ch;
254 }
255 #endif
256 #ifdef BSP_USING_UART2
257 if (uart_device == &uart_device2)
258 {
259 while (R8_UART2_TFC >= UART_FIFO_SIZE);
260 R8_UART2_THR = ch;
261 }
262 #endif
263 #ifdef BSP_USING_UART3
264 if (uart_device == &uart_device3)
265 {
266 while (R8_UART3_TFC >= UART_FIFO_SIZE);
267 R8_UART3_THR = ch;
268 }
269 #endif
270
271 return 1;
272 }
273
uart_getc(struct rt_serial_device * serial)274 static int uart_getc(struct rt_serial_device *serial)
275 {
276 struct uart_device *uart_device = serial->parent.user_data;
277
278 #ifdef BSP_USING_UART0
279 if (uart_device == &uart_device0)
280 {
281 if (R8_UART0_RFC > 0)
282 {
283 return R8_UART0_RBR;
284 }
285 }
286 #endif
287 #ifdef BSP_USING_UART1
288 if (uart_device == &uart_device1)
289 {
290 if (R8_UART1_RFC > 0)
291 {
292 return R8_UART1_RBR;
293 }
294 }
295 #endif
296 #ifdef BSP_USING_UART2
297 if (uart_device == &uart_device2)
298 {
299 if (R8_UART2_RFC > 0)
300 {
301 return R8_UART2_RBR;
302 }
303 }
304 #endif
305 #ifdef BSP_USING_UART3
306 if (uart_device == &uart_device3)
307 {
308 if (R8_UART3_RFC > 0)
309 {
310 return R8_UART3_RBR;
311 }
312 }
313 #endif
314
315 return -1;
316 }
317
318 static const struct rt_uart_ops uart_ops =
319 {
320 .configure = uart_configure,
321 .control = uart_control,
322 .putc = uart_putc,
323 .getc = uart_getc,
324 .dma_transmit = RT_NULL,
325 };
326
uart_isr(struct rt_serial_device * serial,UINT8 flag)327 void uart_isr(struct rt_serial_device *serial, UINT8 flag)
328 {
329 switch (flag)
330 {
331 case UART_II_RECV_RDY: // 数据达到设置触发点
332 rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
333 break;
334 case UART_II_RECV_TOUT: // 接收超时,暂时一帧数据接收完成
335 rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_TIMEOUT);
336 break;
337 case UART_II_THR_EMPTY: // 发送缓存区空,可继续发送
338 rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE);
339 break;
340 default:
341 break;
342 }
343 }
344
345 #ifdef BSP_USING_UART0
UART0_IRQHandler(void)346 void UART0_IRQHandler(void)
347 {
348 rt_interrupt_enter();
349
350 uart_isr(&uart_device0.serial, UART0_GetITFlag());
351
352 rt_interrupt_leave();
353 }
354 #endif
355 #ifdef BSP_USING_UART1
UART1_IRQHandler(void)356 void UART1_IRQHandler(void)
357 {
358 rt_interrupt_enter();
359
360 uart_isr(&uart_device1.serial, UART1_GetITFlag());
361
362 rt_interrupt_leave();
363 }
364 #endif
365 #ifdef BSP_USING_UART2
UART2_IRQHandler(void)366 void UART2_IRQHandler(void)
367 {
368 rt_interrupt_enter();
369
370 uart_isr(&uart_device2.serial, UART2_GetITFlag());
371
372 rt_interrupt_leave();
373 }
374 #endif
375 #ifdef BSP_USING_UART3
UART3_IRQHandler(void)376 void UART3_IRQHandler(void)
377 {
378 rt_interrupt_enter();
379
380 uart_isr(&uart_device3.serial, UART3_GetITFlag());
381
382 rt_interrupt_leave();
383 }
384 #endif
385
rt_hw_uart_init(void)386 int rt_hw_uart_init(void)
387 {
388 struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
389
390 #ifdef BSP_USING_UART0
391 uart_device0.serial.config = config;
392 uart_device0.serial.ops = &uart_ops;
393 rt_hw_serial_register(&uart_device0.serial, uart_device0.name,
394 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
395 &uart_device0);
396 #endif
397 #ifdef BSP_USING_UART1
398 uart_device1.serial.config = config;
399 uart_device1.serial.ops = &uart_ops;
400 rt_hw_serial_register(&uart_device1.serial, uart_device1.name,
401 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
402 &uart_device1);
403 #endif
404 #ifdef BSP_USING_UART2
405 uart_device2.serial.config = config;
406 uart_device2.serial.ops = &uart_ops;
407 rt_hw_serial_register(&uart_device2.serial, uart_device2.name,
408 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
409 &uart_device2);
410 #endif
411 #ifdef BSP_USING_UART3
412 uart_device3.serial.config = config;
413 uart_device3.serial.ops = &uart_ops;
414 rt_hw_serial_register(&uart_device3.serial, uart_device3.name,
415 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
416 &uart_device3);
417 #endif
418
419 return RT_EOK;
420 }
421 #endif /* BSP_USING_UART */
422