serial.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. /*
  2. * File : serial.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2012, 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. * 2006-03-13 bernard first version
  23. * 2012-05-15 lgnq modified according bernard's implementation.
  24. * 2012-05-28 bernard code cleanup
  25. * 2012-11-23 bernard fix compiler warning.
  26. * 2013-02-20 bernard use RT_SERIAL_RB_BUFSZ to define
  27. * the size of ring buffer.
  28. * 2014-07-10 bernard rewrite serial framework
  29. * 2014-12-31 bernard use open_flag for poll_tx stream mode.
  30. * 2015-05-19 Quintin fix DMA tx mod tx_dma->activated flag !=RT_FALSE BUG
  31. * in open function.
  32. * 2015-11-10 bernard fix the poll rx issue when there is no data.
  33. */
  34. #include <rthw.h>
  35. #include <rtthread.h>
  36. #include <rtdevice.h>
  37. /*
  38. * Serial poll routines
  39. */
  40. rt_inline int _serial_poll_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
  41. {
  42. int ch;
  43. int size;
  44. RT_ASSERT(serial != RT_NULL);
  45. size = length;
  46. while (length)
  47. {
  48. ch = serial->ops->getc(serial);
  49. if (ch == -1) break;
  50. *data = ch;
  51. data ++; length --;
  52. if (ch == '\n') break;
  53. }
  54. return size - length;
  55. }
  56. rt_inline int _serial_poll_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
  57. {
  58. int size;
  59. RT_ASSERT(serial != RT_NULL);
  60. size = length;
  61. while (length)
  62. {
  63. /*
  64. * to be polite with serial console add a line feed
  65. * to the carriage return character
  66. */
  67. if (*data == '\n' && (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM))
  68. {
  69. serial->ops->putc(serial, '\r');
  70. }
  71. serial->ops->putc(serial, *data);
  72. ++ data;
  73. -- length;
  74. }
  75. return size - length;
  76. }
  77. /*
  78. * Serial interrupt routines
  79. */
  80. rt_inline int _serial_int_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
  81. {
  82. int size;
  83. struct rt_serial_rx_fifo* rx_fifo;
  84. RT_ASSERT(serial != RT_NULL);
  85. size = length;
  86. rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx;
  87. RT_ASSERT(rx_fifo != RT_NULL);
  88. /* read from software FIFO */
  89. while (length)
  90. {
  91. int ch;
  92. rt_base_t level;
  93. /* disable interrupt */
  94. level = rt_hw_interrupt_disable();
  95. if (rx_fifo->get_index != rx_fifo->put_index)
  96. {
  97. ch = rx_fifo->buffer[rx_fifo->get_index];
  98. rx_fifo->get_index += 1;
  99. if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0;
  100. }
  101. else
  102. {
  103. /* no data, enable interrupt and break out */
  104. rt_hw_interrupt_enable(level);
  105. break;
  106. }
  107. /* enable interrupt */
  108. rt_hw_interrupt_enable(level);
  109. *data = ch & 0xff;
  110. data ++; length --;
  111. }
  112. return size - length;
  113. }
  114. rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
  115. {
  116. int size;
  117. struct rt_serial_tx_fifo *tx;
  118. RT_ASSERT(serial != RT_NULL);
  119. size = length;
  120. tx = (struct rt_serial_tx_fifo*) serial->serial_tx;
  121. RT_ASSERT(tx != RT_NULL);
  122. while (length)
  123. {
  124. if (serial->ops->putc(serial, *(char*)data) == -1)
  125. {
  126. rt_completion_wait(&(tx->completion), RT_WAITING_FOREVER);
  127. continue;
  128. }
  129. data ++; length --;
  130. }
  131. return size - length;
  132. }
  133. /*
  134. * Serial DMA routines
  135. */
  136. rt_inline int _serial_dma_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
  137. {
  138. rt_base_t level;
  139. int result = RT_EOK;
  140. struct rt_serial_rx_dma *rx_dma;
  141. RT_ASSERT((serial != RT_NULL) && (data != RT_NULL));
  142. rx_dma = (struct rt_serial_rx_dma*)serial->serial_rx;
  143. RT_ASSERT(rx_dma != RT_NULL);
  144. level = rt_hw_interrupt_disable();
  145. if (rx_dma->activated != RT_TRUE)
  146. {
  147. rx_dma->activated = RT_TRUE;
  148. serial->ops->dma_transmit(serial, data, length, RT_SERIAL_DMA_RX);
  149. }
  150. else result = -RT_EBUSY;
  151. rt_hw_interrupt_enable(level);
  152. if (result == RT_EOK) return length;
  153. rt_set_errno(result);
  154. return 0;
  155. }
  156. rt_inline int _serial_dma_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
  157. {
  158. rt_base_t level;
  159. rt_err_t result;
  160. struct rt_serial_tx_dma *tx_dma;
  161. tx_dma = (struct rt_serial_tx_dma*)(serial->serial_tx);
  162. result = rt_data_queue_push(&(tx_dma->data_queue), data, length, RT_WAITING_FOREVER);
  163. if (result == RT_EOK)
  164. {
  165. level = rt_hw_interrupt_disable();
  166. if (tx_dma->activated != RT_TRUE)
  167. {
  168. tx_dma->activated = RT_TRUE;
  169. rt_hw_interrupt_enable(level);
  170. /* make a DMA transfer */
  171. serial->ops->dma_transmit(serial, data, length, RT_SERIAL_DMA_TX);
  172. }
  173. else
  174. {
  175. rt_hw_interrupt_enable(level);
  176. }
  177. return length;
  178. }
  179. else
  180. {
  181. rt_set_errno(result);
  182. return 0;
  183. }
  184. }
  185. /* RT-Thread Device Interface */
  186. /*
  187. * This function initializes serial device.
  188. */
  189. static rt_err_t rt_serial_init(struct rt_device *dev)
  190. {
  191. rt_err_t result = RT_EOK;
  192. struct rt_serial_device *serial;
  193. RT_ASSERT(dev != RT_NULL);
  194. serial = (struct rt_serial_device *)dev;
  195. /* initialize rx/tx */
  196. serial->serial_rx = RT_NULL;
  197. serial->serial_tx = RT_NULL;
  198. /* apply configuration */
  199. if (serial->ops->configure)
  200. result = serial->ops->configure(serial, &serial->config);
  201. return result;
  202. }
  203. static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag)
  204. {
  205. struct rt_serial_device *serial;
  206. RT_ASSERT(dev != RT_NULL);
  207. serial = (struct rt_serial_device *)dev;
  208. /* check device flag with the open flag */
  209. if ((oflag & RT_DEVICE_FLAG_DMA_RX) && !(dev->flag & RT_DEVICE_FLAG_DMA_RX))
  210. return -RT_EIO;
  211. if ((oflag & RT_DEVICE_FLAG_DMA_TX) && !(dev->flag & RT_DEVICE_FLAG_DMA_TX))
  212. return -RT_EIO;
  213. if ((oflag & RT_DEVICE_FLAG_INT_RX) && !(dev->flag & RT_DEVICE_FLAG_INT_RX))
  214. return -RT_EIO;
  215. if ((oflag & RT_DEVICE_FLAG_INT_TX) && !(dev->flag & RT_DEVICE_FLAG_INT_TX))
  216. return -RT_EIO;
  217. /* get open flags */
  218. dev->open_flag = oflag & 0xff;
  219. /* initialize the Rx/Tx structure according to open flag */
  220. if (serial->serial_rx == RT_NULL)
  221. {
  222. if (oflag & RT_DEVICE_FLAG_DMA_RX)
  223. {
  224. struct rt_serial_rx_dma* rx_dma;
  225. rx_dma = (struct rt_serial_rx_dma*) rt_malloc (sizeof(struct rt_serial_rx_dma));
  226. RT_ASSERT(rx_dma != RT_NULL);
  227. rx_dma->activated = RT_FALSE;
  228. serial->serial_rx = rx_dma;
  229. dev->open_flag |= RT_DEVICE_FLAG_DMA_RX;
  230. }
  231. else if (oflag & RT_DEVICE_FLAG_INT_RX)
  232. {
  233. struct rt_serial_rx_fifo* rx_fifo;
  234. rx_fifo = (struct rt_serial_rx_fifo*) rt_malloc (sizeof(struct rt_serial_rx_fifo) +
  235. serial->config.bufsz);
  236. RT_ASSERT(rx_fifo != RT_NULL);
  237. rx_fifo->buffer = (rt_uint8_t*) (rx_fifo + 1);
  238. rt_memset(rx_fifo->buffer, 0, serial->config.bufsz);
  239. rx_fifo->put_index = 0;
  240. rx_fifo->get_index = 0;
  241. serial->serial_rx = rx_fifo;
  242. dev->open_flag |= RT_DEVICE_FLAG_INT_RX;
  243. /* configure low level device */
  244. serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
  245. }
  246. else
  247. {
  248. serial->serial_rx = RT_NULL;
  249. }
  250. }
  251. if (serial->serial_tx == RT_NULL)
  252. {
  253. if (oflag & RT_DEVICE_FLAG_DMA_TX)
  254. {
  255. struct rt_serial_tx_dma* tx_dma;
  256. tx_dma = (struct rt_serial_tx_dma*) rt_malloc (sizeof(struct rt_serial_tx_dma));
  257. RT_ASSERT(tx_dma != RT_NULL);
  258. tx_dma->activated = RT_FALSE;
  259. rt_data_queue_init(&(tx_dma->data_queue), 8, 4, RT_NULL);
  260. serial->serial_tx = tx_dma;
  261. dev->open_flag |= RT_DEVICE_FLAG_DMA_TX;
  262. }
  263. else if (oflag & RT_DEVICE_FLAG_INT_TX)
  264. {
  265. struct rt_serial_tx_fifo *tx_fifo;
  266. tx_fifo = (struct rt_serial_tx_fifo*) rt_malloc(sizeof(struct rt_serial_tx_fifo));
  267. RT_ASSERT(tx_fifo != RT_NULL);
  268. rt_completion_init(&(tx_fifo->completion));
  269. serial->serial_tx = tx_fifo;
  270. dev->open_flag |= RT_DEVICE_FLAG_INT_TX;
  271. /* configure low level device */
  272. serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_TX);
  273. }
  274. else
  275. {
  276. serial->serial_tx = RT_NULL;
  277. }
  278. }
  279. return RT_EOK;
  280. }
  281. static rt_err_t rt_serial_close(struct rt_device *dev)
  282. {
  283. struct rt_serial_device *serial;
  284. RT_ASSERT(dev != RT_NULL);
  285. serial = (struct rt_serial_device *)dev;
  286. /* this device has more reference count */
  287. if (dev->ref_count > 1) return RT_EOK;
  288. if (dev->open_flag & RT_DEVICE_FLAG_INT_RX)
  289. {
  290. struct rt_serial_rx_fifo* rx_fifo;
  291. rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx;
  292. RT_ASSERT(rx_fifo != RT_NULL);
  293. rt_free(rx_fifo);
  294. serial->serial_rx = RT_NULL;
  295. dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX;
  296. /* configure low level device */
  297. serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_RX);
  298. }
  299. else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX)
  300. {
  301. struct rt_serial_rx_dma* rx_dma;
  302. rx_dma = (struct rt_serial_rx_dma*)serial->serial_tx;
  303. RT_ASSERT(rx_dma != RT_NULL);
  304. rt_free(rx_dma);
  305. serial->serial_rx = RT_NULL;
  306. dev->open_flag &= ~RT_DEVICE_FLAG_DMA_RX;
  307. }
  308. if (dev->open_flag & RT_DEVICE_FLAG_INT_TX)
  309. {
  310. struct rt_serial_tx_fifo* tx_fifo;
  311. tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_rx;
  312. RT_ASSERT(tx_fifo != RT_NULL);
  313. rt_free(tx_fifo);
  314. serial->serial_tx = RT_NULL;
  315. dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX;
  316. /* configure low level device */
  317. serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX);
  318. }
  319. else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX)
  320. {
  321. struct rt_serial_tx_dma* tx_dma;
  322. tx_dma = (struct rt_serial_tx_dma*)serial->serial_tx;
  323. RT_ASSERT(tx_dma != RT_NULL);
  324. rt_free(tx_dma);
  325. serial->serial_tx = RT_NULL;
  326. dev->open_flag &= ~RT_DEVICE_FLAG_DMA_TX;
  327. }
  328. return RT_EOK;
  329. }
  330. static rt_size_t rt_serial_read(struct rt_device *dev,
  331. rt_off_t pos,
  332. void *buffer,
  333. rt_size_t size)
  334. {
  335. struct rt_serial_device *serial;
  336. RT_ASSERT(dev != RT_NULL);
  337. if (size == 0) return 0;
  338. serial = (struct rt_serial_device *)dev;
  339. if (dev->open_flag & RT_DEVICE_FLAG_INT_RX)
  340. {
  341. return _serial_int_rx(serial, buffer, size);
  342. }
  343. else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX)
  344. {
  345. return _serial_dma_rx(serial, buffer, size);
  346. }
  347. return _serial_poll_rx(serial, buffer, size);
  348. }
  349. static rt_size_t rt_serial_write(struct rt_device *dev,
  350. rt_off_t pos,
  351. const void *buffer,
  352. rt_size_t size)
  353. {
  354. struct rt_serial_device *serial;
  355. RT_ASSERT(dev != RT_NULL);
  356. if (size == 0) return 0;
  357. serial = (struct rt_serial_device *)dev;
  358. if (dev->open_flag & RT_DEVICE_FLAG_INT_TX)
  359. {
  360. return _serial_int_tx(serial, buffer, size);
  361. }
  362. else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX)
  363. {
  364. return _serial_dma_tx(serial, buffer, size);
  365. }
  366. else
  367. {
  368. return _serial_poll_tx(serial, buffer, size);
  369. }
  370. }
  371. static rt_err_t rt_serial_control(struct rt_device *dev,
  372. rt_uint8_t cmd,
  373. void *args)
  374. {
  375. struct rt_serial_device *serial;
  376. RT_ASSERT(dev != RT_NULL);
  377. serial = (struct rt_serial_device *)dev;
  378. switch (cmd)
  379. {
  380. case RT_DEVICE_CTRL_SUSPEND:
  381. /* suspend device */
  382. dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
  383. break;
  384. case RT_DEVICE_CTRL_RESUME:
  385. /* resume device */
  386. dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
  387. break;
  388. case RT_DEVICE_CTRL_CONFIG:
  389. /* configure device */
  390. serial->ops->configure(serial, (struct serial_configure *)args);
  391. break;
  392. default :
  393. /* control device */
  394. serial->ops->control(serial, cmd, args);
  395. break;
  396. }
  397. return RT_EOK;
  398. }
  399. /*
  400. * serial register
  401. */
  402. rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
  403. const char *name,
  404. rt_uint32_t flag,
  405. void *data)
  406. {
  407. struct rt_device *device;
  408. RT_ASSERT(serial != RT_NULL);
  409. device = &(serial->parent);
  410. device->type = RT_Device_Class_Char;
  411. device->rx_indicate = RT_NULL;
  412. device->tx_complete = RT_NULL;
  413. device->init = rt_serial_init;
  414. device->open = rt_serial_open;
  415. device->close = rt_serial_close;
  416. device->read = rt_serial_read;
  417. device->write = rt_serial_write;
  418. device->control = rt_serial_control;
  419. device->user_data = data;
  420. /* register a character device */
  421. return rt_device_register(device, name, flag);
  422. }
  423. /* ISR for serial interrupt */
  424. void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
  425. {
  426. switch (event & 0xff)
  427. {
  428. case RT_SERIAL_EVENT_RX_IND:
  429. {
  430. int ch = -1;
  431. rt_base_t level;
  432. struct rt_serial_rx_fifo* rx_fifo;
  433. /* interrupt mode receive */
  434. rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx;
  435. RT_ASSERT(rx_fifo != RT_NULL);
  436. while (1)
  437. {
  438. ch = serial->ops->getc(serial);
  439. if (ch == -1) break;
  440. /* disable interrupt */
  441. level = rt_hw_interrupt_disable();
  442. rx_fifo->buffer[rx_fifo->put_index] = ch;
  443. rx_fifo->put_index += 1;
  444. if (rx_fifo->put_index >= serial->config.bufsz) rx_fifo->put_index = 0;
  445. /* if the next position is read index, discard this 'read char' */
  446. if (rx_fifo->put_index == rx_fifo->get_index)
  447. {
  448. rx_fifo->get_index += 1;
  449. if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0;
  450. }
  451. /* enable interrupt */
  452. rt_hw_interrupt_enable(level);
  453. }
  454. /* invoke callback */
  455. if (serial->parent.rx_indicate != RT_NULL)
  456. {
  457. rt_size_t rx_length;
  458. /* get rx length */
  459. level = rt_hw_interrupt_disable();
  460. rx_length = (rx_fifo->put_index >= rx_fifo->get_index)? (rx_fifo->put_index - rx_fifo->get_index):
  461. (serial->config.bufsz - (rx_fifo->get_index - rx_fifo->put_index));
  462. rt_hw_interrupt_enable(level);
  463. serial->parent.rx_indicate(&serial->parent, rx_length);
  464. }
  465. break;
  466. }
  467. case RT_SERIAL_EVENT_TX_DONE:
  468. {
  469. struct rt_serial_tx_fifo* tx_fifo;
  470. tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_tx;
  471. rt_completion_done(&(tx_fifo->completion));
  472. break;
  473. }
  474. case RT_SERIAL_EVENT_TX_DMADONE:
  475. {
  476. const void *data_ptr;
  477. rt_size_t data_size;
  478. const void *last_data_ptr;
  479. struct rt_serial_tx_dma* tx_dma;
  480. tx_dma = (struct rt_serial_tx_dma*) serial->serial_tx;
  481. rt_data_queue_pop(&(tx_dma->data_queue), &last_data_ptr, &data_size, 0);
  482. if (rt_data_queue_peak(&(tx_dma->data_queue), &data_ptr, &data_size) == RT_EOK)
  483. {
  484. /* transmit next data node */
  485. tx_dma->activated = RT_TRUE;
  486. serial->ops->dma_transmit(serial, data_ptr, data_size, RT_SERIAL_DMA_TX);
  487. }
  488. else
  489. {
  490. tx_dma->activated = RT_FALSE;
  491. }
  492. /* invoke callback */
  493. if (serial->parent.tx_complete != RT_NULL)
  494. {
  495. serial->parent.tx_complete(&serial->parent, (void*)last_data_ptr);
  496. }
  497. break;
  498. }
  499. case RT_SERIAL_EVENT_RX_DMADONE:
  500. {
  501. int length;
  502. struct rt_serial_rx_dma* rx_dma;
  503. rx_dma = (struct rt_serial_rx_dma*)serial->serial_rx;
  504. /* get DMA rx length */
  505. length = (event & (~0xff)) >> 8;
  506. serial->parent.rx_indicate(&(serial->parent), length);
  507. rx_dma->activated = RT_FALSE;
  508. break;
  509. }
  510. }
  511. }