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