uart.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*
  2. * File : board.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2009 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. * 2010-03-08 Bernard The first version for LPC17xx
  13. */
  14. #include <rthw.h>
  15. #include <rtthread.h>
  16. #include "CMSIS/LPC17xx.h"
  17. #define IER_RBR 0x01
  18. #define IER_THRE 0x02
  19. #define IER_RLS 0x04
  20. #define IIR_PEND 0x01
  21. #define IIR_RLS 0x03
  22. #define IIR_RDA 0x02
  23. #define IIR_CTI 0x06
  24. #define IIR_THRE 0x01
  25. #define LSR_RDR 0x01
  26. #define LSR_OE 0x02
  27. #define LSR_PE 0x04
  28. #define LSR_FE 0x08
  29. #define LSR_BI 0x10
  30. #define LSR_THRE 0x20
  31. #define LSR_TEMT 0x40
  32. #define LSR_RXFE 0x80
  33. /**
  34. * @addtogroup LPC11xx
  35. */
  36. /*@{*/
  37. #if defined(RT_USING_UART0) && defined(RT_USING_DEVICE)
  38. #define UART_BAUDRATE 115200
  39. #define LPC_UART LPC_UART0
  40. #define UART_IRQn UART0_IRQn
  41. struct rt_uart_lpc
  42. {
  43. struct rt_device parent;
  44. /* buffer for reception */
  45. rt_uint8_t read_index, save_index;
  46. rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE];
  47. }uart_device;
  48. void UART0_IRQHandler(void)
  49. {
  50. rt_ubase_t level, iir;
  51. struct rt_uart_lpc* uart = &uart_device;
  52. /* read IIR and clear it */
  53. iir = LPC_UART->IIR;
  54. iir >>= 1; /* skip pending bit in IIR */
  55. iir &= 0x07; /* check bit 1~3, interrupt identification */
  56. if (iir == IIR_RDA) /* Receive Data Available */
  57. {
  58. /* Receive Data Available */
  59. uart->rx_buffer[uart->save_index] = LPC_UART->RBR;
  60. level = rt_hw_interrupt_disable();
  61. uart->save_index ++;
  62. if (uart->save_index >= RT_UART_RX_BUFFER_SIZE)
  63. uart->save_index = 0;
  64. rt_hw_interrupt_enable(level);
  65. /* invoke callback */
  66. if(uart->parent.rx_indicate != RT_NULL)
  67. {
  68. rt_size_t length;
  69. if (uart->read_index > uart->save_index)
  70. length = RT_UART_RX_BUFFER_SIZE - uart->read_index + uart->save_index;
  71. else
  72. length = uart->save_index - uart->read_index;
  73. uart->parent.rx_indicate(&uart->parent, length);
  74. }
  75. }
  76. return;
  77. }
  78. static rt_err_t rt_uart_init (rt_device_t dev)
  79. {
  80. rt_uint32_t Fdiv;
  81. rt_uint32_t pclkdiv, pclk;
  82. /* Init UART Hardware */
  83. if (LPC_UART == LPC_UART0)
  84. {
  85. LPC_PINCON->PINSEL0 &= ~0x000000F0;
  86. LPC_PINCON->PINSEL0 |= 0x00000050; /* RxD0 is P0.3 and TxD0 is P0.2 */
  87. /* By default, the PCLKSELx value is zero, thus, the PCLK for
  88. all the peripherals is 1/4 of the SystemFrequency. */
  89. /* Bit 6~7 is for UART0 */
  90. pclkdiv = (LPC_SC->PCLKSEL0 >> 6) & 0x03;
  91. switch ( pclkdiv )
  92. {
  93. case 0x00:
  94. default:
  95. pclk = SystemFrequency/4;
  96. break;
  97. case 0x01:
  98. pclk = SystemFrequency;
  99. break;
  100. case 0x02:
  101. pclk = SystemFrequency/2;
  102. break;
  103. case 0x03:
  104. pclk = SystemFrequency/8;
  105. break;
  106. }
  107. LPC_UART0->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
  108. Fdiv = ( pclk / 16 ) / UART_BAUDRATE; /*baud rate */
  109. LPC_UART0->DLM = Fdiv / 256;
  110. LPC_UART0->DLL = Fdiv % 256;
  111. LPC_UART0->LCR = 0x03; /* DLAB = 0 */
  112. LPC_UART0->FCR = 0x07; /* Enable and reset TX and RX FIFO. */
  113. }
  114. else if ((LPC_UART1_TypeDef*)LPC_UART == LPC_UART1)
  115. {
  116. LPC_PINCON->PINSEL4 &= ~0x0000000F;
  117. LPC_PINCON->PINSEL4 |= 0x0000000A; /* Enable RxD1 P2.1, TxD1 P2.0 */
  118. /* By default, the PCLKSELx value is zero, thus, the PCLK for
  119. all the peripherals is 1/4 of the SystemFrequency. */
  120. /* Bit 8,9 are for UART1 */
  121. pclkdiv = (LPC_SC->PCLKSEL0 >> 8) & 0x03;
  122. switch ( pclkdiv )
  123. {
  124. case 0x00:
  125. default:
  126. pclk = SystemFrequency/4;
  127. break;
  128. case 0x01:
  129. pclk = SystemFrequency;
  130. break;
  131. case 0x02:
  132. pclk = SystemFrequency/2;
  133. break;
  134. case 0x03:
  135. pclk = SystemFrequency/8;
  136. break;
  137. }
  138. LPC_UART1->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
  139. Fdiv = ( pclk / 16 ) / UART_BAUDRATE ; /*baud rate */
  140. LPC_UART1->DLM = Fdiv / 256;
  141. LPC_UART1->DLL = Fdiv % 256;
  142. LPC_UART1->LCR = 0x03; /* DLAB = 0 */
  143. LPC_UART1->FCR = 0x07; /* Enable and reset TX and RX FIFO. */
  144. }
  145. /* Ensure a clean start, no data in either TX or RX FIFO. */
  146. while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) );
  147. while ( LPC_UART->LSR & LSR_RDR )
  148. {
  149. Fdiv = LPC_UART->RBR; /* Dump data from RX FIFO */
  150. }
  151. LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART interrupt */
  152. return RT_EOK;
  153. }
  154. static rt_err_t rt_uart_open(rt_device_t dev, rt_uint16_t oflag)
  155. {
  156. RT_ASSERT(dev != RT_NULL);
  157. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  158. {
  159. /* Enable the UART Interrupt */
  160. NVIC_EnableIRQ(UART_IRQn);
  161. }
  162. return RT_EOK;
  163. }
  164. static rt_err_t rt_uart_close(rt_device_t dev)
  165. {
  166. RT_ASSERT(dev != RT_NULL);
  167. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  168. {
  169. /* Disable the UART Interrupt */
  170. NVIC_DisableIRQ(UART_IRQn);
  171. }
  172. return RT_EOK;
  173. }
  174. static rt_size_t rt_uart_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  175. {
  176. rt_uint8_t* ptr;
  177. struct rt_uart_lpc *uart = (struct rt_uart_lpc*)dev;
  178. RT_ASSERT(uart != RT_NULL);
  179. /* point to buffer */
  180. ptr = (rt_uint8_t*) buffer;
  181. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  182. {
  183. while (size)
  184. {
  185. /* interrupt receive */
  186. rt_base_t level;
  187. /* disable interrupt */
  188. level = rt_hw_interrupt_disable();
  189. if (uart->read_index != uart->save_index)
  190. {
  191. *ptr = uart->rx_buffer[uart->read_index];
  192. uart->read_index ++;
  193. if (uart->read_index >= RT_UART_RX_BUFFER_SIZE)
  194. uart->read_index = 0;
  195. }
  196. else
  197. {
  198. /* no data in rx buffer */
  199. /* enable interrupt */
  200. rt_hw_interrupt_enable(level);
  201. break;
  202. }
  203. /* enable interrupt */
  204. rt_hw_interrupt_enable(level);
  205. ptr ++;
  206. size --;
  207. }
  208. return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
  209. }
  210. return 0;
  211. }
  212. static rt_size_t rt_uart_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
  213. {
  214. char *ptr;
  215. ptr = (char*)buffer;
  216. if (dev->flag & RT_DEVICE_FLAG_STREAM)
  217. {
  218. /* stream mode */
  219. while (size)
  220. {
  221. if (*ptr == '\n')
  222. {
  223. /* THRE status, contain valid data */
  224. while ( !(LPC_UART->LSR & LSR_THRE) );
  225. /* write data */
  226. LPC_UART->THR = '\r';
  227. }
  228. /* THRE status, contain valid data */
  229. while ( !(LPC_UART->LSR & LSR_THRE) );
  230. /* write data */
  231. LPC_UART->THR = *ptr;
  232. ptr ++;
  233. size --;
  234. }
  235. }
  236. else
  237. {
  238. while ( size != 0 )
  239. {
  240. /* THRE status, contain valid data */
  241. while ( !(LPC_UART->LSR & LSR_THRE) );
  242. /* write data */
  243. LPC_UART->THR = *ptr;
  244. ptr++;
  245. size--;
  246. }
  247. }
  248. return (rt_size_t) ptr - (rt_size_t) buffer;
  249. }
  250. void rt_hw_uart_init(void)
  251. {
  252. struct rt_uart_lpc* uart;
  253. /* get uart device */
  254. uart = &uart_device;
  255. /* device initialization */
  256. uart->parent.type = RT_Device_Class_Char;
  257. rt_memset(uart->rx_buffer, 0, sizeof(uart->rx_buffer));
  258. uart->read_index = uart->save_index = 0;
  259. /* device interface */
  260. uart->parent.init = rt_uart_init;
  261. uart->parent.open = rt_uart_open;
  262. uart->parent.close = rt_uart_close;
  263. uart->parent.read = rt_uart_read;
  264. uart->parent.write = rt_uart_write;
  265. uart->parent.control = RT_NULL;
  266. uart->parent.private = RT_NULL;
  267. rt_device_register(&uart->parent,
  268. "uart0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_INT_RX);
  269. }
  270. #endif /* end of UART */
  271. /*@}*/