1 /*
2  * Copyright (c) 2006-2024, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2024-04-08     QT-one       first version
9  */
10 
11 #include "drv_usart.h"
12 
13 #ifdef RT_USING_SERIAL
14 #if !defined(BSP_USING_USART0) && !defined(BSP_USING_USART1) && \
15     !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && \
16     !defined(BSP_USING_UART2) && !defined(BSP_USING_UART3)
17     #error "Please define at least one BSP_USING_UARTx"
18 #endif
19 
20 struct ht32_usart
21 {
22     char *name;
23     HT_USART_TypeDef *usart_x;
24     IRQn_Type irq;
25     struct rt_serial_device serial;
26 };
27 
28 enum
29 {
30 #ifdef BSP_USING_USART0
31     USART0_INDEX,
32 #endif
33 #ifdef BSP_USING_USART1
34     USART1_INDEX,
35 #endif
36 #ifdef BSP_USING_UART0
37     UART0_INDEX,
38 #endif
39 #ifdef BSP_USING_UART1
40     UART1_INDEX,
41 #endif
42 #ifdef BSP_USING_UART2
43     UART2_INDEX,
44 #endif
45 #ifdef BSP_USING_UART3
46     UART3_INDEX,
47 #endif
48 
49 };
50 
51 static struct ht32_usart usart_config[] =
52 {
53 #ifdef BSP_USING_USART0
54     {
55     .name           = BSP_USING_USART0_NAME,
56     .usart_x        = HT_USART0,
57     .irq            = USART0_IRQn,
58     .serial         = RT_NULL
59     },
60 #endif
61 #ifdef BSP_USING_USART1
62     {
63     .name           = BSP_USING_USART1_NAME,
64     .usart_x        = HT_USART1,
65     .irq            = USART1_IRQn,
66     .serial         = RT_NULL
67     },
68 #endif
69 #ifdef BSP_USING_UART0
70     {
71     .name           = BSP_USING_UART0_NAME,
72     .usart_x        = HT_UART0,
73     .irq            = UART0_IRQn,
74     .serial         = RT_NULL
75     },
76 #endif
77 #ifdef BSP_USING_UART1
78     {
79     .name           = BSP_USING_UART1_NAME,
80     .usart_x        = HT_UART1,
81     .irq            = UART1_IRQn,
82     .serial         = RT_NULL
83     },
84 #endif
85 #ifdef BSP_USING_UART2
86     {
87     .name           = BSP_USING_UART2_NAME,
88     .usart_x        = HT_UART2,
89     .irq            = UART0_UART2_IRQn,
90     .serial         = RT_NULL
91     },
92 #endif
93 #ifdef BSP_USING_UART3
94     {
95     .name           = BSP_USING_UART3_NAME,
96     .usart_x        = HT_UART3,
97     .irq            = UART1_UART3_IRQn,
98     .serial         = RT_NULL
99     },
100 #endif
101 };
102 
ht32_configure(struct rt_serial_device * serial,struct serial_configure * cfg)103 static rt_err_t ht32_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
104 {
105 
106     CKCU_PeripClockConfig_TypeDef   CKCUClock               = {{0}};
107     USART_InitTypeDef               USART_InitStructure     = {0};
108 
109     struct ht32_usart *usart_instance = (struct ht32_usart *)serial->parent.user_data;
110 
111     RT_ASSERT(serial != RT_NULL);
112     RT_ASSERT(cfg != RT_NULL);
113 
114     CKCUClock.Bit.AFIO = 1;
115 
116     if ((usart_instance->usart_x) == HT_UART0)
117         CKCUClock.Bit.UART0 = 1;
118 #if defined(HT_USART0)
119     else if ((usart_instance->usart_x) == HT_USART0)
120         CKCUClock.Bit.USART0 = 1;
121 #endif
122 #if defined(HT_USART1)
123     else if ((usart_instance->usart_x) == HT_USART1)
124         CKCUClock.Bit.USART1 = 1;
125 #endif
126 #if defined(HT_UART1)
127     else if ((usart_instance->usart_x) == HT_UART1)
128         CKCUClock.Bit.UART1 = 1;
129 #endif
130 #if defined(HT_UART2)
131     else if ((usart_instance->usart_x) == HT_UART2)
132         CKCUClock.Bit.UART2 = 1;
133 #endif
134 #if defined(HT_UART3)
135     else if ((usart_instance->usart_x) == HT_UART3)
136         CKCUClock.Bit.UART3 = 1;
137 #endif
138     CKCU_PeripClockConfig(CKCUClock, ENABLE);
139 
140     /* UART gpio init */
141     ht32_usart_gpio_init((void *)usart_instance->usart_x);
142 
143     /* baud rate */
144     USART_InitStructure.USART_BaudRate = (cfg->baud_rate);
145 
146     /* data width */
147     switch (cfg->data_bits)
148     {
149     case DATA_BITS_7:
150         USART_InitStructure.USART_WordLength = USART_WORDLENGTH_7B;
151         break;
152     case DATA_BITS_8:
153         USART_InitStructure.USART_WordLength = USART_WORDLENGTH_8B;
154         break;
155     case DATA_BITS_9:
156         USART_InitStructure.USART_WordLength = USART_WORDLENGTH_9B;
157         break;
158     default:
159         USART_InitStructure.USART_WordLength = USART_WORDLENGTH_8B;
160         break;
161     }
162 
163     /* stop bit */
164     switch (cfg->stop_bits)
165     {
166     case STOP_BITS_1:
167         USART_InitStructure.USART_StopBits = USART_STOPBITS_1;
168         break;
169     case STOP_BITS_2:
170         USART_InitStructure.USART_StopBits = USART_STOPBITS_2;
171         break;
172     default:
173         USART_InitStructure.USART_StopBits = USART_STOPBITS_1;
174         break;
175     }
176 
177     switch (cfg->parity)
178     {
179     case PARITY_NONE:
180         USART_InitStructure.USART_Parity = USART_PARITY_NO;
181         break;
182     case PARITY_ODD:
183         USART_InitStructure.USART_Parity = USART_PARITY_ODD;
184         break;
185     case PARITY_EVEN:
186         USART_InitStructure.USART_Parity = USART_PARITY_EVEN;
187         break;
188     default:
189         USART_InitStructure.USART_Parity = USART_PARITY_NO;
190         break;
191     }
192 
193     /* UART mode */
194     USART_InitStructure.USART_Mode = USART_MODE_NORMAL;
195     /* UART init */
196     USART_Init((usart_instance->usart_x), &USART_InitStructure);
197     /*UART enable */
198     USART_TxCmd((usart_instance->usart_x), ENABLE);
199     USART_RxCmd((usart_instance->usart_x), ENABLE);
200 
201     return RT_EOK;
202 }
203 
ht32_control(struct rt_serial_device * serial,int cmd,void * arg)204 static rt_err_t ht32_control(struct rt_serial_device *serial, int cmd, void *arg)
205 {
206     struct ht32_usart *usart;
207 
208     RT_ASSERT(serial != RT_NULL);
209     usart = (struct ht32_usart *) serial->parent.user_data;
210     RT_ASSERT(usart != RT_NULL);
211 
212     switch (cmd)
213     {
214     case RT_DEVICE_CTRL_CLR_INT:
215         NVIC_DisableIRQ(usart->irq);
216         USART_IntConfig(usart->usart_x, USART_INT_RXDR, DISABLE);
217         break;
218     case RT_DEVICE_CTRL_SET_INT:
219         NVIC_EnableIRQ(usart->irq);
220         USART_IntConfig(usart->usart_x, USART_INT_RXDR, ENABLE);
221         break;
222     }
223     return RT_EOK;
224 }
225 
ht32_putc(struct rt_serial_device * serial,char c)226 static int ht32_putc(struct rt_serial_device *serial, char c)
227 {
228     struct ht32_usart *usart;
229 
230     RT_ASSERT(serial != RT_NULL);
231     usart = (struct ht32_usart *) serial->parent.user_data;
232     RT_ASSERT(usart != RT_NULL);
233 
234     while ((usart->usart_x->SR & USART_FLAG_TXC) == 0);
235     usart->usart_x->DR = (u8)c;
236 
237     return 1;
238 }
239 
ht32_getc(struct rt_serial_device * serial)240 static int ht32_getc(struct rt_serial_device *serial)
241 {
242     int ch;
243     struct ht32_usart *usart;
244 
245     RT_ASSERT(serial != RT_NULL);
246     usart = (struct ht32_usart *) serial->parent.user_data;
247     RT_ASSERT(usart != RT_NULL);
248 
249     ch = -1;
250     if (USART_GetFlagStatus(usart->usart_x, USART_FLAG_RXDR) != RESET)
251     {
252         ch = USART_ReceiveData(usart->usart_x);
253     }
254     return ch;
255 }
256 
ht32_dma_transmit(struct rt_serial_device * serial,rt_uint8_t * buf,rt_size_t size,int direction)257 static rt_ssize_t ht32_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction)
258 {
259     return -RT_ERROR;
260 }
261 
262 static const struct rt_uart_ops ht32_usart_ops =
263 {
264     .configure      = ht32_configure,
265     .control        = ht32_control,
266     .putc           = ht32_putc,
267     .getc           = ht32_getc,
268     .dma_transmit   = ht32_dma_transmit,
269 };
270 
rt_hw_usart_init(void)271 int rt_hw_usart_init(void)
272 {
273     rt_size_t obj_num;
274     int index;
275 
276     obj_num = sizeof(usart_config) / sizeof(struct ht32_usart);
277     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
278     rt_err_t result = 0;
279 
280     for (index = 0; index < obj_num; index++)
281     {
282         usart_config[index].serial.ops = &ht32_usart_ops;
283         usart_config[index].serial.config = config;
284 
285         /* register uart device */
286         result = rt_hw_serial_register(&usart_config[index].serial,
287                                        usart_config[index].name,
288                                        RT_DEVICE_FLAG_RDWR |
289                                        RT_DEVICE_FLAG_INT_RX |
290                                        RT_DEVICE_FLAG_INT_TX,
291                                        &usart_config[index]);
292         RT_ASSERT(result == RT_EOK);
293     }
294 
295     return result;
296 }
297 INIT_BOARD_EXPORT(rt_hw_usart_init);
298 
usart_isr(struct rt_serial_device * serial)299 static void usart_isr(struct rt_serial_device *serial)
300 {
301 
302     struct ht32_usart *usart = (struct ht32_usart *)serial->parent.user_data;
303     RT_ASSERT(usart != RT_NULL);
304 
305     if ((USART_GetFlagStatus(usart->usart_x, USART_FLAG_RXDR) != RESET) && ((usart->usart_x->IER & USART_INT_RXDR) != RESET))
306     {
307         rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
308     }
309 }
310 
311 #ifdef BSP_USING_USART0
USART0_IRQHandler(void)312 void USART0_IRQHandler(void)
313 {
314     /* enter interrupt */
315     rt_interrupt_enter();
316     usart_isr(&usart_config[USART0_INDEX].serial);
317     /* leave interrupt */
318     rt_interrupt_leave();
319 }
320 #endif
321 #ifdef BSP_USING_USART1
USART1_IRQHandler(void)322 void USART1_IRQHandler(void)
323 {
324     /* enter interrupt */
325     rt_interrupt_enter();
326     usart_isr(&usart_config[USART1_INDEX].serial);
327     /* leave interrupt */
328     rt_interrupt_leave();
329 }
330 #endif
331 #ifdef BSP_USING_UART0
UART0_IRQHandler(void)332 void UART0_IRQHandler(void)
333 {
334     /* enter interrupt */
335     rt_interrupt_enter();
336     usart_isr(&usart_config[UART0_INDEX].serial);
337     /* leave interrupt */
338     rt_interrupt_leave();
339 }
340 #endif
341 #ifdef BSP_USING_UART1
UART1_IRQHandler(void)342 void UART1_IRQHandler(void)
343 {
344     /* enter interrupt */
345     rt_interrupt_enter();
346     usart_isr(&usart_config[UART1_INDEX].serial);
347     /* leave interrupt */
348     rt_interrupt_leave();
349 }
350 #endif
351 #ifdef BSP_USING_UART2
UART2_IRQHandler(void)352 void UART2_IRQHandler(void)
353 {
354     /* enter interrupt */
355     rt_interrupt_enter();
356     usart_isr(&usart_config[UART2_INDEX].serial);
357     /* leave interrupt */
358     rt_interrupt_leave();
359 }
360 #endif
361 #ifdef BSP_USING_UART3
UART3_IRQHandler(void)362 void UART3_IRQHandler(void)
363 {
364     /* enter interrupt */
365     rt_interrupt_enter();
366     usart_isr(&usart_config[UART3_INDEX].serial);
367     /* leave interrupt */
368     rt_interrupt_leave();
369 }
370 #endif
371 
372 #endif /* RT_USING_SERIAL */
373