serial.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /*
  2. * File : serial.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006, RT-Thread Development 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://openlab.rt-thread.com/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2011-01-13 weety first version
  13. */
  14. #include <rtthread.h>
  15. #include "serial.h"
  16. /**
  17. * @addtogroup AT91SAM926X
  18. */
  19. /*@{*/
  20. /* RT-Thread Device Interface */
  21. /**
  22. * This function initializes serial
  23. */
  24. static rt_err_t rt_serial_init (rt_device_t dev)
  25. {
  26. struct serial_device* uart = (struct serial_device*) dev->user_data;
  27. if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
  28. {
  29. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  30. {
  31. rt_memset(uart->int_rx->rx_buffer, 0,
  32. sizeof(uart->int_rx->rx_buffer));
  33. uart->int_rx->read_index = uart->int_rx->save_index = 0;
  34. }
  35. if (dev->flag & RT_DEVICE_FLAG_INT_TX)
  36. {
  37. rt_memset(uart->int_tx->tx_buffer, 0,
  38. sizeof(uart->int_tx->tx_buffer));
  39. uart->int_tx->write_index = uart->int_tx->save_index = 0;
  40. }
  41. dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
  42. }
  43. return RT_EOK;
  44. }
  45. /* save a char to serial buffer */
  46. static void rt_serial_savechar(struct serial_device* uart, char ch)
  47. {
  48. rt_base_t level;
  49. /* disable interrupt */
  50. level = rt_hw_interrupt_disable();
  51. uart->int_rx->rx_buffer[uart->int_rx->save_index] = ch;
  52. uart->int_rx->save_index ++;
  53. if (uart->int_rx->save_index >= UART_RX_BUFFER_SIZE)
  54. uart->int_rx->save_index = 0;
  55. /* if the next position is read index, discard this 'read char' */
  56. if (uart->int_rx->save_index == uart->int_rx->read_index)
  57. {
  58. uart->int_rx->read_index ++;
  59. if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE)
  60. uart->int_rx->read_index = 0;
  61. }
  62. /* enable interrupt */
  63. rt_hw_interrupt_enable(level);
  64. }
  65. static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
  66. {
  67. RT_ASSERT(dev != RT_NULL);
  68. return RT_EOK;
  69. }
  70. static rt_err_t rt_serial_close(rt_device_t dev)
  71. {
  72. RT_ASSERT(dev != RT_NULL);
  73. return RT_EOK;
  74. }
  75. static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  76. {
  77. rt_uint8_t* ptr;
  78. rt_err_t err_code;
  79. struct serial_device* uart;
  80. ptr = buffer;
  81. err_code = RT_EOK;
  82. uart = (struct serial_device*)dev->user_data;
  83. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  84. {
  85. rt_base_t level;
  86. /* interrupt mode Rx */
  87. while (size)
  88. {
  89. if (uart->int_rx->read_index != uart->int_rx->save_index)
  90. {
  91. *ptr++ = uart->int_rx->rx_buffer[uart->int_rx->read_index];
  92. size --;
  93. /* disable interrupt */
  94. level = rt_hw_interrupt_disable();
  95. uart->int_rx->read_index ++;
  96. if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE)
  97. uart->int_rx->read_index = 0;
  98. /* enable interrupt */
  99. rt_hw_interrupt_enable(level);
  100. }
  101. else
  102. {
  103. /* set error code */
  104. err_code = -RT_EEMPTY;
  105. break;
  106. }
  107. }
  108. }
  109. else
  110. {
  111. /* polling mode */
  112. while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size)
  113. {
  114. while (uart->uart_device->USART_CSR & RXRDY)
  115. {
  116. *ptr = uart->uart_device->USART_RHR & 0xff;
  117. ptr ++;
  118. }
  119. }
  120. }
  121. /* set error code */
  122. rt_set_errno(err_code);
  123. return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
  124. }
  125. static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
  126. {
  127. rt_uint8_t* ptr;
  128. rt_err_t err_code;
  129. struct serial_device* uart;
  130. err_code = RT_EOK;
  131. ptr = (rt_uint8_t*)buffer;
  132. uart = (struct serial_device*)dev->user_data;
  133. if (dev->flag & RT_DEVICE_FLAG_INT_TX)
  134. {
  135. /* interrupt mode Tx */
  136. while (uart->int_tx->save_index != uart->int_tx->write_index)
  137. {
  138. /* save on tx buffer */
  139. uart->int_tx->tx_buffer[uart->int_tx->save_index] = *ptr++;
  140. -- size;
  141. /* move to next position */
  142. uart->int_tx->save_index ++;
  143. /* wrap save index */
  144. if (uart->int_tx->save_index >= UART_TX_BUFFER_SIZE)
  145. uart->int_tx->save_index = 0;
  146. }
  147. /* set error code */
  148. if (size > 0)
  149. err_code = -RT_EFULL;
  150. }
  151. else
  152. {
  153. /* polling mode */
  154. while (size)
  155. {
  156. /*
  157. * to be polite with serial console add a line feed
  158. * to the carriage return character
  159. */
  160. if (*ptr == '\n' && (dev->flag & RT_DEVICE_FLAG_STREAM))
  161. {
  162. while (!(uart->uart_device->USART_CSR & TXRDY));
  163. uart->uart_device->USART_THR = '\r';
  164. }
  165. while (!(uart->uart_device->USART_CSR & TXRDY));
  166. uart->uart_device->USART_THR = (*ptr & 0xFF);
  167. ++ptr; --size;
  168. }
  169. }
  170. /* set error code */
  171. rt_set_errno(err_code);
  172. return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
  173. }
  174. static rt_err_t rt_serial_control (rt_device_t dev, rt_uint8_t cmd, void *args)
  175. {
  176. RT_ASSERT(dev != RT_NULL);
  177. switch (cmd)
  178. {
  179. case RT_DEVICE_CTRL_SUSPEND:
  180. /* suspend device */
  181. dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
  182. break;
  183. case RT_DEVICE_CTRL_RESUME:
  184. /* resume device */
  185. dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
  186. break;
  187. }
  188. return RT_EOK;
  189. }
  190. /*
  191. * serial register
  192. */
  193. rt_err_t rt_hw_serial_register(rt_device_t device, const char* name, rt_uint32_t flag, struct serial_device *serial)
  194. {
  195. RT_ASSERT(device != RT_NULL);
  196. device->type = RT_Device_Class_Char;
  197. device->rx_indicate = RT_NULL;
  198. device->tx_complete = RT_NULL;
  199. device->init = rt_serial_init;
  200. device->open = rt_serial_open;
  201. device->close = rt_serial_close;
  202. device->read = rt_serial_read;
  203. device->write = rt_serial_write;
  204. device->control = rt_serial_control;
  205. device->user_data = serial;
  206. /* register a character device */
  207. return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);
  208. }
  209. /* ISR for serial interrupt */
  210. void rt_hw_serial_isr(rt_device_t device)
  211. {
  212. struct serial_device* uart = (struct serial_device*) device->user_data;
  213. /* interrupt mode receive */
  214. RT_ASSERT(device->flag & RT_DEVICE_FLAG_INT_RX);
  215. /* save on rx buffer */
  216. while (uart->uart_device->USART_CSR & RXRDY)
  217. {
  218. rt_serial_savechar(uart, uart->uart_device->USART_RHR & 0xff);
  219. }
  220. /* invoke callback */
  221. if (device->rx_indicate != RT_NULL)
  222. {
  223. rt_size_t rx_length;
  224. /* get rx length */
  225. rx_length = uart->int_rx->read_index > uart->int_rx->save_index ?
  226. UART_RX_BUFFER_SIZE - uart->int_rx->read_index + uart->int_rx->save_index :
  227. uart->int_rx->save_index - uart->int_rx->read_index;
  228. device->rx_indicate(device, rx_length);
  229. }
  230. }
  231. /*@}*/