serial.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /*
  2. * File : serial.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2013-03-16 Peng Fan Modified from sep4020
  23. */
  24. #include <rtthread.h>
  25. #include <rthw.h>
  26. #include "serial.h"
  27. /**
  28. * @addtogroup sep6200
  29. */
  30. /*@{*/
  31. /* RT-Thread Device Interface */
  32. /**
  33. * This function initializes serial
  34. */
  35. static rt_err_t rt_serial_init (rt_device_t dev)
  36. {
  37. struct serial_device* uart = (struct serial_device*) dev->user_data;
  38. if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
  39. {
  40. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  41. {
  42. rt_memset(uart->int_rx->rx_buffer, 0,
  43. sizeof(uart->int_rx->rx_buffer));
  44. uart->int_rx->read_index = uart->int_rx->save_index = 0;
  45. }
  46. if (dev->flag & RT_DEVICE_FLAG_INT_TX)
  47. {
  48. rt_memset(uart->int_tx->tx_buffer, 0,
  49. sizeof(uart->int_tx->tx_buffer));
  50. uart->int_tx->write_index = uart->int_tx->save_index = 0;
  51. }
  52. dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
  53. }
  54. return RT_EOK;
  55. }
  56. /* save a char to serial buffer */
  57. static void rt_serial_savechar(struct serial_device* uart, char ch)
  58. {
  59. rt_base_t level;
  60. /* disable interrupt */
  61. level = rt_hw_interrupt_disable();
  62. uart->int_rx->rx_buffer[uart->int_rx->save_index] = ch;
  63. uart->int_rx->save_index ++;
  64. if (uart->int_rx->save_index >= UART_RX_BUFFER_SIZE)
  65. uart->int_rx->save_index = 0;
  66. /* if the next position is read index, discard this 'read char' */
  67. if (uart->int_rx->save_index == uart->int_rx->read_index)
  68. {
  69. uart->int_rx->read_index ++;
  70. if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE)
  71. uart->int_rx->read_index = 0;
  72. }
  73. /* enable interrupt */
  74. rt_hw_interrupt_enable(level);
  75. }
  76. static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
  77. {
  78. RT_ASSERT(dev != RT_NULL);
  79. return RT_EOK;
  80. }
  81. static rt_err_t rt_serial_close(rt_device_t dev)
  82. {
  83. RT_ASSERT(dev != RT_NULL);
  84. return RT_EOK;
  85. }
  86. static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  87. {
  88. rt_uint8_t* ptr;
  89. rt_err_t err_code;
  90. struct serial_device* uart;
  91. ptr = buffer;
  92. err_code = RT_EOK;
  93. uart = (struct serial_device*)dev->user_data;
  94. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  95. {
  96. rt_base_t level;
  97. /* interrupt mode Rx */
  98. while (size)
  99. {
  100. if (uart->int_rx->read_index != uart->int_rx->save_index)
  101. {
  102. *ptr++ = uart->int_rx->rx_buffer[uart->int_rx->read_index];
  103. size --;
  104. /* disable interrupt */
  105. level = rt_hw_interrupt_disable();
  106. uart->int_rx->read_index ++;
  107. if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE)
  108. uart->int_rx->read_index = 0;
  109. /* enable interrupt */
  110. rt_hw_interrupt_enable(level);
  111. }
  112. else
  113. {
  114. /* set error code */
  115. err_code = -RT_EEMPTY;
  116. break;
  117. }
  118. }
  119. }
  120. else
  121. {
  122. /* polling mode */
  123. while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size)
  124. {
  125. while (uart->uart_device->lsr & USTAT_RCV_READY)
  126. {
  127. *ptr = uart->uart_device->dlbl_fifo.txfifo & 0xff;
  128. ptr ++;
  129. }
  130. }
  131. }
  132. /* set error code */
  133. rt_set_errno(err_code);
  134. return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
  135. }
  136. static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
  137. {
  138. rt_uint8_t* ptr;
  139. rt_err_t err_code;
  140. struct serial_device* uart;
  141. err_code = RT_EOK;
  142. ptr = (rt_uint8_t*)buffer;
  143. uart = (struct serial_device*)dev->user_data;
  144. if (dev->flag & RT_DEVICE_FLAG_INT_TX)
  145. {
  146. /* interrupt mode Tx */
  147. while (uart->int_tx->save_index != uart->int_tx->write_index)
  148. {
  149. /* save on tx buffer */
  150. uart->int_tx->tx_buffer[uart->int_tx->save_index] = *ptr++;
  151. -- size;
  152. /* move to next position */
  153. uart->int_tx->save_index ++;
  154. /* wrap save index */
  155. if (uart->int_tx->save_index >= UART_TX_BUFFER_SIZE)
  156. uart->int_tx->save_index = 0;
  157. }
  158. /* set error code */
  159. if (size > 0)
  160. err_code = -RT_EFULL;
  161. }
  162. else
  163. {
  164. /* polling mode */
  165. while (size)
  166. {
  167. /*
  168. * to be polite with serial console add a line feed
  169. * to the carriage return character
  170. */
  171. if (*ptr == '\n' && (dev->flag & RT_DEVICE_FLAG_STREAM))
  172. {
  173. while (!(uart->uart_device->lsr & USTAT_TXB_EMPTY));
  174. uart->uart_device->dlbl_fifo.txfifo = '\r';
  175. }
  176. while (!(uart->uart_device->lsr & USTAT_TXB_EMPTY));
  177. uart->uart_device->dlbl_fifo.txfifo = (*ptr & 0x1FF);
  178. ++ptr; --size;
  179. }
  180. }
  181. /* set error code */
  182. rt_set_errno(err_code);
  183. return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
  184. }
  185. static rt_err_t rt_serial_control (rt_device_t dev, int cmd, void *args)
  186. {
  187. RT_ASSERT(dev != RT_NULL);
  188. switch (cmd)
  189. {
  190. case RT_DEVICE_CTRL_SUSPEND:
  191. /* suspend device */
  192. dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
  193. break;
  194. case RT_DEVICE_CTRL_RESUME:
  195. /* resume device */
  196. dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
  197. break;
  198. }
  199. return RT_EOK;
  200. }
  201. /*
  202. * serial register
  203. */
  204. rt_err_t rt_hw_serial_register(rt_device_t device, const char* name, rt_uint32_t flag, struct serial_device *serial)
  205. {
  206. RT_ASSERT(device != RT_NULL);
  207. device->type = RT_Device_Class_Char;
  208. device->rx_indicate = RT_NULL;
  209. device->tx_complete = RT_NULL;
  210. device->init = rt_serial_init;
  211. device->open = rt_serial_open;
  212. device->close = rt_serial_close;
  213. device->read = rt_serial_read;
  214. device->write = rt_serial_write;
  215. device->control = rt_serial_control;
  216. device->user_data = serial;
  217. /* register a character device */
  218. return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);
  219. }
  220. /* ISR for serial interrupt */
  221. void rt_hw_serial_isr(rt_device_t device)
  222. {
  223. struct serial_device* uart = (struct serial_device*) device->user_data;
  224. /* interrupt mode receive */
  225. RT_ASSERT(device->flag & RT_DEVICE_FLAG_INT_RX);
  226. /* save on rx buffer */
  227. while (uart->uart_device->lsr & USTAT_RCV_READY)
  228. {
  229. rt_serial_savechar(uart, uart->uart_device->dlbl_fifo.rxfifo & 0xff);
  230. }
  231. /* invoke callback */
  232. if (device->rx_indicate != RT_NULL)
  233. {
  234. rt_size_t rx_length;
  235. /* get rx length */
  236. rx_length = uart->int_rx->read_index > uart->int_rx->save_index ?
  237. UART_RX_BUFFER_SIZE - uart->int_rx->read_index + uart->int_rx->save_index :
  238. uart->int_rx->save_index - uart->int_rx->read_index;
  239. device->rx_indicate(device, rx_length);
  240. }
  241. }
  242. /*@}*/