serial.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2013-03-30 Bernard the first verion
  9. */
  10. #include <rthw.h>
  11. #include <rtdevice.h>
  12. #include "serial.h"
  13. #include "board.h"
  14. #include "mmu.h"
  15. /*根据IMX6ULL芯片手册<<55.15 UART Memory Map/Register Definition>>的3608页,定义UART的结构体,*/
  16. typedef struct {
  17. volatile unsigned int URXD; /**< UART Receiver Register, offset: 0x0 串口接收寄存器,偏移地址0x0 */
  18. unsigned char RESERVED_0[60];
  19. volatile unsigned int UTXD; /**< UART Transmitter Register, offset: 0x40 串口发送寄存器,偏移地址0x40*/
  20. unsigned char RESERVED_1[60];
  21. volatile unsigned int UCR1; /**< UART Control Register 1, offset: 0x80 串口控制寄存器1,偏移地址0x80*/
  22. volatile unsigned int UCR2; /**< UART Control Register 2, offset: 0x84 串口控制寄存器2,偏移地址0x84*/
  23. volatile unsigned int UCR3; /**< UART Control Register 3, offset: 0x88 串口控制寄存器3,偏移地址0x88*/
  24. volatile unsigned int UCR4; /**< UART Control Register 4, offset: 0x8C 串口控制寄存器4,偏移地址0x8C*/
  25. volatile unsigned int UFCR; /**< UART FIFO Control Register, offset: 0x90 串口FIFO控制寄存器,偏移地址0x90*/
  26. volatile unsigned int USR1; /**< UART Status Register 1, offset: 0x94 串口状态寄存器1,偏移地址0x94*/
  27. volatile unsigned int USR2; /**< UART Status Register 2, offset: 0x98 串口状态寄存器2,偏移地址0x98*/
  28. volatile unsigned int UESC; /**< UART Escape Character Register, offset: 0x9C 串口转义字符寄存器,偏移地址0x9C*/
  29. volatile unsigned int UTIM; /**< UART Escape Timer Register, offset: 0xA0 串口转义定时器寄存器 偏移地址0xA0*/
  30. volatile unsigned int UBIR; /**< UART BRM Incremental Register, offset: 0xA4 串口二进制倍率增加寄存器 偏移地址0xA4*/
  31. volatile unsigned int UBMR; /**< UART BRM Modulator Register, offset: 0xA8 串口二进制倍率调节寄存器 偏移地址0xA8*/
  32. volatile unsigned int UBRC; /**< UART Baud Rate Count Register, offset: 0xAC 串口波特率计数寄存器 偏移地址0xAC*/
  33. volatile unsigned int ONEMS; /**< UART One Millisecond Register, offset: 0xB0 串口一毫秒寄存器 偏移地址0xB0*/
  34. volatile unsigned int UTS; /**< UART Test Register, offset: 0xB4 串口测试寄存器 偏移地址0xB4*/
  35. volatile unsigned int UMCR; /**< UART RS-485 Mode Control Register, offset: 0xB8 串口485模式控制寄存器 偏移地址0xB8*/
  36. } UART_Type;
  37. struct hw_uart_device
  38. {
  39. rt_uint32_t hw_base;
  40. rt_uint32_t irqno;
  41. };
  42. #define UART_DR(base) __REG32(base + 0x00)
  43. #define UART_FR(base) __REG32(base + 0x18)
  44. #define UART_CR(base) __REG32(base + 0x30)
  45. #define UART_IMSC(base) __REG32(base + 0x38)
  46. #define UART_ICR(base) __REG32(base + 0x44)
  47. #define UARTFR_RXFE 0x10
  48. #define UARTFR_TXFF 0x20
  49. #define UARTIMSC_RXIM 0x10
  50. #define UARTIMSC_TXIM 0x20
  51. #define UARTICR_RXIC 0x10
  52. #define UARTICR_TXIC 0x20
  53. static void rt_hw_uart_isr(int irqno, void *param)
  54. {
  55. struct rt_serial_device *serial = (struct rt_serial_device *)param;
  56. rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
  57. }
  58. static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
  59. {
  60. /* 115200,8n1 */
  61. volatile unsigned int *IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA ;
  62. volatile unsigned int *IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA ;
  63. volatile unsigned int *IOMUXC_UART1_RX_DATA_SELECT_INPUT ;
  64. volatile unsigned int *CCM_CSCDR1;
  65. volatile unsigned int *CCM_CCGR5;
  66. IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA = (volatile unsigned int *)rt_ioremap((void *)0x20E0084, 4);
  67. IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA = (volatile unsigned int *)rt_ioremap((void *)0x20E0088, 4);
  68. IOMUXC_UART1_RX_DATA_SELECT_INPUT = (volatile unsigned int *)rt_ioremap((void *)0x20E0624, 4);
  69. CCM_CSCDR1 = (volatile unsigned int *)rt_ioremap((void *)0x020C4024, 4);
  70. CCM_CCGR5 = (volatile unsigned int *)rt_ioremap((void *)0x020C407C, 4);
  71. struct hw_uart_device * uart = (struct hw_uart_device *)serial->parent.user_data;
  72. UART_Type *uart_reg = (UART_Type *)uart->hw_base;
  73. /* 设置UART的总时钟
  74. * UART_CLK_ROOT = 80Mhz
  75. */
  76. *CCM_CSCDR1 &= ~((1<<6) | (0x3f));
  77. /* 给UART1模块提供时钟
  78. * uart1_clk_enable
  79. */
  80. *CCM_CCGR5 |= (3<<24);
  81. /* 配置引脚功能 */
  82. *IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA &= ~0xf;
  83. *IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA &= ~0xf;
  84. /* IMX6ULL特殊的地方 */
  85. *IOMUXC_UART1_RX_DATA_SELECT_INPUT |= 3;
  86. /* 设置波特率
  87. * 115200 = 80M/(16*(UBMR+1)/(UBIR+1))
  88. * UBIR = 15
  89. * 115200 = 80M/(UBMR+1)
  90. * UBMR = 80,000,000/115200 = 694 - 1 = 693
  91. * 真正的baudrate = 80,000,000/694 = 115274
  92. * 先设置UBIR, 后设置UBMR
  93. */
  94. uart_reg->UFCR |= (5<<7);
  95. uart_reg->UBIR = 15;
  96. uart_reg->UBMR = 693;
  97. /* 设置数据格式 */
  98. uart_reg->UCR2 |= (1<<14) | (0<<8) | (0<<6) | (1<<5) | (1<<2) | (1<<1);
  99. /* IMX6ULL芯片要求必须设置 */
  100. uart_reg->UCR3 |= (1<<2);
  101. /* 使能UART */
  102. uart_reg->UCR1 |= (1<<0);
  103. return RT_EOK;
  104. }
  105. static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
  106. {
  107. struct hw_uart_device *uart;
  108. UART_Type *uart_reg;
  109. RT_ASSERT(serial != RT_NULL);
  110. uart = (struct hw_uart_device *)serial->parent.user_data;
  111. uart_reg = (UART_Type *)uart->hw_base;
  112. switch (cmd)
  113. {
  114. case RT_DEVICE_CTRL_CLR_INT:
  115. /* disable rx irq */
  116. uart_reg->UCR4 &= ~(1<<0);
  117. break;
  118. case RT_DEVICE_CTRL_SET_INT:
  119. /* enable rx irq */
  120. uart_reg->UCR4 |= (1<<0);
  121. rt_hw_interrupt_umask(uart->irqno);
  122. break;
  123. }
  124. return RT_EOK;
  125. }
  126. static int uart_putc(struct rt_serial_device *serial, char c)
  127. {
  128. struct hw_uart_device *uart;
  129. UART_Type *uart_reg;
  130. RT_ASSERT(serial != RT_NULL);
  131. uart = (struct hw_uart_device *)serial->parent.user_data;
  132. uart_reg = (UART_Type *)uart->hw_base;
  133. while ((uart_reg->USR2 & (1<<3)) == 0);
  134. uart_reg->UTXD = c;
  135. return 1;
  136. }
  137. static int uart_getc(struct rt_serial_device *serial)
  138. {
  139. int ch;
  140. struct hw_uart_device *uart;
  141. UART_Type *uart_reg;
  142. RT_ASSERT(serial != RT_NULL);
  143. uart = (struct hw_uart_device *)serial->parent.user_data;
  144. uart_reg = (UART_Type *)uart->hw_base;
  145. if ((uart_reg->USR2 & (1<<0)) == 0)
  146. ch = -1;
  147. else
  148. ch = uart_reg->URXD;
  149. return ch;
  150. }
  151. static const struct rt_uart_ops _uart_ops =
  152. {
  153. uart_configure,
  154. uart_control,
  155. uart_putc,
  156. uart_getc,
  157. };
  158. #ifdef RT_USING_UART0
  159. /* UART device driver structure */
  160. static struct hw_uart_device _uart0_device =
  161. {
  162. 0x02020000, /* imx6ull uart1 phy addr */
  163. 58, /* rx irq */
  164. };
  165. static struct rt_serial_device _serial0;
  166. #endif
  167. #ifdef RT_USING_UART1
  168. /* UART1 device driver structure */
  169. static struct hw_uart_device _uart1_device =
  170. {
  171. REALVIEW_UART1_BASE,
  172. IRQ_PBA8_UART1,
  173. };
  174. static struct rt_serial_device _serial1;
  175. #endif
  176. int rt_hw_uart_init(void)
  177. {
  178. struct hw_uart_device *uart;
  179. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
  180. #ifdef RT_USING_UART0
  181. _uart0_device.hw_base = (uint32_t)rt_ioremap((void*)_uart0_device.hw_base, 0x1000);
  182. uart = &_uart0_device;
  183. _serial0.ops = &_uart_ops;
  184. _serial0.config = config;
  185. /* register UART1 device */
  186. rt_hw_serial_register(&_serial0, "uart0",
  187. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
  188. uart);
  189. rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial0, "uart0");
  190. #endif
  191. #ifdef RT_USING_UART1
  192. _uart1_device.hw_base = (uint32_t)rt_ioremap((void*)_uart1_device.hw_base, 0x1000);
  193. uart = &_uart1_device;
  194. _serial1.ops = &_uart_ops;
  195. _serial1.config = config;
  196. /* register UART1 device */
  197. rt_hw_serial_register(&_serial1, "uart1",
  198. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart);
  199. /* enable Rx and Tx of UART */
  200. UART_CR(uart->hw_base) = (1 << 0) | (1 << 8) | (1 << 9);
  201. rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial1, "uart1");
  202. #endif
  203. return 0;
  204. }
  205. INIT_BOARD_EXPORT(rt_hw_uart_init);