uart.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /****************************************************************************
  2. * $Id:: uart.c 3736 2010-06-24 02:07:03Z usb00423 $
  3. * Project: NXP LPC122x UART example
  4. *
  5. * Description:
  6. * This file contains UART code example which include UART
  7. * initialization, UART interrupt handler, and related APIs for
  8. * UART access.
  9. *
  10. ****************************************************************************
  11. * Software that is described herein is for illustrative purposes only
  12. * which provides customers with programming information regarding the
  13. * products. This software is supplied "AS IS" without any warranties.
  14. * NXP Semiconductors assumes no responsibility or liability for the
  15. * use of the software, conveys no license or title under any patent,
  16. * copyright, or mask work right to the product. NXP Semiconductors
  17. * reserves the right to make changes in the software without
  18. * notification. NXP Semiconductors also make no representation or
  19. * warranty that such application will be suitable for the specified
  20. * use without further testing or modification.
  21. ****************************************************************************/
  22. #include <rthw.h>
  23. #include <rtthread.h>
  24. #include <CMSIS/LPC122x.h>
  25. #include "uart.h"
  26. #define IER_RBR 0x01
  27. #define IER_THRE 0x02
  28. #define IER_RLS 0x04
  29. #define IIR_PEND 0x01
  30. #define IIR_RLS 0x03
  31. #define IIR_RDA 0x02
  32. #define IIR_CTI 0x06
  33. #define IIR_THRE 0x01
  34. #define LSR_RDR 0x01
  35. #define LSR_OE 0x02
  36. #define LSR_PE 0x04
  37. #define LSR_FE 0x08
  38. #define LSR_BI 0x10
  39. #define LSR_THRE 0x20
  40. #define LSR_TEMT 0x40
  41. #define LSR_RXFE 0x80
  42. /**
  43. * @addtogroup LPC11xx
  44. */
  45. /*@{*/
  46. #if defined(RT_USING_UART) && defined(RT_USING_DEVICE)
  47. #define UART_BAUDRATE 115200
  48. struct rt_uart_lpc
  49. {
  50. struct rt_device parent;
  51. /* buffer for reception */
  52. rt_uint8_t read_index, save_index;
  53. rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE];
  54. }uart_device;
  55. void UART0_IRQHandler(void)
  56. {
  57. rt_ubase_t level, iir;
  58. struct rt_uart_lpc* uart = &uart_device;
  59. /* read IIR and clear it */
  60. iir = LPC_UART0->IIR;
  61. iir >>= 0x01; /* skip pending bit in IIR */
  62. iir &= 0x07; /* check bit 1~3, interrupt identification */
  63. if (iir == IIR_RDA) /* Receive Line Status */
  64. {
  65. /* If no error on RLS, normal ready, save into the data buffer. */
  66. /* Note: read RBR will clear the interrupt */
  67. uart->rx_buffer[uart->save_index] = LPC_UART0->RBR;
  68. level = rt_hw_interrupt_disable();
  69. uart->save_index ++;
  70. if (uart->save_index >= RT_UART_RX_BUFFER_SIZE)
  71. uart->save_index = 0;
  72. rt_hw_interrupt_enable(level);
  73. /* invoke callback */
  74. if(uart->parent.rx_indicate != RT_NULL)
  75. {
  76. rt_size_t length;
  77. if (uart->read_index > uart->save_index)
  78. length = RT_UART_RX_BUFFER_SIZE - uart->read_index + uart->save_index;
  79. else
  80. length = uart->save_index - uart->read_index;
  81. uart->parent.rx_indicate(&uart->parent, length);
  82. }
  83. }
  84. return;
  85. }
  86. /*****************************************************************************
  87. ** Function name: rt_uart_init
  88. ** Descriptions:
  89. ** parameters: dev
  90. ** Returned value: None
  91. *****************************************************************************/
  92. static rt_err_t rt_uart_init(rt_device_t dev)
  93. {
  94. rt_uint32_t Fdiv;
  95. rt_uint32_t regVal;
  96. NVIC_DisableIRQ(UART0_IRQn);
  97. /* Init UART Hardware */
  98. LPC_IOCON->PIO0_1 &= ~0x07; /* UART I/O config */
  99. LPC_IOCON->PIO0_1 |= 0x02; /* UART RXD */
  100. LPC_IOCON->PIO0_2 &= ~0x07;
  101. LPC_IOCON->PIO0_2 |= 0x02; /* UART TXD */
  102. /* Enable UART clock */
  103. LPC_SYSCON->PRESETCTRL |= (0x1<<2);
  104. LPC_SYSCON->SYSAHBCLKCTRL |= (0x1<<12);
  105. LPC_SYSCON->UART0CLKDIV = 0x1; /* divided by 1 */
  106. LPC_UART0->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
  107. regVal = LPC_SYSCON->UART0CLKDIV;
  108. Fdiv = ((SystemAHBFrequency/regVal)/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. /* Read to clear the line status. */
  114. regVal = LPC_UART0->LSR;
  115. /* Ensure a clean start, no data in either TX or RX FIFO. */
  116. while ( LPC_UART0->LSR & (LSR_THRE|LSR_TEMT) != (LSR_THRE|LSR_TEMT) );
  117. while ( LPC_UART0->LSR & LSR_RDR )
  118. {
  119. regVal = LPC_UART0->RBR; /* Dump data from RX FIFO */
  120. }
  121. /* Enable the UART Interrupt */
  122. NVIC_EnableIRQ(UART0_IRQn);
  123. LPC_UART0->IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART interrupt */
  124. return RT_EOK;
  125. }
  126. static rt_err_t rt_uart_open(rt_device_t dev, rt_uint16_t oflag)
  127. {
  128. RT_ASSERT(dev != RT_NULL);
  129. if(dev->flag & RT_DEVICE_FLAG_INT_RX)
  130. {
  131. /* Enable the UART Interrupt */
  132. NVIC_EnableIRQ(UART0_IRQn);
  133. }
  134. return RT_EOK;
  135. }
  136. static rt_err_t rt_uart_close(rt_device_t dev)
  137. {
  138. RT_ASSERT(dev != RT_NULL);
  139. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  140. {
  141. /* Disable the UART Interrupt */
  142. NVIC_DisableIRQ(UART0_IRQn);
  143. }
  144. return RT_EOK;
  145. }
  146. static rt_size_t rt_uart_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  147. {
  148. rt_uint8_t* ptr;
  149. struct rt_uart_lpc *uart = (struct rt_uart_lpc*)dev;
  150. RT_ASSERT(uart != RT_NULL);
  151. /* point to buffer */
  152. ptr = (rt_uint8_t*) buffer;
  153. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  154. {
  155. while (size)
  156. {
  157. /* interrupt receive */
  158. rt_base_t level;
  159. /* disable interrupt */
  160. level = rt_hw_interrupt_disable();
  161. if (uart->read_index != uart->save_index)
  162. {
  163. *ptr = uart->rx_buffer[uart->read_index];
  164. uart->read_index ++;
  165. if (uart->read_index >= RT_UART_RX_BUFFER_SIZE)
  166. uart->read_index = 0;
  167. }
  168. else
  169. {
  170. /* no data in rx buffer */
  171. /* enable interrupt */
  172. rt_hw_interrupt_enable(level);
  173. break;
  174. }
  175. /* enable interrupt */
  176. rt_hw_interrupt_enable(level);
  177. ptr ++;
  178. size --;
  179. }
  180. return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
  181. }
  182. return 0;
  183. }
  184. static rt_size_t rt_uart_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
  185. {
  186. char *ptr;
  187. ptr = (char*)buffer;
  188. if (dev->flag & RT_DEVICE_FLAG_STREAM)
  189. {
  190. /* stream mode */
  191. while (size)
  192. {
  193. if (*ptr == '\n')
  194. {
  195. /* THRE status, contain valid data */
  196. while ( !(LPC_UART0->LSR & LSR_THRE) );
  197. /* write data */
  198. LPC_UART0->THR = '\r';
  199. }
  200. /* THRE status, contain valid data */
  201. while ( !(LPC_UART0->LSR & LSR_THRE) );
  202. /* write data */
  203. LPC_UART0->THR = *ptr;
  204. ptr ++;
  205. size --;
  206. }
  207. }
  208. else
  209. {
  210. while ( size != 0 )
  211. {
  212. /* THRE status, contain valid data */
  213. while ( !(LPC_UART0->LSR & LSR_THRE) );
  214. /* write data */
  215. LPC_UART0->THR = *ptr;
  216. ptr++;
  217. size--;
  218. }
  219. }
  220. return (rt_size_t) ptr - (rt_size_t) buffer;
  221. }
  222. void rt_hw_uart_init(void)
  223. {
  224. struct rt_uart_lpc* uart;
  225. /* get uart device */
  226. uart = &uart_device;
  227. /* device initialization */
  228. uart->parent.type = RT_Device_Class_Char;
  229. rt_memset(uart->rx_buffer, 0, sizeof(uart->rx_buffer));
  230. uart->read_index = uart->save_index = 0;
  231. /* device interface */
  232. uart->parent.init = rt_uart_init;
  233. uart->parent.open = rt_uart_open;
  234. uart->parent.close = rt_uart_close;
  235. uart->parent.read = rt_uart_read;
  236. uart->parent.write = rt_uart_write;
  237. uart->parent.control = RT_NULL;
  238. uart->parent.user_data = RT_NULL;
  239. rt_device_register(&uart->parent,
  240. "uart", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_INT_RX);
  241. }
  242. #endif
  243. /******************************************************************************
  244. ** End Of File
  245. ******************************************************************************/