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