drv_uart.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /*
  2. * File : drv_uart.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2009-2013 RT-Thread Develop Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2013-05-18 Bernard The first version for LPC40xx
  13. */
  14. #include <rthw.h>
  15. #include <rtthread.h>
  16. #include <rtdevice.h>
  17. #include "board.h"
  18. struct lpc_uart
  19. {
  20. LPC_UART_TypeDef *UART;
  21. IRQn_Type UART_IRQn;
  22. };
  23. static rt_err_t lpc_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
  24. {
  25. struct lpc_uart *uart;
  26. uint32_t Fdiv = 0;
  27. RT_ASSERT(serial != RT_NULL);
  28. uart = (struct lpc_uart *)serial->parent.user_data;
  29. /* Initialize UART Configuration parameter structure to default state:
  30. * Baudrate = 115200 bps
  31. * 8 data bit
  32. * 1 Stop bit
  33. * None parity
  34. */
  35. /* set DLAB=1 */
  36. uart->UART->LCR |= 0x80;
  37. /* config uart baudrate */
  38. Fdiv = (PeripheralClock / 16) / cfg->baud_rate;
  39. uart->UART->DLM = Fdiv / 256;
  40. uart->UART->DLL = Fdiv % 256;
  41. /* set DLAB=0 */
  42. uart->UART->LCR &= ~0x80;
  43. /* config to 8 data bit,1 Stop bit,None parity */
  44. uart->UART->LCR |= 0x03;
  45. /*enable and reset FIFO*/
  46. uart->UART->FCR = 0x07;
  47. return RT_EOK;
  48. }
  49. static rt_err_t lpc_control(struct rt_serial_device *serial, int cmd, void *arg)
  50. {
  51. struct lpc_uart *uart;
  52. RT_ASSERT(serial != RT_NULL);
  53. uart = (struct lpc_uart *)serial->parent.user_data;
  54. switch (cmd)
  55. {
  56. case RT_DEVICE_CTRL_CLR_INT:
  57. /* disable rx irq */
  58. uart->UART->IER &= ~0x01;
  59. break;
  60. case RT_DEVICE_CTRL_SET_INT:
  61. /* enable rx irq */
  62. uart->UART->IER |= 0x01;
  63. break;
  64. }
  65. return RT_EOK;
  66. }
  67. static int lpc_putc(struct rt_serial_device *serial, char c)
  68. {
  69. struct lpc_uart *uart;
  70. uart = (struct lpc_uart *)serial->parent.user_data;
  71. while (!(uart->UART->LSR & 0x20));
  72. uart->UART->THR = c;
  73. return 1;
  74. }
  75. static int lpc_getc(struct rt_serial_device *serial)
  76. {
  77. struct lpc_uart *uart;
  78. uart = (struct lpc_uart *)serial->parent.user_data;
  79. if (uart->UART->LSR & 0x01)
  80. return (uart->UART->RBR);
  81. else
  82. return -1;
  83. }
  84. static const struct rt_uart_ops lpc_uart_ops =
  85. {
  86. lpc_configure,
  87. lpc_control,
  88. lpc_putc,
  89. lpc_getc,
  90. };
  91. #ifdef RT_USING_UART0
  92. /* UART0 device driver structure */
  93. #if RTTHREAD_VERSION < 20000 /* RT-Thread 1.x */
  94. struct serial_ringbuffer uart0_int_rx;
  95. #endif
  96. struct lpc_uart uart0 =
  97. {
  98. LPC_UART0,
  99. UART0_IRQn,
  100. };
  101. struct rt_serial_device serial0;
  102. void UART0_IRQHandler(void)
  103. {
  104. volatile uint32_t IIR, tmp;
  105. /* enter interrupt */
  106. rt_interrupt_enter();
  107. IIR = LPC_UART0->IIR;
  108. IIR &= 0x0e;
  109. switch (IIR)
  110. {
  111. case 0x04:
  112. case 0x0C:
  113. #if RTTHREAD_VERSION < 20000
  114. rt_hw_serial_isr(&serial0);
  115. #else
  116. rt_hw_serial_isr(&serial0, RT_SERIAL_EVENT_RX_IND);
  117. #endif
  118. break;
  119. case 0x06:
  120. tmp = LPC_UART0->LSR;
  121. break;
  122. default :
  123. tmp = LPC_UART0->LSR;
  124. break;
  125. }
  126. /* leave interrupt */
  127. rt_interrupt_leave();
  128. }
  129. #endif
  130. #ifdef RT_USING_UART2
  131. /* UART2 device driver structure */
  132. #if RTTHREAD_VERSION < 20000 /* RT-Thread 1.x */
  133. struct serial_ringbuffer uart2_int_rx;
  134. #endif
  135. struct lpc_uart uart2 =
  136. {
  137. LPC_UART2,
  138. UART2_IRQn,
  139. };
  140. struct rt_serial_device serial2;
  141. void UART2_IRQHandler(void)
  142. {
  143. volatile uint32_t IIR, tmp;
  144. /* enter interrupt */
  145. rt_interrupt_enter();
  146. IIR = LPC_UART2->IIR;
  147. IIR &= 0x0e;
  148. switch (IIR)
  149. {
  150. case 0x04:
  151. case 0x0C:
  152. #if RTTHREAD_VERSION < 20000
  153. rt_hw_serial_isr(&serial2);
  154. #else
  155. rt_hw_serial_isr(&serial2, RT_SERIAL_EVENT_RX_IND);
  156. #endif
  157. break;
  158. case 0x06:
  159. tmp = LPC_UART2->LSR;
  160. break;
  161. default :
  162. tmp = LPC_UART2->LSR;
  163. break;
  164. }
  165. /* leave interrupt */
  166. rt_interrupt_leave();
  167. }
  168. #endif
  169. #ifdef RT_USING_UART4
  170. /* UART4 device driver structure */
  171. #if RTTHREAD_VERSION < 20000 /* RT-Thread 1.x */
  172. struct serial_ringbuffer uart4_int_rx;
  173. #endif
  174. struct lpc_uart uart4 =
  175. {
  176. LPC_UART4,
  177. UART4_IRQn,
  178. };
  179. struct rt_serial_device serial4;
  180. void UART4_IRQHandler(void)
  181. {
  182. volatile uint32_t IIR, tmp;
  183. /* enter interrupt */
  184. rt_interrupt_enter();
  185. IIR = LPC_UART4->IIR;
  186. IIR &= 0x0e;
  187. switch (IIR)
  188. {
  189. case 0x04:
  190. case 0x0C:
  191. #if RTTHREAD_VERSION < 20000
  192. rt_hw_serial_isr(&serial4);
  193. #else
  194. rt_hw_serial_isr(&serial4, RT_SERIAL_EVENT_RX_IND);
  195. #endif
  196. break;
  197. case 0x06:
  198. tmp = LPC_UART4->LSR;
  199. break;
  200. default :
  201. tmp = LPC_UART4->LSR;
  202. break;
  203. }
  204. /* leave interrupt */
  205. rt_interrupt_leave();
  206. }
  207. #endif
  208. void rt_hw_uart_init(void)
  209. {
  210. struct lpc_uart *uart;
  211. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
  212. #ifdef RT_USING_UART0
  213. uart = &uart0;
  214. serial0.ops = &lpc_uart_ops;
  215. serial0.config = config;
  216. #if RTTHREAD_VERSION < 20000
  217. serial0.int_rx = &uart0_int_rx;
  218. #endif
  219. serial0.parent.user_data = uart;
  220. /*
  221. * Initialize UART0 pin connect
  222. * P0.2: U0_TXD
  223. * P0.3: U0_RXD
  224. */
  225. LPC_IOCON->P0_2 &= ~0x07;
  226. LPC_IOCON->P0_2 |= 0x01;
  227. LPC_IOCON->P0_3 &= ~0x07;
  228. LPC_IOCON->P0_3 |= 0x01;
  229. /* enable the uart0 power and clock */
  230. LPC_SC->PCONP |= 0x01 << 3;
  231. /* preemption = 1, sub-priority = 1 */
  232. NVIC_SetPriority(uart->UART_IRQn, ((0x01 << 3) | 0x01));
  233. /* Enable Interrupt for UART channel */
  234. NVIC_EnableIRQ(uart->UART_IRQn);
  235. /* register UART0 device */
  236. rt_hw_serial_register(&serial0, "uart0",
  237. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
  238. uart);
  239. #endif
  240. #ifdef RT_USING_UART2
  241. uart = &uart2;
  242. serial2.ops = &lpc_uart_ops;
  243. serial2.config = config;
  244. #if RTTHREAD_VERSION < 20000
  245. serial2.int_rx = &uart2_int_rx;
  246. #endif
  247. serial2.parent.user_data = uart;
  248. /*
  249. * Initialize UART2 pin connect
  250. * P2.8: U2_TXD
  251. * P0.11: U2_RXD
  252. */
  253. LPC_IOCON->P2_8 &= ~0x07;
  254. LPC_IOCON->P0_11 &= ~0x07;
  255. LPC_IOCON->P2_8 |= 0x02;
  256. LPC_IOCON->P0_11 |= 0x01;
  257. /* enable the uart2 power and clock */
  258. LPC_SC->PCONP |= 0x01 << 24;
  259. /* preemption = 1, sub-priority = 1 */
  260. NVIC_SetPriority(uart->UART_IRQn, ((0x01 << 3) | 0x01));
  261. /* Enable Interrupt for UART channel */
  262. NVIC_EnableIRQ(uart->UART_IRQn);
  263. /* register UART2 device */
  264. rt_hw_serial_register(&serial2, "uart2",
  265. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
  266. uart);
  267. #endif
  268. #ifdef RT_USING_UART4
  269. uart = &uart4;
  270. serial4.ops = &lpc_uart_ops;
  271. serial4.config = config;
  272. #if RTTHREAD_VERSION < 20000
  273. serial4.int_rx = &uart4_int_rx;
  274. #endif
  275. serial4.parent.user_data = uart;
  276. /*
  277. * Initialize UART2 pin connect
  278. * P5.4: U2_TXD
  279. * P5.3: U2_RXD
  280. */
  281. LPC_IOCON->P5_4 &= ~0x07;
  282. LPC_IOCON->P5_3 &= ~0x07;
  283. LPC_IOCON->P5_4 |= 0x04;
  284. LPC_IOCON->P5_3 |= 0x04;
  285. /* enable the uart4 power and clock */
  286. LPC_SC->PCONP |= 0x01 << 8;
  287. /* preemption = 1, sub-priority = 1 */
  288. NVIC_SetPriority(uart->UART_IRQn, ((0x01 << 3) | 0x01));
  289. /* Enable Interrupt for UART channel */
  290. NVIC_EnableIRQ(uart->UART_IRQn);
  291. /* register UART2 device */
  292. rt_hw_serial_register(&serial4, "uart4",
  293. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
  294. uart);
  295. #endif
  296. }