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  * 2021-08-27     Jiao         first version
9 */
10 
11 #include "drv_usart.h"
12 #include "drv_config.h"
13 
14 #ifdef RT_USING_SERIAL
15 
16 //#define DRV_DEBUG
17 #define LOG_TAG             "drv.usart"
18 #include <drv_log.h>
19 
20 enum
21 {
22 #ifdef BSP_USING_UART0
23     UART0_INDEX,
24 #endif
25 #ifdef BSP_USING_UART1
26     UART1_INDEX,
27 #endif
28 #ifdef BSP_USING_UART4
29     UART4_INDEX,
30 #endif
31 #ifdef BSP_USING_UART5
32     UART5_INDEX,
33 #endif
34 #ifdef BSP_USING_LPUART0
35     LPUART0_INDEX,
36 #endif
37 #ifdef BSP_USING_LPUART1
38     LPUART1_INDEX,
39 #endif
40 };
41 
42 static struct _uart_config uart_config[] =
43 {
44 #ifdef BSP_USING_UART0
45     UART0_CONFIG,
46 #endif
47 #ifdef BSP_USING_UART1
48     UART1_CONFIG,
49 #endif
50 #ifdef BSP_USING_UART4
51     UART4_CONFIG,
52 #endif
53 #ifdef BSP_USING_UART5
54     UART5_CONFIG,
55 #endif
56 #ifdef BSP_USING_LPUART0
57     LPUART0_CONFIG,
58 #endif
59 #ifdef BSP_USING_LPUART1
60     LPUART1_CONFIG,
61 #endif
62 };
63 
64 static struct _uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0};
65 
uart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)66 static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
67 {
68     extern FL_ErrorStatus FL_UART_GPIO_Init(UART_Type * UARTx);
69 
70     struct _uart *uart;
71     RT_ASSERT(serial != RT_NULL);
72     RT_ASSERT(cfg != RT_NULL);
73 
74     uart = rt_container_of(serial, struct _uart, serial);
75 
76     if (FL_UART_GPIO_Init(uart->config->InitTypeDef) != FL_PASS)
77     {
78         return -RT_ERROR;
79     }
80 
81     uart->handle.clockSrc          = uart->config->clockSrc;
82     uart->handle.baudRate          = cfg->baud_rate;
83 
84     switch (cfg->data_bits)
85     {
86     case DATA_BITS_8:
87         uart->handle.dataWidth = FL_UART_DATA_WIDTH_8B;
88         break;
89     case DATA_BITS_9:
90         uart->handle.dataWidth = FL_UART_DATA_WIDTH_9B;
91         break;
92     default:
93         uart->handle.dataWidth = FL_UART_DATA_WIDTH_8B;
94         break;
95     }
96 
97     switch (cfg->stop_bits)
98     {
99     case STOP_BITS_1:
100         uart->handle.stopBits = FL_UART_STOP_BIT_WIDTH_1B;
101         break;
102     case STOP_BITS_2:
103         uart->handle.stopBits = FL_UART_STOP_BIT_WIDTH_2B;
104         break;
105     default:
106         uart->handle.stopBits = FL_UART_STOP_BIT_WIDTH_1B;
107         break;
108     }
109     switch (cfg->parity)
110     {
111     case PARITY_NONE:
112         uart->handle.parity = FL_UART_PARITY_NONE;
113         break;
114     case PARITY_ODD:
115         uart->handle.parity = FL_UART_PARITY_ODD;
116         break;
117     case PARITY_EVEN:
118         uart->handle.parity = FL_UART_PARITY_EVEN;
119         break;
120     default:
121         uart->handle.parity = FL_UART_PARITY_NONE;
122         break;
123     }
124 
125     uart->handle.transferDirection = FL_UART_DIRECTION_TX_RX;
126 
127     if (FL_UART_Init(uart->config->InitTypeDef, &uart->handle) != FL_PASS)
128     {
129         return -RT_ERROR;
130     }
131 
132     return RT_EOK;
133 }
134 
uart_control(struct rt_serial_device * serial,int cmd,void * arg)135 static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
136 {
137     struct _uart *uart;
138 #ifdef RT_SERIAL_USING_DMA
139     rt_ubase_t ctrl_arg = (rt_ubase_t)arg;
140 #endif
141 
142     RT_ASSERT(serial != RT_NULL);
143     uart = rt_container_of(serial, struct _uart, serial);
144 
145     switch (cmd)
146     {
147     /* disable interrupt */
148     case RT_DEVICE_CTRL_CLR_INT:
149         /* disable rx irq */
150         NVIC_DisableIRQ(uart->config->irq_type);
151         /* disable interrupt */
152         FL_UART_DisableIT_RXBuffFull(uart->config->InitTypeDef);
153 
154         break;
155 
156     /* enable interrupt */
157     case RT_DEVICE_CTRL_SET_INT:
158         /* enable rx irq */
159         NVIC_SetPriority(uart->config->irq_type, 1);
160         NVIC_EnableIRQ(uart->config->irq_type);
161         /* enable interrupt */
162         FL_UART_EnableIT_RXBuffFull(uart->config->InitTypeDef);
163         break;
164 
165 #ifdef RT_SERIAL_USING_DMA
166     case RT_DEVICE_CTRL_CONFIG:
167         stm32_dma_config(serial, ctrl_arg);
168         break;
169 #endif
170 
171     case RT_DEVICE_CTRL_CLOSE:
172         if (FL_UART_DeInit(uart->config->InitTypeDef) != FL_PASS)
173         {
174             RT_ASSERT(0)
175         }
176         break;
177 
178     }
179     return RT_EOK;
180 }
181 
uart_putc(struct rt_serial_device * serial,char c)182 static int uart_putc(struct rt_serial_device *serial, char c)
183 {
184     struct _uart *uart;
185     RT_ASSERT(serial != RT_NULL);
186 
187     uart = rt_container_of(serial, struct _uart, serial);
188     FL_UART_WriteTXBuff(uart->config->InitTypeDef, c); //发送一个数据
189     while (FL_SET != FL_UART_IsActiveFlag_TXShiftBuffEmpty(uart->config->InitTypeDef));
190     return 1;
191 }
192 
uart_getc(struct rt_serial_device * serial)193 static int uart_getc(struct rt_serial_device *serial)
194 {
195     int ch;
196     struct _uart *uart;
197     RT_ASSERT(serial != RT_NULL);
198     uart = rt_container_of(serial, struct _uart, serial);
199 
200     ch = -1;
201     if (FL_SET == FL_UART_IsActiveFlag_RXBuffFull(uart->config->InitTypeDef))
202     {
203         ch = FL_UART_ReadRXBuff(uart->config->InitTypeDef);//接收中断标志可通过读取rxreg寄存器清除
204     }
205     return ch;
206 }
207 
208 /**
209  * Uart common interrupt process. This need add to uart ISR.
210  *
211  * @param serial serial device
212  */
uart_isr(struct rt_serial_device * serial)213 static void uart_isr(struct rt_serial_device *serial)
214 {
215     struct _uart *uart;
216 
217     RT_ASSERT(serial != RT_NULL);
218     uart = rt_container_of(serial, struct _uart, serial);
219 
220     /* UART in mode Receiver -------------------------------------------------*/
221     if ((FL_ENABLE == FL_UART_IsEnabledIT_RXBuffFull(uart->config->InitTypeDef))
222             && (FL_SET == FL_UART_IsActiveFlag_RXBuffFull(uart->config->InitTypeDef)))
223     {
224         rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
225     }
226 }
227 
228 #if defined(BSP_USING_UART0)
UART0_IRQHandler(void)229 void UART0_IRQHandler(void)
230 {
231     /* enter interrupt */
232     rt_interrupt_enter();
233 
234     uart_isr(&(uart_obj[UART0_INDEX].serial));
235 
236     /* leave interrupt */
237     rt_interrupt_leave();
238 }
239 #endif /* BSP_USING_UART1 */
240 
241 #if defined(BSP_USING_UART1)
UART1_IRQHandler(void)242 void UART1_IRQHandler(void)
243 {
244     /* enter interrupt */
245     rt_interrupt_enter();
246 
247     uart_isr(&(uart_obj[UART1_INDEX].serial));
248 
249     /* leave interrupt */
250     rt_interrupt_leave();
251 }
252 #endif /* BSP_USING_UART1 */
253 
254 #if defined(BSP_USING_UART4)
UART4_IRQHandler(void)255 void UART4_IRQHandler(void)
256 {
257     /* enter interrupt */
258     rt_interrupt_enter();
259 
260     uart_isr(&(uart_obj[UART4_INDEX].serial));
261 
262     /* leave interrupt */
263     rt_interrupt_leave();
264 }
265 #endif /* BSP_USING_UART4 */
266 
267 #if defined(BSP_USING_UART5)
UART5_IRQHandler(void)268 void UART5_IRQHandler(void)
269 {
270     /* enter interrupt */
271     rt_interrupt_enter();
272 
273     uart_isr(&(uart_obj[UART5_INDEX].serial));
274 
275     /* leave interrupt */
276     rt_interrupt_leave();
277 }
278 #endif /* BSP_USING_UART5 */
279 
280 #if defined(BSP_USING_LPUART0)
LPUART0_IRQHandler(void)281 void LPUART0_IRQHandler(void)
282 {
283     /* enter interrupt */
284     rt_interrupt_enter();
285 
286     uart_isr(&(uart_obj[LPUART0_INDEX].serial));
287 
288     /* leave interrupt */
289     rt_interrupt_leave();
290 }
291 #endif /* BSP_USING_LPUART0*/
292 
293 #if defined(BSP_USING_LPUART1)
LPUART1_IRQHandler(void)294 void LPUART1_IRQHandler(void)
295 {
296     /* enter interrupt */
297     rt_interrupt_enter();
298 
299     uart_isr(&(uart_obj[LPUART1_INDEX].serial));
300 
301     /* leave interrupt */
302     rt_interrupt_leave();
303 }
304 #endif /* BSP_USING_LPUART1*/
305 
306 static const struct rt_uart_ops _uart_ops =
307 {
308     .configure = uart_configure,
309     .control = uart_control,
310     .putc = uart_putc,
311     .getc = uart_getc,
312     .dma_transmit = 0
313 };
314 
rt_hw_usart_init(void)315 int rt_hw_usart_init(void)
316 {
317     rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct _uart);
318     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
319     rt_err_t result = 0;
320 
321     for (int i = 0; i < obj_num; i++)
322     {
323         /* init UART object */
324         uart_obj[i].config = &uart_config[i];
325         uart_obj[i].serial.ops    = &_uart_ops;
326         uart_obj[i].serial.config = config;
327 
328         /* register UART device */
329         result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name,
330                                        RT_DEVICE_FLAG_RDWR
331                                        | RT_DEVICE_FLAG_INT_RX
332                                        | RT_DEVICE_FLAG_INT_TX
333                                        | uart_obj[i].uart_dma_flag
334                                        , NULL);
335         RT_ASSERT(result == RT_EOK);
336     }
337 
338     return result;
339 }
340 
341 #endif /* RT_USING_SERIAL */
342