1 /*
2  *
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Change Logs:
6  * Date           Author       Notes
7  * 2021-9-1       DongBowen    first version
8  */
9 
10 #include "drv_usart.h"
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "board.h"
14 
15 #ifdef RT_USING_SERIAL
16 #ifdef BSP_USING_UART
17 
18 #if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) && \
19     !defined(BSP_USING_UART3)
20     #error "Please define at least one BSP_USING_UARTx"
21     /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
22 #endif
23 
24 enum
25 {
26 #ifdef BSP_USING_UART0
27     UART0_INDEX,
28 #endif
29 #ifdef BSP_USING_UART1
30     UART1_INDEX,
31 #endif
32 #ifdef BSP_USING_UART2
33     UART2_INDEX,
34 #endif
35 #ifdef BSP_USING_UART3
36     UART3_INDEX,
37 #endif
38 };
39 
40 static struct hc_uart_cfg uart_cfg[] =
41 {
42 #ifdef BSP_USING_UART0
43     UART0_CFG,
44 #endif
45 #ifdef BSP_USING_UART1
46     UART1_CFG,
47 #endif
48 #ifdef BSP_USING_UART2
49     UART2_CFG,
50 #endif
51 #ifdef BSP_USING_UART3
52     UART3_CFG,
53 #endif
54 };
55 
56 static struct hc_uart uart_drv[sizeof(uart_cfg) / sizeof(uart_cfg[0])] = {0};
57 
_uart_init(struct rt_serial_device * serial_device,struct serial_configure * configure)58 static rt_err_t _uart_init(struct rt_serial_device *serial_device, struct serial_configure *configure)
59 {
60     stc_gpio_cfg_t stcGpioCfg;
61     stc_uart_cfg_t stcCfg;
62 
63     struct hc_uart_cfg *cfg;
64     RT_ASSERT(serial_device != RT_NULL);
65     RT_ASSERT(configure != RT_NULL);
66     cfg = serial_device->parent.user_data;
67 
68     /* configure rx and tx gpio */
69     rt_memset(&stcGpioCfg, 0, sizeof(stcGpioCfg));
70     Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
71     stcGpioCfg.enDir = GpioDirOut;
72     Gpio_Init(cfg->tx_port, cfg->tx_pin, &stcGpioCfg);
73     Gpio_SetAfMode(cfg->tx_port, cfg->tx_pin, cfg->tx_af);
74     stcGpioCfg.enDir = GpioDirIn;
75     Gpio_Init(cfg->rx_port, cfg->rx_pin, &stcGpioCfg);
76     Gpio_SetAfMode(cfg->rx_port, cfg->rx_pin, cfg->rx_af);
77 
78     /* configure uart */
79     rt_memset(&stcCfg, 0, sizeof(stcCfg));
80 
81     Sysctrl_SetPeripheralGate(cfg->uart_periph, TRUE);
82 
83     stcCfg.stcBaud.u32Baud = configure->baud_rate;
84     stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div;
85     stcCfg.stcBaud.u32Pclk = Sysctrl_GetPClkFreq();
86 
87     switch (configure->data_bits)
88     {
89     case DATA_BITS_8:
90         break;
91     default:
92         break;
93     }
94 
95     switch (configure->stop_bits)
96     {
97     case STOP_BITS_1:
98         stcCfg.enStopBit = UartMsk1bit;
99         break;
100     case STOP_BITS_2:
101         stcCfg.enStopBit = UartMsk2bit;
102         break;
103     default:
104         stcCfg.enStopBit = UartMsk1bit;
105         break;
106     }
107 
108     switch (configure->parity)
109     {
110     case PARITY_NONE:
111         stcCfg.enMmdorCk = UartMskDataOrAddr;
112         stcCfg.enRunMode = UartMskMode1;
113         break;
114     case PARITY_ODD:
115         stcCfg.enMmdorCk = UartMskOdd;
116         stcCfg.enRunMode = UartMskMode3;
117         break;
118     case PARITY_EVEN:
119         stcCfg.enMmdorCk = UartMskEven;
120         stcCfg.enRunMode = UartMskMode3;
121         break;
122     default:
123         stcCfg.enMmdorCk = UartMskDataOrAddr;
124         stcCfg.enRunMode = UartMskMode1;
125         break;
126     }
127 
128     Uart_Init(cfg->uart, &stcCfg);
129 
130     Uart_ClrStatus(cfg->uart, UartRC);
131     Uart_ClrStatus(cfg->uart, UartTC);
132 
133     rt_hw_us_delay(2);
134     return RT_EOK;
135 }
136 
_uart_control(struct rt_serial_device * serial_device,int cmd,void * arg)137 static rt_err_t _uart_control(struct rt_serial_device *serial_device, int cmd, void *arg)
138 {
139     struct hc_uart_cfg *cfg;
140     RT_ASSERT(serial_device != RT_NULL);
141     cfg = serial_device->parent.user_data;
142 
143     switch (cmd)
144     {
145     case RT_DEVICE_CTRL_CLR_INT:
146         /* disable rx irq */
147         Uart_DisableIrq(cfg->uart, UartRxIrq);
148         EnableNvic(cfg->irqn, IrqLevel3, FALSE);
149         break;
150     case RT_DEVICE_CTRL_SET_INT:
151         /* enable rx irq */
152         Uart_EnableIrq(cfg->uart, UartRxIrq);
153         EnableNvic(cfg->irqn, IrqLevel3, TRUE);
154         break;
155     }
156     return RT_EOK;
157 }
158 
_uart_putc(struct rt_serial_device * serial_device,char c)159 static int _uart_putc(struct rt_serial_device *serial_device, char c)
160 {
161     struct hc_uart_cfg *cfg;
162     RT_ASSERT(serial_device != RT_NULL);
163     cfg = serial_device->parent.user_data;
164 
165     Uart_SendDataPoll(cfg->uart, (uint8_t)c);
166     return 1;
167 }
168 
_uart_getc(struct rt_serial_device * serial_device)169 static int _uart_getc(struct rt_serial_device *serial_device)
170 {
171     int ch;
172     struct hc_uart_cfg *cfg;
173     RT_ASSERT(serial_device != RT_NULL);
174     cfg = serial_device->parent.user_data;
175 
176     ch = -1;
177 
178     if (Uart_GetStatus(cfg->uart, UartRC))
179     {
180         Uart_ClrStatus(cfg->uart, UartRC);
181         ch = Uart_ReceiveData(cfg->uart);
182     }
183 
184     return ch;
185 }
186 
187 static const struct rt_uart_ops _uart_ops =
188 {
189     .configure = _uart_init,
190     .control = _uart_control,
191     .putc = _uart_putc,
192     .getc = _uart_getc,
193     .dma_transmit = RT_NULL
194 };
195 
196 /**
197  * Uart common interrupt process. This need add to uart ISR.
198  *
199  * @param serial serial device
200  */
rt_hw_uart_isr(struct rt_serial_device * serial_device)201 static void rt_hw_uart_isr(struct rt_serial_device *serial_device)
202 {
203     struct hc_uart_cfg *cfg;
204     uint32_t status;
205     RT_ASSERT(serial_device != RT_NULL);
206 
207     cfg = serial_device->parent.user_data;
208     status = cfg->uart->ISR;
209 
210     /* UART in mode Receiver -------------------------------------------------*/
211     if (status & (1 << UartFE))
212     {
213         Uart_ClrStatus(cfg->uart, UartFE);
214     }
215     if (status & (1 << UartPE))
216     {
217         Uart_ClrStatus(cfg->uart, UartPE);
218     }
219     if (status & (1 << UartRC))
220     {
221         rt_hw_serial_isr(serial_device, RT_SERIAL_EVENT_RX_IND);
222     }
223 }
224 
225 #if defined(BSP_USING_UART0)
Uart0_IRQHandler(void)226 void Uart0_IRQHandler(void)
227 {
228     /* enter interrupt */
229     rt_interrupt_enter();
230 
231     rt_hw_uart_isr(&(uart_drv[UART0_INDEX].serial_device));
232 
233     /* leave interrupt */
234     rt_interrupt_leave();
235 }
236 #endif /* BSP_USING_UART0 */
237 
238 #if defined(BSP_USING_UART1)
Uart1_IRQHandler(void)239 void Uart1_IRQHandler(void)
240 {
241     /* enter interrupt */
242     rt_interrupt_enter();
243 
244     rt_hw_uart_isr(&(uart_drv[UART1_INDEX].serial_device));
245 
246     /* leave interrupt */
247     rt_interrupt_leave();
248 }
249 #endif /* BSP_USING_UART1 */
250 
251 #if defined(BSP_USING_UART2)
Uart2_IRQHandler(void)252 void Uart2_IRQHandler(void)
253 {
254     /* enter interrupt */
255     rt_interrupt_enter();
256 
257     rt_hw_uart_isr(&(uart_drv[UART2_INDEX].serial_device));
258 
259     /* leave interrupt */
260     rt_interrupt_leave();
261 }
262 #endif /* BSP_USING_UART2 */
263 
264 #if defined(BSP_USING_UART3)
Uart3_IRQHandler(void)265 void Uart3_IRQHandler(void)
266 {
267     /* enter interrupt */
268     rt_interrupt_enter();
269 
270     rt_hw_uart_isr(&(uart_drv[UART3_INDEX].serial_device));
271 
272     /* leave interrupt */
273     rt_interrupt_leave();
274 }
275 #endif /* BSP_USING_UART3 */
276 
rt_hw_uart_init(void)277 int rt_hw_uart_init(void)
278 {
279     struct serial_configure cfg = RT_SERIAL_CONFIG_DEFAULT;
280     int i = 0;
281     rt_err_t result = RT_EOK;
282 
283     for (i = 0; i < sizeof(uart_cfg) / sizeof(uart_cfg[0]); i++)
284     {
285         uart_drv[i].cfg = &uart_cfg[i];
286         uart_drv[i].serial_device.ops = &_uart_ops;
287         uart_drv[i].serial_device.config = cfg;
288         /* register UART device */
289         result = rt_hw_serial_register(&uart_drv[i].serial_device, uart_drv[i].cfg->name,
290                                        RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart_drv[i].cfg);
291         RT_ASSERT(result == RT_EOK);
292     }
293 
294     return result;
295 }
296 INIT_BOARD_EXPORT(rt_hw_uart_init);
297 
298 #endif /* BSP_USING_UART */
299 #endif /* RT_USING_SERIAL */
300