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  * 2017-10-10     Tanek        the first version
9  * 2019-5-10      misonyo      add DMA TX and RX function
10  */
11 
12 #include <rtthread.h>
13 #ifdef BSP_USING_LPUART
14 
15 #include "rthw.h"
16 #include <rtdevice.h>
17 #include "drv_uart.h"
18 #include "board.h"
19 #include "fsl_lpuart.h"
20 #include "fsl_lpuart_edma.h"
21 #include "fsl_dmamux.h"
22 
23 #define LOG_TAG             "drv.usart"
24 #include <drv_log.h>
25 
26 #if defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL
27     #error "Please don't define 'FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL'!"
28 #endif
29 
30 enum
31 {
32 #ifdef BSP_USING_LPUART1
33     LPUART1_INDEX,
34 #endif
35 #ifdef BSP_USING_LPUART2
36     LPUART2_INDEX,
37 #endif
38 #ifdef BSP_USING_LPUART3
39     LPUART3_INDEX,
40 #endif
41 #ifdef BSP_USING_LPUART4
42     LPUART4_INDEX,
43 #endif
44 #ifdef BSP_USING_LPUART5
45     LPUART5_INDEX,
46 #endif
47 #ifdef BSP_USING_LPUART6
48     LPUART6_INDEX,
49 #endif
50 #ifdef BSP_USING_LPUART7
51     LPUART7_INDEX,
52 #endif
53 #ifdef BSP_USING_LPUART8
54     LPUART8_INDEX,
55 #endif
56 };
57 
58 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
59 struct dma_rx_config
60 {
61     edma_handle_t edma;
62     dma_request_source_t request;
63     rt_uint8_t channel;
64     rt_uint32_t last_index;
65 };
66 
67 struct dma_tx_config
68 {
69     edma_handle_t edma;
70     lpuart_edma_handle_t uart_edma;
71     dma_request_source_t request;
72     rt_uint8_t channel;
73 };
74 
75 #endif
76 
77 struct imxrt_uart
78 {
79     char *name;
80     LPUART_Type *uart_base;
81     IRQn_Type irqn;
82 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
83     struct dma_rx_config *dma_rx;
84     struct dma_tx_config *dma_tx;
85 #endif
86     rt_uint16_t dma_flag;
87     struct rt_serial_device serial;
88 };
89 
90 static struct imxrt_uart uarts[] =
91 {
92 #ifdef BSP_USING_LPUART1
93     {
94         .name = "uart1",
95         .uart_base = LPUART1,
96         .irqn = LPUART1_IRQn,
97 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
98         .dma_rx = RT_NULL,
99         .dma_tx = RT_NULL,
100 #endif
101         .dma_flag = 0,
102     },
103 #endif
104 #ifdef BSP_USING_LPUART2
105     {
106         .name = "uart2",
107         .uart_base = LPUART2,
108         .irqn = LPUART2_IRQn,
109 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
110         .dma_rx = RT_NULL,
111         .dma_tx = RT_NULL,
112 #endif
113         .dma_flag = 0,
114     },
115 #endif
116 #ifdef BSP_USING_LPUART3
117     {
118         .name = "uart3",
119         .uart_base = LPUART3,
120         .irqn = LPUART3_IRQn,
121 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
122         .dma_rx = RT_NULL,
123         .dma_tx = RT_NULL,
124 #endif
125         .dma_flag = 0,
126     },
127 #endif
128 #ifdef BSP_USING_LPUART4
129     {
130         .name = "uart4",
131         .uart_base = LPUART4,
132         .irqn = LPUART4_IRQn,
133 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
134         .dma_rx = RT_NULL,
135         .dma_tx = RT_NULL,
136 #endif
137         .dma_flag = 0,
138     },
139 #endif
140 #ifdef BSP_USING_LPUART5
141     {
142         .name = "uart5",
143         .uart_base = LPUART5,
144         .irqn = LPUART5_IRQn,
145 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
146         .dma_rx = RT_NULL,
147         .dma_tx = RT_NULL,
148 #endif
149         .dma_flag = 0,
150     },
151 #endif
152 #ifdef BSP_USING_LPUART6
153     {
154         .name = "uart6",
155         .uart_base = LPUART6,
156         .irqn = LPUART6_IRQn,
157 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
158         .dma_rx = RT_NULL,
159         .dma_tx = RT_NULL,
160 #endif
161         .dma_flag = 0,
162     },
163 #endif
164 #ifdef BSP_USING_LPUART7
165     {
166         .name = "uart7",
167         .uart_base = LPUART7,
168         .irqn = LPUART7_IRQn,
169 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
170         .dma_rx = RT_NULL,
171         .dma_tx = RT_NULL,
172 #endif
173         .dma_flag = 0,
174     },
175 #endif
176 #ifdef BSP_USING_LPUART8
177     {
178         .name = "uart8",
179         .uart_base = LPUART8,
180         .irqn = LPUART8_IRQn,
181 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
182         .dma_rx = RT_NULL,
183         .dma_tx = RT_NULL,
184 #endif
185         .dma_flag = 0,
186     },
187 #endif
188 };
189 
uart_get_dma_config(void)190 static void uart_get_dma_config(void)
191 {
192 #ifdef BSP_LPUART1_RX_USING_DMA
193     static struct dma_rx_config uart1_dma_rx = {.request = kDmaRequestMuxLPUART1Rx, .channel = BSP_LPUART1_RX_DMA_CHANNEL, .last_index = 0};
194     uarts[LPUART1_INDEX].dma_rx = &uart1_dma_rx;
195     uarts[LPUART1_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_RX;
196 #endif
197 #ifdef BSP_LPUART1_TX_USING_DMA
198     static struct dma_tx_config uart1_dma_tx = {.request = kDmaRequestMuxLPUART1Tx, .channel = BSP_LPUART1_TX_DMA_CHANNEL};
199     uarts[LPUART1_INDEX].dma_tx = &uart1_dma_tx;
200     uarts[LPUART1_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_TX;
201 #endif
202 
203 #ifdef BSP_LPUART2_RX_USING_DMA
204     static struct dma_rx_config uart2_dma_rx = {.request = kDmaRequestMuxLPUART2Rx, .channel = BSP_LPUART2_RX_DMA_CHANNEL, .last_index = 0};
205     uarts[LPUART2_INDEX].dma_rx = &uart2_dma_rx;
206     uarts[LPUART2_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_RX;
207 #endif
208 #ifdef BSP_LPUART2_TX_USING_DMA
209     static struct dma_tx_config uart2_dma_tx = {.request = kDmaRequestMuxLPUART2Tx, .channel = BSP_LPUART2_TX_DMA_CHANNEL};
210     uarts[LPUART2_INDEX].dma_tx = &uart2_dma_tx;
211     uarts[LPUART2_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_TX;
212 #endif
213 
214 #ifdef BSP_LPUART3_RX_USING_DMA
215     static struct dma_rx_config uart3_dma_rx = {.request = kDmaRequestMuxLPUART3Rx, .channel = BSP_LPUART3_RX_DMA_CHANNEL, .last_index = 0};
216     uarts[LPUART3_INDEX].dma_rx = &uart3_dma_rx;
217     uarts[LPUART3_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_RX;
218 #endif
219 #ifdef BSP_LPUART3_TX_USING_DMA
220     static struct dma_tx_config uart3_dma_tx = {.request = kDmaRequestMuxLPUART3Tx, .channel = BSP_LPUART3_TX_DMA_CHANNEL};
221     uarts[LPUART3_INDEX].dma_tx = &uart3_dma_tx;
222     uarts[LPUART3_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_TX;
223 #endif
224 
225 #ifdef BSP_LPUART4_RX_USING_DMA
226     static struct dma_rx_config uart4_dma_rx = {.request = kDmaRequestMuxLPUART4Rx, .channel = BSP_LPUART4_RX_DMA_CHANNEL, .last_index = 0};
227     uarts[LPUART4_INDEX].dma_rx = &uart4_dma_rx;
228     uarts[LPUART4_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_RX;
229 #endif
230 #ifdef BSP_LPUART4_TX_USING_DMA
231     static struct dma_tx_config uart4_dma_tx = {.request = kDmaRequestMuxLPUART4Tx, .channel = BSP_LPUART4_TX_DMA_CHANNEL};
232     uarts[LPUART4_INDEX].dma_tx = &uart4_dma_tx;
233     uarts[LPUART4_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_TX;
234 #endif
235 
236 #ifdef BSP_LPUART5_RX_USING_DMA
237     static struct dma_rx_config uart5_dma_rx = {.request = kDmaRequestMuxLPUART5Rx, .channel = BSP_LPUART5_RX_DMA_CHANNEL, .last_index = 0};
238     uarts[LPUART5_INDEX].dma_rx = &uart5_dma_rx;
239     uarts[LPUART5_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_RX;
240 #endif
241 #ifdef BSP_LPUART5_TX_USING_DMA
242     static struct dma_tx_config uart5_dma_tx = {.request = kDmaRequestMuxLPUART5Tx, .channel = BSP_LPUART5_TX_DMA_CHANNEL};
243     uarts[LPUART5_INDEX].dma_tx = &uart5_dma_tx;
244     uarts[LPUART5_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_TX;
245 #endif
246 
247 #ifdef BSP_LPUART6_RX_USING_DMA
248     static struct dma_rx_config uart6_dma_rx = {.request = kDmaRequestMuxLPUART6Rx, .channel = BSP_LPUART6_RX_DMA_CHANNEL, .last_index = 0};
249     uarts[LPUART6_INDEX].dma_rx = &uart6_dma_rx;
250     uarts[LPUART6_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_RX;
251 #endif
252 #ifdef BSP_LPUART6_TX_USING_DMA
253     static struct dma_tx_config uart6_dma_tx = {.request = kDmaRequestMuxLPUART6Tx, .channel = BSP_LPUART6_TX_DMA_CHANNEL};
254     uarts[LPUART6_INDEX].dma_tx = &uart6_dma_tx;
255     uarts[LPUART6_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_TX;
256 #endif
257 
258 #ifdef BSP_LPUART7_RX_USING_DMA
259     static struct dma_rx_config uart7_dma_rx = {.request = kDmaRequestMuxLPUART7Rx, .channel = BSP_LPUART7_RX_DMA_CHANNEL, .last_index = 0};
260     uarts[LPUART7_INDEX].dma_rx = &uart7_dma_rx;
261     uarts[LPUART7_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_RX;
262 #endif
263 #ifdef BSP_LPUART7_TX_USING_DMA
264     static struct dma_tx_config uart7_dma_tx = {.request = kDmaRequestMuxLPUART7Tx, .channel = BSP_LPUART7_TX_DMA_CHANNEL};
265     uarts[LPUART7_INDEX].dma_tx = &uart7_dma_tx;
266     uarts[LPUART7_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_TX;
267 #endif
268 
269 #ifdef BSP_LPUART8_RX_USING_DMA
270     static struct dma_rx_config uart8_dma_rx = {.request = kDmaRequestMuxLPUART8Rx, .channel = BSP_LPUART8_RX_DMA_CHANNEL, .last_index = 0};
271     uarts[LPUART8_INDEX].dma_rx = &uart8_dma_rx;
272     uarts[LPUART8_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_RX;
273 #endif
274 #ifdef BSP_LPUART8_TX_USING_DMA
275     static struct dma_tx_config uart8_dma_tx = {.request = kDmaRequestMuxLPUART8Tx, .channel = BSP_LPUART8_TX_DMA_CHANNEL};
276     uarts[LPUART8_INDEX].dma_tx = &uart8_dma_tx;
277     uarts[LPUART8_INDEX].dma_flag |= RT_DEVICE_FLAG_DMA_TX;
278 #endif
279 }
280 
281 static void uart_isr(struct imxrt_uart *uart);
282 
283 #if defined(BSP_USING_LPUART1)
284 
LPUART1_IRQHandler(void)285 void LPUART1_IRQHandler(void)
286 {
287     rt_interrupt_enter();
288 
289     uart_isr(&uarts[LPUART1_INDEX]);
290 
291     rt_interrupt_leave();
292 }
293 
294 #endif /* BSP_USING_LPUART1 */
295 
296 #if defined(BSP_USING_LPUART2)
297 struct rt_serial_device serial2;
298 
LPUART2_IRQHandler(void)299 void LPUART2_IRQHandler(void)
300 {
301     rt_interrupt_enter();
302 
303     uart_isr(&uarts[LPUART2_INDEX]);
304 
305     rt_interrupt_leave();
306 }
307 
308 #endif /* BSP_USING_LPUART2 */
309 
310 #if defined(BSP_USING_LPUART3)
311 struct rt_serial_device serial3;
312 
LPUART3_IRQHandler(void)313 void LPUART3_IRQHandler(void)
314 {
315     rt_interrupt_enter();
316 
317     uart_isr(&uarts[LPUART3_INDEX]);
318 
319     rt_interrupt_leave();
320 }
321 
322 #endif /* BSP_USING_LPUART3 */
323 
324 #if defined(BSP_USING_LPUART4)
325 
LPUART4_IRQHandler(void)326 void LPUART4_IRQHandler(void)
327 {
328     rt_interrupt_enter();
329 
330     uart_isr(&uarts[LPUART4_INDEX]);
331 
332     rt_interrupt_leave();
333 }
334 
335 #endif /* BSP_USING_LPUART4 */
336 
337 #if defined(BSP_USING_LPUART5)
338 struct rt_serial_device serial5;
339 
LPUART5_IRQHandler(void)340 void LPUART5_IRQHandler(void)
341 {
342     rt_interrupt_enter();
343 
344     uart_isr(&uarts[LPUART5_INDEX]);
345 
346     rt_interrupt_leave();
347 }
348 
349 #endif /* BSP_USING_LPUART5 */
350 
351 #if defined(BSP_USING_LPUART6)
352 struct rt_serial_device serial6;
353 
LPUART6_IRQHandler(void)354 void LPUART6_IRQHandler(void)
355 {
356     rt_interrupt_enter();
357 
358     uart_isr(&uarts[LPUART6_INDEX]);
359 
360     rt_interrupt_leave();
361 }
362 
363 #endif /* BSP_USING_LPUART6 */
364 
365 #if defined(BSP_USING_LPUART7)
366 struct rt_serial_device serial7;
367 
LPUART7_IRQHandler(void)368 void LPUART7_IRQHandler(void)
369 {
370     rt_interrupt_enter();
371 
372     uart_isr(&uarts[LPUART7_INDEX]);
373 
374     rt_interrupt_leave();
375 }
376 
377 #endif /* BSP_USING_LPUART7 */
378 
379 #if defined(BSP_USING_LPUART8)
380 struct rt_serial_device serial8;
381 
LPUART8_IRQHandler(void)382 void LPUART8_IRQHandler(void)
383 {
384     rt_interrupt_enter();
385 
386     uart_isr(&uarts[LPUART8_INDEX]);
387 
388     rt_interrupt_leave();
389 }
390 
391 #endif /* BSP_USING_LPUART8 */
392 
uart_isr(struct imxrt_uart * uart)393 static void uart_isr(struct imxrt_uart *uart)
394 {
395     RT_ASSERT(uart != RT_NULL);
396 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
397     rt_size_t total_index, recv_len;
398     rt_base_t level;
399 #endif
400 
401     /* kLPUART_RxDataRegFullFlag can only cleared or set by hardware */
402     if (LPUART_GetStatusFlags(uart->uart_base) & kLPUART_RxDataRegFullFlag)
403     {
404         rt_hw_serial_isr(&uart->serial, RT_SERIAL_EVENT_RX_IND);
405     }
406 
407     if (LPUART_GetStatusFlags(uart->uart_base) & kLPUART_RxOverrunFlag)
408     {
409         /* Clear overrun flag, otherwise the RX does not work. */
410         LPUART_ClearStatusFlags(uart->uart_base, kLPUART_RxOverrunFlag);
411     }
412 
413 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
414     if ((LPUART_GetStatusFlags(uart->uart_base) & kLPUART_IdleLineFlag) && (uart->dma_rx != RT_NULL))
415     {
416         LPUART_ClearStatusFlags(uart->uart_base, kLPUART_IdleLineFlag);
417         level = rt_hw_interrupt_disable();
418 
419         total_index = uart->serial.config.bufsz - EDMA_GetRemainingMajorLoopCount(DMA0, uart->dma_rx->channel);
420         if (total_index > uart->dma_rx->last_index)
421         {
422             recv_len = total_index - uart->dma_rx->last_index;
423         }
424         else
425         {
426             recv_len = total_index + (uart->serial.config.bufsz - uart->dma_rx->last_index);
427         }
428 
429         if ((recv_len > 0) && (recv_len < uart->serial.config.bufsz))
430         {
431             uart->dma_rx->last_index = total_index;
432             rt_hw_interrupt_enable(level);
433 
434             rt_hw_serial_isr(&uart->serial, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8));
435         }
436         else
437         {
438             rt_hw_interrupt_enable(level);
439         }
440     }
441 #endif
442 }
443 
444 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
edma_rx_callback(struct _edma_handle * handle,void * userData,bool transferDone,uint32_t tcds)445 void edma_rx_callback(struct _edma_handle *handle, void *userData, bool transferDone, uint32_t tcds)
446 {
447     rt_size_t total_index, recv_len;
448     rt_base_t level;
449     struct imxrt_uart *uart = (struct imxrt_uart *)userData;
450     RT_ASSERT(uart != RT_NULL);
451 
452     if (transferDone)
453     {
454         level = rt_hw_interrupt_disable();
455 
456         if ((EDMA_GetChannelStatusFlags(DMA0, uart->dma_rx->channel) & kEDMA_DoneFlag) != 0U)
457         {
458             /* clear full interrupt */
459             EDMA_ClearChannelStatusFlags(DMA0, uart->dma_rx->channel,kEDMA_DoneFlag);
460 
461             recv_len = uart->serial.config.bufsz - uart->dma_rx->last_index;
462             uart->dma_rx->last_index = 0;
463         }
464         else
465         {
466             /* clear half interrupt */
467             EDMA_ClearChannelStatusFlags(DMA0, uart->dma_rx->channel,kEDMA_InterruptFlag);
468 
469             total_index = uart->serial.config.bufsz - EDMA_GetRemainingMajorLoopCount(DMA0, uart->dma_rx->channel);
470             if (total_index > uart->dma_rx->last_index)
471             {
472                 recv_len = total_index - uart->dma_rx->last_index;
473             }
474             else
475             {
476                 recv_len = total_index + (uart->serial.config.bufsz - uart->dma_rx->last_index);
477             }
478             uart->dma_rx->last_index = total_index;
479         }
480 
481         rt_hw_interrupt_enable(level);
482 
483         if (recv_len)
484         {
485             rt_hw_serial_isr(&uart->serial, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8));
486         }
487     }
488 }
489 
edma_tx_callback(LPUART_Type * base,lpuart_edma_handle_t * handle,status_t status,void * userData)490 void edma_tx_callback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData)
491 {
492     struct imxrt_uart *uart = (struct imxrt_uart *)userData;
493     RT_ASSERT(uart != RT_NULL);
494 
495     if (kStatus_LPUART_TxIdle == status)
496     {
497         rt_hw_serial_isr(&uart->serial, RT_SERIAL_EVENT_TX_DMADONE);
498     }
499 }
500 
imxrt_dma_rx_config(struct imxrt_uart * uart)501 static void imxrt_dma_rx_config(struct imxrt_uart *uart)
502 {
503     RT_ASSERT(uart != RT_NULL);
504 
505     edma_transfer_config_t xferConfig;
506     struct rt_serial_rx_fifo *rx_fifo;
507 
508     DMAMUX_SetSource(DMAMUX, uart->dma_rx->channel, uart->dma_rx->request);
509     DMAMUX_EnableChannel(DMAMUX, uart->dma_rx->channel);
510     EDMA_CreateHandle(&uart->dma_rx->edma, DMA0, uart->dma_rx->channel);
511     EDMA_SetCallback(&uart->dma_rx->edma, edma_rx_callback, uart);
512 
513     rx_fifo = (struct rt_serial_rx_fifo *)uart->serial.serial_rx;
514 
515     EDMA_PrepareTransfer(&xferConfig,
516                          (void *)LPUART_GetDataRegisterAddress(uart->uart_base),
517                          sizeof(uint8_t),
518                          rx_fifo->buffer,
519                          sizeof(uint8_t),
520                          sizeof(uint8_t),
521                          uart->serial.config.bufsz,
522                          kEDMA_PeripheralToMemory);
523 
524     EDMA_SubmitTransfer(&uart->dma_rx->edma, &xferConfig);
525     EDMA_EnableChannelInterrupts(DMA0, uart->dma_rx->channel, kEDMA_MajorInterruptEnable | kEDMA_HalfInterruptEnable);
526     EDMA_EnableAutoStopRequest(DMA0, uart->dma_rx->channel, false);
527     /* complement to adjust final destination address */
528     uart->dma_rx->edma.base->TCD[uart->dma_rx->channel].DLAST_SGA = -(uart->serial.config.bufsz);
529     EDMA_StartTransfer(&uart->dma_rx->edma);
530     LPUART_EnableRxDMA(uart->uart_base, true);
531 
532     LPUART_EnableInterrupts(uart->uart_base, kLPUART_IdleLineInterruptEnable);
533     NVIC_SetPriority(uart->irqn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 4, 0));
534     EnableIRQ(uart->irqn);
535 
536     LOG_D("%s dma rx config done\n", uart->name);
537 }
538 
imxrt_dma_tx_config(struct imxrt_uart * uart)539 static void imxrt_dma_tx_config(struct imxrt_uart *uart)
540 {
541     RT_ASSERT(uart != RT_NULL);
542 
543     DMAMUX_SetSource(DMAMUX, uart->dma_tx->channel, uart->dma_tx->request);
544     DMAMUX_EnableChannel(DMAMUX, uart->dma_tx->channel);
545     EDMA_CreateHandle(&uart->dma_tx->edma, DMA0, uart->dma_tx->channel);
546 
547     LPUART_TransferCreateHandleEDMA(uart->uart_base,
548                                     &uart->dma_tx->uart_edma,
549                                     edma_tx_callback,
550                                     uart,
551                                     &uart->dma_tx->edma,
552                                     RT_NULL);
553 
554     LOG_D("%s dma tx config done\n", uart->name);
555 }
556 
557 #endif
558 
GetUartSrcFreq(LPUART_Type * uart_base)559 uint32_t GetUartSrcFreq(LPUART_Type *uart_base)
560 {
561     uint32_t freq;
562 #ifdef SOC_IMXRT1170_SERIES
563     uint32_t base = (uint32_t) uart_base;
564     switch (base)
565     {
566     case LPUART1_BASE:
567         freq = CLOCK_GetRootClockFreq(kCLOCK_Root_Lpuart1);
568         break;
569     case LPUART12_BASE:
570         freq = CLOCK_GetRootClockFreq(kCLOCK_Root_Lpuart12);
571         break;
572     default:
573         freq = CLOCK_GetRootClockFreq(kCLOCK_Root_Lpuart2);
574         break;
575     }
576 #else
577     /* To make it simple, we assume default PLL and divider settings, and the only variable
578        from application is use PLL3 source or OSC source */
579     if (CLOCK_GetMux(kCLOCK_UartMux) == 0) /* PLL3 div6 80M */
580     {
581         freq = (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6U) / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U);
582     }
583     else
584     {
585         freq = CLOCK_GetOscFreq() / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U);
586     }
587 #endif
588     return freq;
589 
590 }
591 
imxrt_configure(struct rt_serial_device * serial,struct serial_configure * cfg)592 static rt_err_t imxrt_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
593 {
594     struct imxrt_uart *uart;
595     lpuart_config_t config;
596 
597     RT_ASSERT(serial != RT_NULL);
598     RT_ASSERT(cfg != RT_NULL);
599 
600     uart = rt_container_of(serial, struct imxrt_uart, serial);
601 
602     LPUART_GetDefaultConfig(&config);
603     config.baudRate_Bps = cfg->baud_rate;
604 
605     switch (cfg->data_bits)
606     {
607     case DATA_BITS_7:
608         config.dataBitsCount = kLPUART_SevenDataBits;
609         break;
610 
611     default:
612         config.dataBitsCount = kLPUART_EightDataBits;
613         break;
614     }
615 
616     switch (cfg->stop_bits)
617     {
618     case STOP_BITS_2:
619         config.stopBitCount = kLPUART_TwoStopBit;
620         break;
621     default:
622         config.stopBitCount = kLPUART_OneStopBit;
623         break;
624     }
625 
626     switch (cfg->parity)
627     {
628     case PARITY_ODD:
629         config.parityMode = kLPUART_ParityOdd;
630         break;
631     case PARITY_EVEN:
632         config.parityMode = kLPUART_ParityEven;
633         break;
634     default:
635         config.parityMode = kLPUART_ParityDisabled;
636         break;
637     }
638 
639     config.enableTx = true;
640     config.enableRx = true;
641 
642     LPUART_Init(uart->uart_base, &config, GetUartSrcFreq(uart->uart_base));
643 
644     return RT_EOK;
645 }
646 
imxrt_control(struct rt_serial_device * serial,int cmd,void * arg)647 static rt_err_t imxrt_control(struct rt_serial_device *serial, int cmd, void *arg)
648 {
649     struct imxrt_uart *uart;
650 
651     RT_ASSERT(serial != RT_NULL);
652     uart = rt_container_of(serial, struct imxrt_uart, serial);
653 
654 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
655     rt_ubase_t ctrl_arg = (rt_ubase_t)arg;
656 #endif
657 
658     switch (cmd)
659     {
660     case RT_DEVICE_CTRL_CLR_INT:
661         DisableIRQ(uart->irqn);
662         break;
663 
664     case RT_DEVICE_CTRL_SET_INT:
665         LPUART_EnableInterrupts(uart->uart_base, kLPUART_RxDataRegFullInterruptEnable);
666         NVIC_SetPriority(uart->irqn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 4, 0));
667         EnableIRQ(uart->irqn);
668         break;
669 
670 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
671     case RT_DEVICE_CTRL_CONFIG:
672 
673         if (RT_DEVICE_FLAG_DMA_RX == ctrl_arg)
674         {
675             imxrt_dma_rx_config(uart);
676         }
677         else if (RT_DEVICE_FLAG_DMA_TX == ctrl_arg)
678         {
679             imxrt_dma_tx_config(uart);
680         }
681         break;
682 #endif
683     }
684 
685     return RT_EOK;
686 }
687 
imxrt_putc(struct rt_serial_device * serial,char ch)688 static int imxrt_putc(struct rt_serial_device *serial, char ch)
689 {
690     struct imxrt_uart *uart;
691 
692     RT_ASSERT(serial != RT_NULL);
693     uart = rt_container_of(serial, struct imxrt_uart, serial);
694 
695     LPUART_WriteByte(uart->uart_base, ch);
696     while (!(LPUART_GetStatusFlags(uart->uart_base) & kLPUART_TxDataRegEmptyFlag));
697 
698     return 1;
699 }
700 
imxrt_getc(struct rt_serial_device * serial)701 static int imxrt_getc(struct rt_serial_device *serial)
702 {
703     int ch;
704     struct imxrt_uart *uart;
705 
706     RT_ASSERT(serial != RT_NULL);
707     uart = rt_container_of(serial, struct imxrt_uart, serial);
708 
709     ch = -1;
710     if (LPUART_GetStatusFlags(uart->uart_base) & kLPUART_RxDataRegFullFlag)
711     {
712         ch = LPUART_ReadByte(uart->uart_base);
713     }
714 
715     return ch;
716 }
717 
718 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
dma_tx_xfer(struct rt_serial_device * serial,rt_uint8_t * buf,rt_size_t size,int direction)719 rt_size_t dma_tx_xfer(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction)
720 {
721     struct imxrt_uart *uart;
722     lpuart_transfer_t xfer;
723     rt_size_t xfer_size = 0;
724 
725     RT_ASSERT(serial != RT_NULL);
726     uart = rt_container_of(serial, struct imxrt_uart, serial);
727 
728     if (0 != size)
729     {
730         if (RT_SERIAL_DMA_TX == direction)
731         {
732             xfer.data = buf;
733             xfer.dataSize = size;
734             if (LPUART_SendEDMA(uart->uart_base, &uart->dma_tx->uart_edma, &xfer) == kStatus_Success)
735             {
736                 xfer_size = size;
737             }
738         }
739     }
740 
741     return xfer_size;
742 }
743 #endif
744 
745 static const struct rt_uart_ops imxrt_uart_ops =
746 {
747     imxrt_configure,
748     imxrt_control,
749     imxrt_putc,
750     imxrt_getc,
751 #if defined(RT_SERIAL_USING_DMA) && defined(BSP_USING_DMA)
752     dma_tx_xfer
753 #else
754     RT_NULL
755 #endif
756 };
757 
rt_hw_uart_init(void)758 int rt_hw_uart_init(void)
759 {
760     int i;
761     rt_uint32_t flag;
762     rt_err_t ret = RT_EOK;
763     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
764 
765     flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX;
766 
767     uart_get_dma_config();
768 
769     for (i = 0; i < sizeof(uarts) / sizeof(uarts[0]); i++)
770     {
771         uarts[i].serial.ops    = &imxrt_uart_ops;
772         uarts[i].serial.config = config;
773 
774         ret = rt_hw_serial_register(&uarts[i].serial, uarts[i].name, flag | uarts[i].dma_flag, NULL);
775     }
776 
777     return ret;
778 }
779 INIT_BOARD_EXPORT(rt_hw_uart_init);
780 
781 #endif /* BSP_USING_LPUART */
782