serial.c 9.3 KB

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