1 /*
2 * Copyright (c) 2006-2025, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2025-04-27 WangShun the first version
9 */
10
11 #include "board.h"
12 #include "rtthread.h"
13 #include <rtdevice.h>
14 #include <string.h>
15 #include <drv_usart.h>
16
17 #ifdef RT_USING_SERIAL
18 #define DRV_DEBUG
19 #define LOG_TAG "drv.uart"
20
21 #ifdef DRV_DEBUG
22 #define DBG_LVL DBG_LOG
23 #else
24 #define DBG_LVL DBG_INFO
25 #endif /* DRV_DEBUG */
26
27 #include <rtdbg.h>
28
29 #if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) && !defined(BSP_USING_UART3) \
30 && !defined(BSP_USING_UART4) && !defined(BSP_USING_UART5) && !defined(BSP_USING_UART6) && !defined(BSP_USING_UART7)
31 #error "Please define at least one BSP_USING_UARTx"
32 /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
33 #endif
34
35 static void xuantie_uart0_rx_isr(csi_uart_t *uart_handler, csi_uart_event_t event, void *arg);
36
37 enum
38 {
39 #ifdef BSP_USING_UART0
40 UART0_INDEX,
41 #endif
42 };
43
44 struct xuantie_uart_config uart_config[] =
45 {
46 #ifdef BSP_USING_UART0
47 {
48 "uart0",
49 0,
50 xuantie_uart0_rx_isr
51 }
52 #endif
53 };
54
55 struct xuantie_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0};
56
xuantie_configure(struct rt_serial_device * serial,struct serial_configure * cfg)57 static rt_err_t xuantie_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
58 {
59 struct xuantie_uart *uart = (struct xuantie_uart *)serial->parent.user_data;
60 csi_error_t ret;
61
62 ret = csi_uart_baud(&uart->uart, cfg->baud_rate);
63 if (ret != CSI_OK)
64 {
65 return -RT_ERROR;
66 }
67
68 csi_uart_data_bits_t data_bits;
69 csi_uart_parity_t parity;
70 csi_uart_stop_bits_t stop_bits;
71
72 switch (cfg->data_bits)
73 {
74 case DATA_BITS_5:
75 data_bits = UART_DATA_BITS_5;
76 break;
77 case DATA_BITS_6:
78 data_bits = UART_DATA_BITS_6;
79 break;
80 case DATA_BITS_7:
81 data_bits = UART_DATA_BITS_7;
82 break;
83 case DATA_BITS_8:
84 data_bits = UART_DATA_BITS_8;
85 break;
86 case DATA_BITS_9:
87 data_bits = UART_DATA_BITS_9;
88 break;
89 default:
90 data_bits = UART_DATA_BITS_8;
91 break;
92 }
93
94 switch (cfg->parity)
95 {
96 case PARITY_NONE:
97 parity = UART_PARITY_NONE;
98 break;
99 case PARITY_ODD:
100 parity = UART_PARITY_ODD;
101 break;
102 case PARITY_EVEN:
103 parity = UART_PARITY_EVEN;
104 break;
105 default:
106 parity = UART_PARITY_NONE;
107 break;
108 }
109
110 switch (cfg->stop_bits)
111 {
112 case STOP_BITS_1:
113 stop_bits = UART_STOP_BITS_1;
114 break;
115 case STOP_BITS_2:
116 stop_bits = UART_STOP_BITS_2;
117 break;
118 default:
119 stop_bits = UART_STOP_BITS_1;
120 break;
121 }
122
123 ret = csi_uart_format(&uart->uart, data_bits, parity, stop_bits);
124 if (ret != CSI_OK)
125 {
126 return -RT_ERROR;
127 }
128
129 return RT_EOK;
130 }
131
xuantie_control(struct rt_serial_device * serial,int cmd,void * arg)132 static rt_err_t xuantie_control(struct rt_serial_device *serial, int cmd, void *arg)
133 {
134 switch (cmd)
135 {
136 case RT_DEVICE_CTRL_CONFIG:
137 return xuantie_configure(serial, (struct serial_configure *)arg);
138 default:
139 return -RT_ERROR;
140 }
141 }
142
xuantie_putc(struct rt_serial_device * serial,char c)143 static int xuantie_putc(struct rt_serial_device *serial, char c)
144 {
145 struct xuantie_uart *uart = (struct xuantie_uart *)serial->parent.user_data;
146 int32_t ret;
147
148 ret = csi_uart_send(&uart->uart, &c, 1, 50);
149 if (ret == 1)
150 return RT_EOK;
151
152 return -RT_ERROR;
153 }
154
xuantie_getc(struct rt_serial_device * serial)155 static int xuantie_getc(struct rt_serial_device *serial)
156 {
157 int c = -1;
158 struct xuantie_uart *uart = (struct xuantie_uart *)serial->parent.user_data;
159 dw_uart_regs_t *uart_base = (dw_uart_regs_t *)HANDLE_REG_BASE((&uart->uart));
160
161 csi_uart_receive(&uart->uart, &c, 1, 0x5);
162 dw_uart_enable_recv_irq(uart_base);
163 return c;
164 }
165
166 static const struct rt_uart_ops xuantie_uart_ops =
167 {
168 xuantie_configure,
169 xuantie_control,
170 xuantie_putc,
171 xuantie_getc,
172 RT_NULL,
173 };
174
xuantie_uart0_rx_isr(csi_uart_t * uart_handler,csi_uart_event_t event,void * arg)175 static void xuantie_uart0_rx_isr(csi_uart_t *uart_handler, csi_uart_event_t event, void *arg)
176 {
177 rt_interrupt_enter();
178 rt_hw_serial_isr(&uart_obj[UART0_INDEX].serial, RT_SERIAL_EVENT_RX_IND);
179 rt_interrupt_leave();
180 }
181
rt_hw_usart_init(void)182 int rt_hw_usart_init(void)
183 {
184 rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct xuantie_uart);
185 struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
186 rt_err_t result = 0;
187
188 for (int i = 0; i < obj_num; i++)
189 {
190 /* Initialize YOC UART */
191 result = csi_uart_init(&uart_obj[i].uart, 0);
192 if (result != CSI_OK)
193 {
194 LOG_E("Failed to initialize UART %d", uart_obj[i].config->idx);
195 return -RT_ERROR;
196 }
197
198 /* Init UART object */
199 uart_obj[i].config = &uart_config[i];
200 uart_obj[i].serial.ops = &xuantie_uart_ops;
201 uart_obj[i].serial.config = config;
202
203 csi_uart_attach_callback(&uart_obj[i].uart, uart_obj[i].config->xuantie_uart_rx_isr, NULL);
204
205 /* Register UART device */
206 result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name,
207 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
208 &uart_obj[i]);
209 if (result != RT_EOK)
210 {
211 LOG_E("Failed to register UART device %s", uart_obj[i].config->name);
212 csi_uart_uninit(&uart_obj[i].uart);
213 return -RT_ERROR;
214 }
215 }
216 return result;
217 }
218
219 #endif /* RT_USING_SERIAL */
220