1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-01-21     charlown      first version
9  */
10 
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "board.h"
14 #include "drv_uart.h"
15 #include "ch32f20x_usart.h"
16 #include "ch32f20x_misc.h"
17 
18 #ifdef BSP_USING_UART
19 
20 #ifndef ITEM_NUM
21 #define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
22 #endif
23 
24 struct usart_device
25 {
26     struct rt_serial_device parent;
27     char *name;
28     USART_TypeDef *periph;
29     IRQn_Type irqn;
30 };
31 
32 #ifdef BSP_USING_UART1
33 static struct usart_device usart_device1 =
34     {
35         .name = "uart1",
36         .periph = USART1,
37         .irqn = USART1_IRQn,
38 };
39 #endif
40 
41 #ifdef BSP_USING_UART2
42 static struct usart_device usart_device2 =
43     {
44         .name = "uart2",
45         .periph = USART2,
46         .irqn = USART2_IRQn,
47 };
48 #endif
49 #ifdef BSP_USING_UART3
50 static struct usart_device usart_device3 =
51     {
52         .name = "uart3",
53         .periph = USART3,
54         .irqn = USART3_IRQn,
55 };
56 #endif
57 #ifdef BSP_USING_UART4
58 static struct usart_device usart_device4 =
59     {
60         .name = "uart4",
61         .periph = UART4,
62         .irqn = UART4_IRQn,
63 };
64 #endif
65 #ifdef BSP_USING_UART5
66 static struct usart_device usart_device5 =
67     {
68         .name = "uart5",
69         .periph = UART5,
70         .irqn = UART5_IRQn,
71 };
72 #endif
73 #ifdef BSP_USING_UART6
74 static struct usart_device usart_device6 =
75     {
76         .name = "uart6",
77         .periph = UART6,
78         .irqn = UART6_IRQn,
79 };
80 #endif
81 #ifdef BSP_USING_UART7
82 static struct usart_device usart_device7 =
83     {
84         .name = "uart7",
85         .periph = UART7,
86         .irqn = UART7_IRQn,
87 };
88 #endif
89 #ifdef BSP_USING_UART8
90 static struct usart_device usart_device8 =
91     {
92         .name = "uart8",
93         .periph = UART8,
94         .irqn = UART8_IRQn,
95 };
96 #endif
97 
ch32f2_usart_configure(struct rt_serial_device * serial,struct serial_configure * cfg)98 static rt_err_t ch32f2_usart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
99 {
100     struct usart_device *usart_dev;
101     USART_InitTypeDef USART_InitStructure;
102 
103     RT_ASSERT(serial != RT_NULL);
104     RT_ASSERT(cfg != RT_NULL);
105 
106     usart_dev = (struct usart_device *)serial;
107     RT_ASSERT(usart_dev != RT_NULL);
108 
109     ch32f2_usart_clock_and_io_init(usart_dev->periph);
110 
111     USART_StructInit(&USART_InitStructure);
112 
113     USART_InitStructure.USART_BaudRate = cfg->baud_rate;
114     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
115     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
116 
117     switch (cfg->data_bits)
118     {
119     case DATA_BITS_8:
120         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
121         break;
122 
123     case DATA_BITS_9:
124         USART_InitStructure.USART_WordLength = USART_WordLength_9b;
125         break;
126     default:
127         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
128         break;
129     }
130 
131     switch (cfg->stop_bits)
132     {
133     case STOP_BITS_1:
134         USART_InitStructure.USART_StopBits = USART_StopBits_1;
135         break;
136     case STOP_BITS_2:
137         USART_InitStructure.USART_StopBits = USART_StopBits_2;
138         break;
139     default:
140         USART_InitStructure.USART_StopBits = USART_StopBits_1;
141         break;
142     }
143 
144     switch (cfg->parity)
145     {
146     case PARITY_NONE:
147         USART_InitStructure.USART_Parity = USART_Parity_No;
148         break;
149     case PARITY_ODD:
150         USART_InitStructure.USART_Parity = USART_Parity_Odd;
151         break;
152     case PARITY_EVEN:
153         USART_InitStructure.USART_Parity = USART_Parity_Even;
154         break;
155     default:
156         USART_InitStructure.USART_Parity = USART_Parity_No;
157         break;
158     }
159     USART_Init(usart_dev->periph, &USART_InitStructure);
160     USART_Cmd(usart_dev->periph, ENABLE);
161 
162     return RT_EOK;
163 }
164 
ch32f2_usart_control(struct rt_serial_device * serial,int cmd,void * arg)165 static rt_err_t ch32f2_usart_control(struct rt_serial_device *serial, int cmd, void *arg)
166 {
167     struct usart_device *usart_dev;
168 
169     NVIC_InitTypeDef NVIC_InitStruct;
170 
171     RT_ASSERT(serial != RT_NULL);
172 
173     usart_dev = (struct usart_device *)serial;
174 
175     RT_ASSERT(usart_dev != RT_NULL);
176 
177     NVIC_InitStruct.NVIC_IRQChannel = usart_dev->irqn;
178     NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
179     NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
180 
181     switch (cmd)
182     {
183     case RT_DEVICE_CTRL_CLR_INT:
184         NVIC_InitStruct.NVIC_IRQChannelCmd = DISABLE;
185         NVIC_Init(&NVIC_InitStruct);
186         USART_ITConfig(usart_dev->periph, USART_IT_RXNE, DISABLE);
187         break;
188 
189     case RT_DEVICE_CTRL_SET_INT:
190         NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
191         NVIC_Init(&NVIC_InitStruct);
192         USART_ITConfig(usart_dev->periph, USART_IT_RXNE, ENABLE);
193         break;
194     }
195 
196     return RT_EOK;
197 }
198 
ch32f2_usart_putc(struct rt_serial_device * serial,char ch)199 static int ch32f2_usart_putc(struct rt_serial_device *serial, char ch)
200 {
201     struct usart_device *usart_dev;
202 
203     RT_ASSERT(serial != RT_NULL);
204 
205     usart_dev = (struct usart_device *)serial;
206 
207     RT_ASSERT(usart_dev != RT_NULL);
208 
209     USART_SendData(usart_dev->periph, (uint8_t)ch);
210     while (USART_GetFlagStatus(usart_dev->periph, USART_FLAG_TXE) == RESET)
211         ;
212 
213     return 1;
214 }
215 
ch32f2_usart_getc(struct rt_serial_device * serial)216 static int ch32f2_usart_getc(struct rt_serial_device *serial)
217 {
218     struct usart_device *usart_dev;
219     int ch;
220 
221     RT_ASSERT(serial != RT_NULL);
222 
223     usart_dev = (struct usart_device *)serial;
224 
225     RT_ASSERT(usart_dev != RT_NULL);
226 
227     ch = -1;
228     if (RESET != USART_GetFlagStatus(usart_dev->periph, USART_FLAG_RXNE))
229     {
230         ch = USART_ReceiveData(usart_dev->periph) & 0xff;
231     }
232 
233     return ch;
234 }
235 
236 static const struct rt_uart_ops usart_ops = {
237     .configure = ch32f2_usart_configure,
238     .control = ch32f2_usart_control,
239     .putc = ch32f2_usart_putc,
240     .getc = ch32f2_usart_getc,
241     .dma_transmit = RT_NULL};
242 
usart_isr(struct usart_device * usart_dev)243 static void usart_isr(struct usart_device *usart_dev)
244 {
245 
246     RT_ASSERT(usart_dev != RT_NULL);
247 
248     if ((USART_GetITStatus(usart_dev->periph, USART_IT_RXNE) != RESET) && (RESET != USART_GetFlagStatus(usart_dev->periph, USART_FLAG_RXNE)))
249     {
250         rt_hw_serial_isr(&usart_dev->parent, RT_SERIAL_EVENT_RX_IND);
251         USART_ClearITPendingBit(usart_dev->periph, USART_IT_RXNE);
252         USART_ClearFlag(usart_dev->periph, USART_FLAG_RXNE);
253     }
254     else
255     {
256         if (USART_GetFlagStatus(usart_dev->periph, USART_FLAG_CTS) != RESET)
257         {
258             USART_ClearFlag(usart_dev->periph, USART_FLAG_CTS);
259         }
260 
261         if (USART_GetFlagStatus(usart_dev->periph, USART_FLAG_LBD) != RESET)
262         {
263             USART_ClearFlag(usart_dev->periph, USART_FLAG_LBD);
264         }
265 
266         if (USART_GetFlagStatus(usart_dev->periph, USART_FLAG_TC) != RESET)
267         {
268             USART_ClearFlag(usart_dev->periph, USART_FLAG_TC);
269         }
270     }
271 }
272 
273 #ifdef BSP_USING_UART1
USART1_IRQHandler(void)274 void USART1_IRQHandler(void)
275 {
276     rt_interrupt_enter();
277 
278     usart_isr(&usart_device1);
279 
280     rt_interrupt_leave();
281 }
282 #endif
283 #ifdef BSP_USING_UART2
USART2_IRQHandler(void)284 void USART2_IRQHandler(void)
285 {
286     rt_interrupt_enter();
287 
288     usart_isr(&usart_device2);
289 
290     rt_interrupt_leave();
291 }
292 #endif
293 #ifdef BSP_USING_UART3
USART3_IRQHandler(void)294 void USART3_IRQHandler(void)
295 {
296     rt_interrupt_enter();
297 
298     usart_isr(&usart_device3);
299 
300     rt_interrupt_leave();
301 }
302 #endif
303 #ifdef BSP_USING_UART4
USART4_IRQHandler(void)304 void USART4_IRQHandler(void)
305 {
306     rt_interrupt_enter();
307 
308     usart_isr(&usart_device4);
309 
310     rt_interrupt_leave();
311 }
312 #endif
313 #ifdef BSP_USING_UART5
USART5_IRQHandler(void)314 void USART5_IRQHandler(void)
315 {
316     rt_interrupt_enter();
317 
318     usart_isr(&usart_device5);
319 
320     rt_interrupt_leave();
321 }
322 #endif
323 #ifdef BSP_USING_UART6
USART6_IRQHandler(void)324 void USART6_IRQHandler(void)
325 {
326     rt_interrupt_enter();
327 
328     usart_isr(&usart_device6);
329 
330     rt_interrupt_leave();
331 }
332 #endif
333 #ifdef BSP_USING_UART7
USART7_IRQHandler(void)334 void USART7_IRQHandler(void)
335 {
336     rt_interrupt_enter();
337 
338     usart_isr(&usart_device7);
339 
340     rt_interrupt_leave();
341 }
342 #endif
343 #ifdef BSP_USING_UART8
USART8_IRQHandler(void)344 void USART8_IRQHandler(void)
345 {
346     rt_interrupt_enter();
347 
348     usart_isr(&usart_device8);
349 
350     rt_interrupt_leave();
351 }
352 #endif
353 
rt_hw_uart_init(void)354 int rt_hw_uart_init(void)
355 {
356     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
357 
358 #ifdef BSP_USING_UART1
359     usart_device1.parent.ops = &usart_ops;
360     usart_device1.parent.config = config;
361     rt_hw_serial_register(&usart_device1.parent, usart_device1.name,
362                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
363                           RT_NULL);
364 #endif
365 
366 #ifdef BSP_USING_UART2
367     usart_device2.parent.ops = &usart_ops;
368     usart_device2.parent.config = config;
369     rt_hw_serial_register(&usart_device2.parent, usart_device2.name,
370                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
371                           RT_NULL);
372 #endif
373 
374 #ifdef BSP_USING_UART3
375     usart_device3.parent.ops = &usart_ops;
376     usart_device3.parent.config = config;
377     rt_hw_serial_register(&usart_device3.parent, usart_device3.name,
378                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
379                           RT_NULL);
380 #endif
381 
382 #ifdef BSP_USING_UART4
383     usart_device4.parent.ops = &usart_ops;
384     usart_device4.parent.config = config;
385     rt_hw_serial_register(&usart_device4.parent, usart_device4.name,
386                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
387                           RT_NULL);
388 #endif
389 
390 #ifdef BSP_USING_UART5
391     usart_device5.parent.ops = &usart_ops;
392     usart_device5.parent.config = config;
393     rt_hw_serial_register(&usart_device5.parent, usart_device5.name,
394                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
395                           RT_NULL);
396 #endif
397 
398 #ifdef BSP_USING_UART6
399     usart_device6.parent.ops = &usart_ops;
400     usart_device6.parent.config = config;
401     rt_hw_serial_register(&usart_device6.parent, usart_device6.name,
402                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
403                           RT_NULL);
404 #endif
405 
406 #ifdef BSP_USING_UART7
407     usart_device7.parent.ops = &usart_ops;
408     usart_device7.parent.config = config;
409     rt_hw_serial_register(&usart_device7.parent, usart_device7.name,
410                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
411                           RT_NULL);
412 #endif
413 
414 #ifdef BSP_USING_UART8
415     usart_device8.parent.ops = &usart_ops;
416     usart_device8.parent.config = config;
417     rt_hw_serial_register(&usart_device8.parent, usart_device8.name,
418                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
419                           RT_NULL);
420 #endif
421 
422     return RT_EOK;
423 }
424 
425 #endif /* BSP_USING_UART */
426