drv_uart.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. /*
  2. * Copyright (c) 2006-2018, 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. * 2018-03-17 laiyiketang Add other uart.
  10. */
  11. #include <rtthread.h>
  12. #include "drv_uart.h"
  13. #include "fsl_common.h"
  14. #include "fsl_lpuart.h"
  15. #include "fsl_iomuxc.h"
  16. #ifdef RT_USING_SERIAL
  17. #if defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL
  18. #error "Please don't define 'FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL'!"
  19. #endif
  20. #if !defined(RT_USING_UART1) && !defined(RT_USING_UART2) && \
  21. !defined(RT_USING_UART3) && !defined(RT_USING_UART4) && \
  22. !defined(RT_USING_UART5) && !defined(RT_USING_UART6) && \
  23. !defined(RT_USING_UART7) && !defined(RT_USING_UART8)
  24. #error "Please define at least one UARTx"
  25. #endif
  26. #include <rtdevice.h>
  27. /* imxrt uart driver */
  28. struct imxrt_uart
  29. {
  30. LPUART_Type *uart_base;
  31. IRQn_Type irqn;
  32. struct rt_serial_device *serial;
  33. char *device_name;
  34. };
  35. static void uart_isr(struct rt_serial_device *serial);
  36. #if defined(RT_USING_UART1)
  37. struct rt_serial_device serial1;
  38. void LPUART1_IRQHandler(void)
  39. {
  40. uart_isr(&serial1);
  41. }
  42. #endif /* RT_USING_UART1 */
  43. #if defined(RT_USING_UART2)
  44. struct rt_serial_device serial2;
  45. void LPUART2_IRQHandler(void)
  46. {
  47. uart_isr(&serial2);
  48. }
  49. #endif /* RT_USING_UART2 */
  50. #if defined(RT_USING_UART3)
  51. struct rt_serial_device serial3;
  52. void LPUART3_IRQHandler(void)
  53. {
  54. uart_isr(&serial3);
  55. }
  56. #endif /* RT_USING_UART3 */
  57. #if defined(RT_USING_UART4)
  58. struct rt_serial_device serial4;
  59. void LPUART4_IRQHandler(void)
  60. {
  61. uart_isr(&serial4);
  62. }
  63. #endif /* RT_USING_UART4 */
  64. #if defined(RT_USING_UART5)
  65. struct rt_serial_device serial5;
  66. void LPUART5_IRQHandler(void)
  67. {
  68. uart_isr(&serial5);
  69. }
  70. #endif /* RT_USING_UART5 */
  71. #if defined(RT_USING_UART6)
  72. struct rt_serial_device serial6;
  73. void LPUART6_IRQHandler(void)
  74. {
  75. uart_isr(&serial6);
  76. }
  77. #endif /* RT_USING_UART6 */
  78. #if defined(RT_USING_UART7)
  79. struct rt_serial_device serial7;
  80. void LPUART7_IRQHandler(void)
  81. {
  82. uart_isr(&serial7);
  83. }
  84. #endif /* RT_USING_UART7 */
  85. #if defined(RT_USING_UART8)
  86. struct rt_serial_device serial8;
  87. void LPUART8_IRQHandler(void)
  88. {
  89. uart_isr(&serial8);
  90. }
  91. #endif /* RT_USING_UART8 */
  92. static const struct imxrt_uart uarts[] =
  93. {
  94. #ifdef RT_USING_UART1
  95. {
  96. LPUART1,
  97. LPUART1_IRQn,
  98. &serial1,
  99. "uart1",
  100. },
  101. #endif
  102. #ifdef RT_USING_UART2
  103. {
  104. LPUART2,
  105. LPUART2_IRQn,
  106. &serial2,
  107. "uart2",
  108. },
  109. #endif
  110. #ifdef RT_USING_UART3
  111. {
  112. LPUART3,
  113. LPUART3_IRQn,
  114. &serial3,
  115. "uart3",
  116. },
  117. #endif
  118. #ifdef RT_USING_UART4
  119. {
  120. LPUART4,
  121. LPUART4_IRQn,
  122. &serial4,
  123. "uart4",
  124. },
  125. #endif
  126. #ifdef RT_USING_UART5
  127. {
  128. LPUART5,
  129. LPUART5_IRQn,
  130. &serial5,
  131. "uart5",
  132. },
  133. #endif
  134. #ifdef RT_USING_UART6
  135. {
  136. LPUART6,
  137. LPUART6_IRQn,
  138. &serial6,
  139. "uart6",
  140. },
  141. #endif
  142. #ifdef RT_USING_UART7
  143. {
  144. LPUART7,
  145. LPUART7_IRQn,
  146. &serial7,
  147. "uart7",
  148. },
  149. #endif
  150. #ifdef RT_USING_UART8
  151. {
  152. LPUART8,
  153. LPUART8_IRQn,
  154. &serial8,
  155. "uart8",
  156. },
  157. #endif
  158. };
  159. /* Get debug console frequency. */
  160. uint32_t GetUartSrcFreq(void)
  161. {
  162. uint32_t freq;
  163. /* To make it simple, we assume default PLL and divider settings, and the only variable
  164. from application is use PLL3 source or OSC source */
  165. if (CLOCK_GetMux(kCLOCK_UartMux) == 0) /* PLL3 div6 80M */
  166. {
  167. freq = (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6U) / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U);
  168. }
  169. else
  170. {
  171. freq = CLOCK_GetOscFreq() / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U);
  172. }
  173. return freq;
  174. }
  175. /**
  176. * @brief UART MSP Initialization
  177. * This function configures the hardware resources used in this example:
  178. * - Peripheral's clock enable
  179. * - Peripheral's GPIO Configuration
  180. * - NVIC configuration for UART interrupt request enable
  181. * @param huart: UART handle pointer
  182. * @retval None
  183. */
  184. void imxrt_uart_gpio_init(struct imxrt_uart *uart)
  185. {
  186. if (uart->uart_base != RT_NULL)
  187. {
  188. #ifdef RT_USING_UART1
  189. IOMUXC_SetPinMux(
  190. IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 is configured as LPUART1_TX */
  191. 0U); /* Software Input On Field: Input Path is determined by functionality */
  192. IOMUXC_SetPinMux(
  193. IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 is configured as LPUART1_RX */
  194. 0U); /* Software Input On Field: Input Path is determined by functionality */
  195. IOMUXC_SetPinConfig(
  196. IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 PAD functional properties : */
  197. 0x10B0u); /* Slew Rate Field: Slow Slew Rate
  198. Drive Strength Field: R0/6
  199. Speed Field: medium(100MHz)
  200. Open Drain Enable Field: Open Drain Disabled
  201. Pull / Keep Enable Field: Pull/Keeper Enabled
  202. Pull / Keep Select Field: Keeper
  203. Pull Up / Down Config. Field: 100K Ohm Pull Down
  204. Hyst. Enable Field: Hysteresis Disabled */
  205. IOMUXC_SetPinConfig(
  206. IOMUXC_GPIO_AD_B0_13_LPUART1_RX, /* GPIO_AD_B0_13 PAD functional properties : */
  207. 0x10B0u); /* Slew Rate Field: Slow Slew Rate
  208. Drive Strength Field: R0/6
  209. Speed Field: medium(100MHz)
  210. Open Drain Enable Field: Open Drain Disabled
  211. Pull / Keep Enable Field: Pull/Keeper Enabled
  212. Pull / Keep Select Field: Keeper
  213. Pull Up / Down Config. Field: 100K Ohm Pull Down
  214. Hyst. Enable Field: Hysteresis Disabled */
  215. #endif
  216. #ifdef RT_USING_UART2
  217. IOMUXC_SetPinMux(
  218. IOMUXC_GPIO_AD_B1_02_LPUART2_TX,
  219. 0U);
  220. IOMUXC_SetPinMux(
  221. IOMUXC_GPIO_AD_B1_03_LPUART2_RX,
  222. 0U);
  223. IOMUXC_SetPinConfig(
  224. IOMUXC_GPIO_AD_B1_02_LPUART2_TX,
  225. 0x10B0u);
  226. IOMUXC_SetPinConfig(
  227. IOMUXC_GPIO_AD_B1_03_LPUART2_RX,
  228. 0x10B0u);
  229. #endif
  230. #ifdef RT_USING_UART3
  231. IOMUXC_SetPinMux(
  232. IOMUXC_GPIO_AD_B1_06_LPUART3_TX,
  233. 0U);
  234. IOMUXC_SetPinMux(
  235. IOMUXC_GPIO_AD_B1_07_LPUART3_RX,
  236. 0U);
  237. IOMUXC_SetPinConfig(
  238. IOMUXC_GPIO_AD_B1_06_LPUART3_TX,
  239. 0x10B0u);
  240. IOMUXC_SetPinConfig(
  241. IOMUXC_GPIO_AD_B1_07_LPUART3_RX,
  242. 0x10B0u);
  243. #endif
  244. #ifdef RT_USING_UART4
  245. #ifdef BOARD_RT1050_ATK
  246. IOMUXC_SetPinMux(
  247. IOMUXC_GPIO_SD_B1_00_LPUART4_TX,
  248. 0U);
  249. IOMUXC_SetPinMux(
  250. IOMUXC_GPIO_SD_B1_01_LPUART4_RX,
  251. 0U);
  252. IOMUXC_SetPinConfig(
  253. IOMUXC_GPIO_SD_B1_00_LPUART4_TX,
  254. 0x10B0u);
  255. IOMUXC_SetPinConfig(
  256. IOMUXC_GPIO_SD_B1_01_LPUART4_RX,
  257. 0x10B0u);
  258. #else
  259. IOMUXC_SetPinMux(
  260. IOMUXC_GPIO_B1_00_LPUART4_TX,
  261. 0U);
  262. IOMUXC_SetPinMux(
  263. IOMUXC_GPIO_B1_01_LPUART4_RX,
  264. 0U);
  265. IOMUXC_SetPinConfig(
  266. IOMUXC_GPIO_B1_00_LPUART4_TX,
  267. 0x10B0u);
  268. IOMUXC_SetPinConfig(
  269. IOMUXC_GPIO_B1_01_LPUART4_RX,
  270. 0x10B0u);
  271. #endif
  272. #endif
  273. #ifdef RT_USING_UART5
  274. IOMUXC_SetPinMux(
  275. IOMUXC_GPIO_B1_12_LPUART5_TX,
  276. 0U);
  277. IOMUXC_SetPinMux(
  278. IOMUXC_GPIO_B1_13_LPUART5_RX,
  279. 0U);
  280. IOMUXC_SetPinConfig(
  281. IOMUXC_GPIO_B1_12_LPUART5_TX,
  282. 0x10B0u);
  283. IOMUXC_SetPinConfig(
  284. IOMUXC_GPIO_B1_13_LPUART5_RX,
  285. 0x10B0u);
  286. #endif
  287. #ifdef RT_USING_UART6
  288. IOMUXC_SetPinMux(
  289. IOMUXC_GPIO_AD_B0_02_LPUART6_TX,
  290. 0U);
  291. IOMUXC_SetPinMux(
  292. IOMUXC_GPIO_AD_B0_03_LPUART6_RX,
  293. 0U);
  294. IOMUXC_SetPinConfig(
  295. IOMUXC_GPIO_AD_B0_02_LPUART6_TX,
  296. 0x10B0u);
  297. IOMUXC_SetPinConfig(
  298. IOMUXC_GPIO_AD_B0_03_LPUART6_RX,
  299. 0x10B0u);
  300. #endif
  301. #ifdef RT_USING_UART7
  302. IOMUXC_SetPinMux(
  303. IOMUXC_GPIO_EMC_31_LPUART7_TX,
  304. 0U);
  305. IOMUXC_SetPinMux(
  306. IOMUXC_GPIO_EMC_32_LPUART7_RX,
  307. 0U);
  308. IOMUXC_SetPinConfig(
  309. IOMUXC_GPIO_EMC_31_LPUART7_TX,
  310. 0x10B0u);
  311. IOMUXC_SetPinConfig(
  312. IOMUXC_GPIO_EMC_32_LPUART7_RX,
  313. 0x10B0u);
  314. #endif
  315. #ifdef RT_USING_UART8
  316. IOMUXC_SetPinMux(
  317. IOMUXC_GPIO_AD_B1_10_LPUART8_TX,
  318. 0U);
  319. IOMUXC_SetPinMux(
  320. IOMUXC_GPIO_AD_B1_11_LPUART8_RX,
  321. 0U);
  322. IOMUXC_SetPinConfig(
  323. IOMUXC_GPIO_AD_B1_10_LPUART8_TX,
  324. 0x10B0u);
  325. IOMUXC_SetPinConfig(
  326. IOMUXC_GPIO_AD_B1_11_LPUART8_RX,
  327. 0x10B0u);
  328. #endif
  329. }
  330. else
  331. {
  332. RT_ASSERT(RT_NULL);
  333. }
  334. }
  335. static rt_err_t imxrt_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
  336. {
  337. struct imxrt_uart *uart;
  338. lpuart_config_t config;
  339. RT_ASSERT(serial != RT_NULL);
  340. RT_ASSERT(cfg != RT_NULL);
  341. uart = (struct imxrt_uart *)serial->parent.user_data;
  342. imxrt_uart_gpio_init(uart);
  343. LPUART_GetDefaultConfig(&config);
  344. config.baudRate_Bps = cfg->baud_rate;
  345. switch (cfg->data_bits)
  346. {
  347. case DATA_BITS_7:
  348. config.dataBitsCount = kLPUART_SevenDataBits;
  349. break;
  350. default:
  351. config.dataBitsCount = kLPUART_EightDataBits;
  352. break;
  353. }
  354. switch (cfg->stop_bits)
  355. {
  356. case STOP_BITS_2:
  357. config.stopBitCount = kLPUART_TwoStopBit;
  358. break;
  359. default:
  360. config.stopBitCount = kLPUART_OneStopBit;
  361. break;
  362. }
  363. switch (cfg->parity)
  364. {
  365. case PARITY_ODD:
  366. config.parityMode = kLPUART_ParityOdd;
  367. break;
  368. case PARITY_EVEN:
  369. config.parityMode = kLPUART_ParityEven;
  370. break;
  371. default:
  372. config.parityMode = kLPUART_ParityDisabled;
  373. break;
  374. }
  375. config.enableTx = true;
  376. config.enableRx = true;
  377. LPUART_Init(uart->uart_base, &config, GetUartSrcFreq());
  378. LPUART_EnableInterrupts(uart->uart_base, kLPUART_RxDataRegFullInterruptEnable);
  379. return RT_EOK;
  380. }
  381. static rt_err_t imxrt_control(struct rt_serial_device *serial, int cmd, void *arg)
  382. {
  383. struct imxrt_uart *uart;
  384. RT_ASSERT(serial != RT_NULL);
  385. uart = (struct imxrt_uart *)serial->parent.user_data;
  386. switch (cmd)
  387. {
  388. case RT_DEVICE_CTRL_CLR_INT:
  389. /* disable rx irq */
  390. DisableIRQ(uart->irqn);
  391. break;
  392. case RT_DEVICE_CTRL_SET_INT:
  393. /* enable rx irq */
  394. EnableIRQ(uart->irqn);
  395. break;
  396. }
  397. return RT_EOK;
  398. }
  399. static int imxrt_putc(struct rt_serial_device *serial, char ch)
  400. {
  401. struct imxrt_uart *uart;
  402. RT_ASSERT(serial != RT_NULL);
  403. uart = (struct imxrt_uart *)serial->parent.user_data;
  404. LPUART_WriteByte(uart->uart_base, ch);
  405. while (!(LPUART_GetStatusFlags(uart->uart_base) & kLPUART_TxDataRegEmptyFlag));
  406. return 1;
  407. }
  408. static int imxrt_getc(struct rt_serial_device *serial)
  409. {
  410. int ch;
  411. struct imxrt_uart *uart;
  412. RT_ASSERT(serial != RT_NULL);
  413. uart = (struct imxrt_uart *)serial->parent.user_data;
  414. ch = -1;
  415. if (LPUART_GetStatusFlags(uart->uart_base) & kLPUART_RxDataRegFullFlag)
  416. ch = LPUART_ReadByte(uart->uart_base);
  417. return ch;
  418. }
  419. /**
  420. * Uart common interrupt process. This need add to uart ISR.
  421. *
  422. * @param serial serial device
  423. */
  424. static void uart_isr(struct rt_serial_device *serial)
  425. {
  426. struct imxrt_uart *uart;
  427. LPUART_Type *base;
  428. RT_ASSERT(serial != RT_NULL);
  429. uart = (struct imxrt_uart *) serial->parent.user_data;
  430. RT_ASSERT(uart != RT_NULL);
  431. base = uart->uart_base;
  432. RT_ASSERT(base != RT_NULL);
  433. /* enter interrupt */
  434. rt_interrupt_enter();
  435. /* UART in mode Receiver -------------------------------------------------*/
  436. if (LPUART_GetStatusFlags(base) & kLPUART_RxDataRegFullFlag)
  437. {
  438. rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
  439. }
  440. /* If RX overrun. */
  441. if (LPUART_STAT_OR_MASK & base->STAT)
  442. {
  443. /* Clear overrun flag, otherwise the RX does not work. */
  444. base->STAT = ((base->STAT & 0x3FE00000U) | LPUART_STAT_OR_MASK);
  445. }
  446. /* leave interrupt */
  447. rt_interrupt_leave();
  448. }
  449. static const struct rt_uart_ops imxrt_uart_ops =
  450. {
  451. imxrt_configure,
  452. imxrt_control,
  453. imxrt_putc,
  454. imxrt_getc,
  455. };
  456. int imxrt_hw_uart_init(void)
  457. {
  458. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
  459. int i;
  460. /* Configure UART divider to default */
  461. CLOCK_SetMux(kCLOCK_UartMux, 0); /* Set UART source to PLL3 80M */
  462. CLOCK_SetDiv(kCLOCK_UartDiv, 0); /* Set UART divider to 1 */
  463. for (i = 0; i < sizeof(uarts) / sizeof(uarts[0]); i++)
  464. {
  465. uarts[i].serial->ops = &imxrt_uart_ops;
  466. uarts[i].serial->config = config;
  467. /* register UART device */
  468. rt_hw_serial_register(uarts[i].serial,
  469. uarts[i].device_name,
  470. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
  471. (void *)&uarts[i]);
  472. }
  473. return 0;
  474. }
  475. INIT_BOARD_EXPORT(imxrt_hw_uart_init);
  476. #endif /*RT_USING_SERIAL */