drv_uart.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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-02-06 yandld The first version for MCX
  9. * 2024-11-11 hywing add more UART channels
  10. */
  11. #include <rtdevice.h>
  12. #include "drv_uart.h"
  13. #include "fsl_lpuart.h"
  14. #ifdef RT_USING_SERIAL
  15. #define DBG_TAG "drv.uart"
  16. #define DBG_LVL DBG_INFO
  17. #include <rtdbg.h>
  18. struct mcx_uart
  19. {
  20. struct rt_serial_device *serial;
  21. LPUART_Type *uart_base;
  22. IRQn_Type irqn;
  23. clock_ip_name_t clock_ip_name;
  24. clock_ip_src_t clock_ip_src;
  25. char *device_name;
  26. };
  27. static void uart_isr(struct rt_serial_device *serial);
  28. #if defined(BSP_USING_UART0)
  29. struct rt_serial_device serial0;
  30. void LPUART0_IRQHandler(void)
  31. {
  32. uart_isr(&serial0);
  33. }
  34. #endif
  35. #if defined(BSP_USING_UART1)
  36. struct rt_serial_device serial1;
  37. void LPUART1_IRQHandler(void)
  38. {
  39. uart_isr(&serial1);
  40. }
  41. #endif
  42. #if defined(BSP_USING_UART2)
  43. struct rt_serial_device serial2;
  44. void LPUART2_IRQHandler(void)
  45. {
  46. uart_isr(&serial2);
  47. }
  48. #endif
  49. static const struct mcx_uart uarts[] =
  50. {
  51. #ifdef BSP_USING_UART0
  52. {
  53. .serial = &serial0,
  54. .uart_base = LPUART0,
  55. .irqn = LPUART0_IRQn,
  56. .clock_ip_name = kCLOCK_Lpuart0,
  57. .clock_ip_src = kCLOCK_IpSrcSysOscAsync,
  58. .device_name = "uart0",
  59. },
  60. #endif
  61. #ifdef BSP_USING_UART1
  62. {
  63. .serial = &serial1,
  64. .uart_base = LPUART1,
  65. .irqn = LPUART1_IRQn,
  66. .clock_ip_name = kCLOCK_Lpuart1,
  67. .clock_ip_src = kCLOCK_IpSrcSysOscAsync,
  68. .device_name = "uart1",
  69. },
  70. #endif
  71. #ifdef BSP_USING_UART2
  72. {
  73. .serial = &serial2,
  74. .uart_base = LPUART2,
  75. .irqn = LPUART2_IRQn,
  76. .clock_ip_name = kCLOCK_Lpuart2,
  77. .clock_ip_src = kCLOCK_IpSrcSysOscAsync,
  78. .device_name = "uart2",
  79. },
  80. #endif
  81. };
  82. static rt_err_t mcx_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
  83. {
  84. struct mcx_uart *uart;
  85. lpuart_config_t config;
  86. RT_ASSERT(serial != RT_NULL);
  87. RT_ASSERT(cfg != RT_NULL);
  88. uart = (struct mcx_uart *)serial->parent.user_data;
  89. CLOCK_SetIpSrc(uart->clock_ip_name, uart->clock_ip_src);
  90. LPUART_GetDefaultConfig(&config);
  91. config.baudRate_Bps = cfg->baud_rate;
  92. switch (cfg->data_bits)
  93. {
  94. case DATA_BITS_7:
  95. config.dataBitsCount = kLPUART_SevenDataBits;
  96. break;
  97. default:
  98. config.dataBitsCount = kLPUART_EightDataBits;
  99. break;
  100. }
  101. config.enableTx = true;
  102. config.enableRx = true;
  103. LPUART_Init(uart->uart_base, &config, CLOCK_GetIpFreq(uart->clock_ip_name));
  104. return RT_EOK;
  105. }
  106. static rt_err_t mcx_control(struct rt_serial_device *serial, int cmd, void *arg)
  107. {
  108. struct mcx_uart *uart = (struct mcx_uart *)serial->parent.user_data;
  109. RT_ASSERT(uart != RT_NULL);
  110. switch (cmd)
  111. {
  112. case RT_DEVICE_CTRL_CLR_INT:
  113. /* disable rx irq */
  114. LPUART_DisableInterrupts(uart->uart_base, kLPUART_RxDataRegFullInterruptEnable);
  115. DisableIRQ(uart->irqn);
  116. break;
  117. case RT_DEVICE_CTRL_SET_INT:
  118. /* enable rx irq */
  119. LPUART_EnableInterrupts(uart->uart_base, kLPUART_RxDataRegFullInterruptEnable);
  120. EnableIRQ(uart->irqn);
  121. break;
  122. }
  123. return RT_EOK;
  124. }
  125. static int mcx_putc(struct rt_serial_device *serial, char ch)
  126. {
  127. struct mcx_uart *uart = (struct mcx_uart *)serial->parent.user_data;
  128. while (!(kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(uart->uart_base)));
  129. LPUART_WriteByte(uart->uart_base, ch);
  130. return 1;
  131. }
  132. static int mcx_getc(struct rt_serial_device *serial)
  133. {
  134. struct mcx_uart *uart = (struct mcx_uart *)serial->parent.user_data;
  135. if (kLPUART_RxDataRegFullInterruptEnable & LPUART_GetStatusFlags(uart->uart_base))
  136. {
  137. return LPUART_ReadByte(uart->uart_base);
  138. }
  139. else
  140. {
  141. return -1;
  142. }
  143. }
  144. /**
  145. * Uart common interrupt process. This need add to uart ISR.
  146. *
  147. * @param serial serial device
  148. */
  149. static void uart_isr(struct rt_serial_device *serial)
  150. {
  151. struct mcx_uart *uart;
  152. RT_ASSERT(serial != RT_NULL);
  153. uart = (struct mcx_uart *)serial->parent.user_data;
  154. RT_ASSERT(uart != RT_NULL);
  155. /* enter interrupt */
  156. rt_interrupt_enter();
  157. /* UART in mode Receiver -------------------------------------------------*/
  158. rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
  159. /* leave interrupt */
  160. rt_interrupt_leave();
  161. }
  162. static const struct rt_uart_ops mcx_uart_ops =
  163. {
  164. mcx_configure,
  165. mcx_control,
  166. mcx_putc,
  167. mcx_getc,
  168. };
  169. int rt_hw_uart_init(void)
  170. {
  171. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
  172. int i;
  173. for (i = 0; i < sizeof(uarts) / sizeof(uarts[0]); i++)
  174. {
  175. uarts[i].serial->ops = &mcx_uart_ops;
  176. uarts[i].serial->config = config;
  177. /* register UART device */
  178. rt_hw_serial_register(uarts[i].serial, uarts[i].device_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, (void *)&uarts[i]);
  179. }
  180. return 0;
  181. }
  182. INIT_BOARD_EXPORT(rt_hw_uart_init);
  183. #endif /*BSP_USING_SERIAL */