1 /*
2 * Copyright (c) 2006-2022, Synwit Technology Co.,Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-07-01 lik first version
9 */
10
11 #include "drv_uart.h"
12
13 #ifdef RT_USING_SERIAL
14 #ifdef BSP_USING_UART
15
16 //#define DRV_DEBUG
17 #define LOG_TAG "drv.uart"
18 #include <drv_log.h>
19
20 #if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) && \
21 !defined(BSP_USING_UART3)
22 #error "Please define at least one BSP_USING_UARTx"
23 /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
24 #endif
25
26 #ifdef BSP_USING_UART0
27 #ifndef UART0_CFG
28 #define UART0_CFG \
29 { \
30 .name = "uart0", \
31 .UARTx = UART0, \
32 .irq = UART0_IRQn, \
33 .uart_initstruct.Baudrate = 115200, \
34 .uart_initstruct.DataBits = UART_DATA_8BIT, \
35 .uart_initstruct.Parity = UART_PARITY_NONE, \
36 .uart_initstruct.StopBits = UART_STOP_1BIT, \
37 .uart_initstruct.RXThreshold = 0, \
38 .uart_initstruct.RXThresholdIEn = 1, \
39 .uart_initstruct.TXThresholdIEn = 0, \
40 .uart_initstruct.TimeoutTime = 10, \
41 .uart_initstruct.TimeoutIEn = 1, \
42 }
43 #endif /* UART0_CFG */
44 #endif /* BSP_USING_UART0 */
45
46 #ifdef BSP_USING_UART1
47 #ifndef UART1_CFG
48 #define UART1_CFG \
49 { \
50 .name = "uart1", \
51 .UARTx = UART1, \
52 .irq = UART1_IRQn, \
53 .uart_initstruct.Baudrate = 115200, \
54 .uart_initstruct.DataBits = UART_DATA_8BIT, \
55 .uart_initstruct.Parity = UART_PARITY_NONE, \
56 .uart_initstruct.StopBits = UART_STOP_1BIT, \
57 .uart_initstruct.RXThreshold = 0, \
58 .uart_initstruct.RXThresholdIEn = 1, \
59 .uart_initstruct.TXThresholdIEn = 0, \
60 .uart_initstruct.TimeoutTime = 10, \
61 .uart_initstruct.TimeoutIEn = 1, \
62 }
63 #endif /* UART1_CFG */
64 #endif /* BSP_USING_UART1 */
65
66 #ifdef BSP_USING_UART2
67 #ifndef UART2_CFG
68 #define UART2_CFG \
69 { \
70 .name = "uart2", \
71 .UARTx = UART2, \
72 .irq = UART2_IRQn, \
73 .uart_initstruct.Baudrate = 115200, \
74 .uart_initstruct.DataBits = UART_DATA_8BIT, \
75 .uart_initstruct.Parity = UART_PARITY_NONE, \
76 .uart_initstruct.StopBits = UART_STOP_1BIT, \
77 .uart_initstruct.RXThreshold = 0, \
78 .uart_initstruct.RXThresholdIEn = 1, \
79 .uart_initstruct.TXThresholdIEn = 0, \
80 .uart_initstruct.TimeoutTime = 10, \
81 .uart_initstruct.TimeoutIEn = 1, \
82 }
83 #endif /* UART2_CFG */
84 #endif /* BSP_USING_UART2 */
85
86 #ifdef BSP_USING_UART3
87 #ifndef UART3_CFG
88 #define UART3_CFG \
89 { \
90 .name = "uart3", \
91 .UARTx = UART3, \
92 .irq = UART3_IRQn, \
93 .uart_initstruct.Baudrate = 115200, \
94 .uart_initstruct.DataBits = UART_DATA_8BIT, \
95 .uart_initstruct.Parity = UART_PARITY_NONE, \
96 .uart_initstruct.StopBits = UART_STOP_1BIT, \
97 .uart_initstruct.RXThreshold = 0, \
98 .uart_initstruct.RXThresholdIEn = 1, \
99 .uart_initstruct.TXThresholdIEn = 0, \
100 .uart_initstruct.TimeoutTime = 10, \
101 .uart_initstruct.TimeoutIEn = 1, \
102 }
103 #endif /* UART3_CFG */
104 #endif /* BSP_USING_UART3 */
105
106 /* swm config class */
107 struct swm_uart_cfg
108 {
109 const char *name;
110 UART_TypeDef *UARTx;
111 IRQn_Type irq;
112 UART_InitStructure uart_initstruct;
113 };
114
115 /* swm uart dirver class */
116 struct swm_uart_device
117 {
118 struct swm_uart_cfg *uart_cfg;
119 struct rt_serial_device serial_device;
120 };
121
122 enum
123 {
124 #ifdef BSP_USING_UART0
125 UART0_INDEX,
126 #endif
127 #ifdef BSP_USING_UART1
128 UART1_INDEX,
129 #endif
130 #ifdef BSP_USING_UART2
131 UART2_INDEX,
132 #endif
133 #ifdef BSP_USING_UART3
134 UART3_INDEX,
135 #endif
136 };
137
138 static struct swm_uart_cfg swm_uart_cfg[] =
139 {
140 #ifdef BSP_USING_UART0
141 UART0_CFG,
142 #endif
143 #ifdef BSP_USING_UART1
144 UART1_CFG,
145 #endif
146 #ifdef BSP_USING_UART2
147 UART2_CFG,
148 #endif
149 #ifdef BSP_USING_UART3
150 UART3_CFG,
151 #endif
152 };
153
154 static struct swm_uart_device uart_obj[sizeof(swm_uart_cfg) / sizeof(swm_uart_cfg[0])] = {0};
155
swm_uart_configure(struct rt_serial_device * serial_device,struct serial_configure * configure)156 static rt_err_t swm_uart_configure(struct rt_serial_device *serial_device, struct serial_configure *configure)
157 {
158 struct swm_uart_cfg *uart_cfg;
159 RT_ASSERT(serial_device != RT_NULL);
160 RT_ASSERT(configure != RT_NULL);
161 uart_cfg = serial_device->parent.user_data;
162
163 uart_cfg->uart_initstruct.Baudrate = configure->baud_rate;
164 switch (configure->data_bits)
165 {
166 case DATA_BITS_8:
167 uart_cfg->uart_initstruct.DataBits = UART_DATA_8BIT;
168 break;
169 case DATA_BITS_9:
170 uart_cfg->uart_initstruct.DataBits = UART_DATA_9BIT;
171 break;
172 default:
173 uart_cfg->uart_initstruct.DataBits = UART_DATA_8BIT;
174 break;
175 }
176 switch (configure->stop_bits)
177 {
178 case STOP_BITS_1:
179 uart_cfg->uart_initstruct.StopBits = UART_STOP_1BIT;
180 break;
181 case STOP_BITS_2:
182 uart_cfg->uart_initstruct.StopBits = UART_STOP_2BIT;
183 break;
184 default:
185 uart_cfg->uart_initstruct.StopBits = UART_STOP_1BIT;
186 break;
187 }
188 switch (configure->parity)
189 {
190 case PARITY_NONE:
191 uart_cfg->uart_initstruct.Parity = UART_PARITY_NONE;
192 break;
193 case PARITY_ODD:
194 uart_cfg->uart_initstruct.Parity = UART_PARITY_ODD;
195 break;
196 case PARITY_EVEN:
197 uart_cfg->uart_initstruct.Parity = UART_PARITY_EVEN;
198 break;
199 default:
200 uart_cfg->uart_initstruct.Parity = UART_PARITY_NONE;
201 break;
202 }
203
204 UART_Init(uart_cfg->UARTx, &(uart_cfg->uart_initstruct));
205 UART_Open(uart_cfg->UARTx);
206 return RT_EOK;
207 }
208
swm_uart_control(struct rt_serial_device * serial_device,int cmd,void * arg)209 static rt_err_t swm_uart_control(struct rt_serial_device *serial_device, int cmd, void *arg)
210 {
211 struct swm_uart_cfg *uart_cfg;
212 RT_ASSERT(serial_device != RT_NULL);
213 uart_cfg = serial_device->parent.user_data;
214
215 switch (cmd)
216 {
217 case RT_DEVICE_CTRL_CLR_INT:
218 /* disable rx irq */
219 NVIC_DisableIRQ(uart_cfg->irq);
220 break;
221 case RT_DEVICE_CTRL_SET_INT:
222 /* enable rx irq */
223 NVIC_EnableIRQ(uart_cfg->irq);
224 break;
225 }
226 return RT_EOK;
227 }
228
swm_uart_putc(struct rt_serial_device * serial_device,char c)229 static int swm_uart_putc(struct rt_serial_device *serial_device, char c)
230 {
231 struct swm_uart_cfg *uart_cfg;
232 RT_ASSERT(serial_device != RT_NULL);
233 uart_cfg = serial_device->parent.user_data;
234
235 UART_WriteByte(uart_cfg->UARTx, c);
236 while (UART_IsTXBusy(uart_cfg->UARTx))
237 ;
238 return 1;
239 }
240
swm_uart_getc(struct rt_serial_device * serial_device)241 static int swm_uart_getc(struct rt_serial_device *serial_device)
242 {
243 int ch;
244 struct swm_uart_cfg *uart_cfg;
245 RT_ASSERT(serial_device != RT_NULL);
246 uart_cfg = serial_device->parent.user_data;
247
248 ch = -1;
249 if (UART_IsRXFIFOEmpty(uart_cfg->UARTx) == 0)
250 {
251 UART_ReadByte(uart_cfg->UARTx, (uint32_t *)&ch);
252 }
253 return ch;
254 }
255
256 static const struct rt_uart_ops swm_uart_ops =
257 {
258 .configure = swm_uart_configure,
259 .control = swm_uart_control,
260 .putc = swm_uart_putc,
261 .getc = swm_uart_getc,
262 .dma_transmit = RT_NULL};
263
264 /**
265 * Uart common interrupt process. This need add to uart ISR.
266 *
267 * @param serial serial device
268 */
swm_uart_isr(struct rt_serial_device * serial_device)269 static void swm_uart_isr(struct rt_serial_device *serial_device)
270 {
271 struct swm_uart_cfg *uart_cfg;
272 RT_ASSERT(serial_device != RT_NULL);
273 uart_cfg = serial_device->parent.user_data;
274
275 /* UART in mode Receiver -------------------------------------------------*/
276 if (UART_INTStat(uart_cfg->UARTx, UART_IT_RX_THR) || UART_INTStat(uart_cfg->UARTx, UART_IT_RX_TOUT))
277 {
278 if(!UART_IsRXFIFOEmpty(uart_cfg->UARTx))
279 {
280 rt_hw_serial_isr(serial_device, RT_SERIAL_EVENT_RX_IND);
281 }
282
283 if(UART_INTStat(uart_cfg->UARTx, UART_IT_RX_TOUT))
284 {
285 UART_INTClr(uart_cfg->UARTx, UART_IT_RX_TOUT);
286
287 rt_hw_serial_isr(serial_device, RT_SERIAL_EVENT_RX_TIMEOUT);
288 }
289 }
290 }
291
292 #if defined(BSP_USING_UART0)
UART0_Handler(void)293 void UART0_Handler(void)
294 {
295 rt_interrupt_enter();
296 swm_uart_isr(&(uart_obj[UART0_INDEX].serial_device));
297 rt_interrupt_leave();
298 }
299 #endif /* BSP_USING_UART0 */
300
301 #if defined(BSP_USING_UART1)
UART1_Handler(void)302 void UART1_Handler(void)
303 {
304 rt_interrupt_enter();
305 swm_uart_isr(&(uart_obj[UART1_INDEX].serial_device));
306 rt_interrupt_leave();
307 }
308 #endif /* BSP_USING_UART1 */
309
310 #if defined(BSP_USING_UART2)
UART2_Handler(void)311 void UART2_Handler(void)
312 {
313 rt_interrupt_enter();
314 swm_uart_isr(&(uart_obj[UART2_INDEX].serial_device));
315 rt_interrupt_leave();
316 }
317 #endif /* BSP_USING_UART2 */
318
319 #if defined(BSP_USING_UART3)
UART3_Handler(void)320 void UART3_Handler(void)
321 {
322 rt_interrupt_enter();
323 swm_uart_isr(&(uart_obj[UART3_INDEX].serial_device));
324 rt_interrupt_leave();
325 }
326 #endif /* BSP_USING_UART3 */
327
swm_uart_init(void)328 int swm_uart_init(void)
329 {
330 struct serial_configure serial_cfg = RT_SERIAL_CONFIG_DEFAULT;
331 int i = 0;
332 rt_err_t result = RT_EOK;
333
334 #ifdef BSP_USING_UART0
335 PORT_Init(PORTM, PIN0, PORTM_PIN0_UART0_RX, 1);
336 PORT_Init(PORTM, PIN1, PORTM_PIN1_UART0_TX, 0);
337 #endif
338 #ifdef BSP_USING_UART1
339 PORT_Init(PORTD, PIN4, PORTD_PIN4_UART1_RX, 1);
340 PORT_Init(PORTD, PIN3, PORTD_PIN3_UART1_TX, 0);
341 #endif
342 #ifdef BSP_USING_UART2
343 PORT_Init(PORTC, PIN1, PORTC_PIN1_UART2_RX, 1);
344 PORT_Init(PORTC, PIN0, PORTC_PIN0_UART2_TX, 0);
345 #endif
346 #ifdef BSP_USING_UART3
347 PORT_Init(PORTC, PIN2, PORTC_PIN2_UART3_RX, 1);
348 PORT_Init(PORTC, PIN3, PORTC_PIN3_UART3_TX, 0);
349 #endif
350
351 for (i = 0; i < sizeof(swm_uart_cfg) / sizeof(swm_uart_cfg[0]); i++)
352 {
353 uart_obj[i].uart_cfg = &swm_uart_cfg[i];
354 uart_obj[i].serial_device.ops = &swm_uart_ops;
355 uart_obj[i].serial_device.config = serial_cfg;
356
357 result = rt_hw_serial_register(&uart_obj[i].serial_device, uart_obj[i].uart_cfg->name,
358 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart_obj[i].uart_cfg);
359 RT_ASSERT(result == RT_EOK);
360 }
361
362 return result;
363 }
364
365 #endif /* BSP_USING_UART */
366 #endif /* RT_USING_SERIAL */
367