1 /*
2  * Copyright (c) 2006-2024, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2006-03-13     bernard      first version
9  * 2012-05-15     lgnq         modified according bernard's implementation.
10  * 2012-05-28     bernard      code cleanup
11  * 2012-11-23     bernard      fix compiler warning.
12  * 2013-02-20     bernard      use RT_SERIAL_RB_BUFSZ to define
13  *                             the size of ring buffer.
14  * 2014-07-10     bernard      rewrite serial framework
15  * 2014-12-31     bernard      use open_flag for poll_tx stream mode.
16  * 2015-05-19     Quintin      fix DMA tx mod tx_dma->activated flag !=RT_FALSE BUG
17  *                             in open function.
18  * 2015-11-10     bernard      fix the poll rx issue when there is no data.
19  * 2016-05-10     armink       add fifo mode to DMA rx when serial->config.bufsz != 0.
20  * 2017-01-19     aubr.cool    prevent change serial rx bufsz when serial is opened.
21  * 2017-11-07     JasonJia     fix data bits error issue when using tcsetattr.
22  * 2017-11-15     JasonJia     fix poll rx issue when data is full.
23  *                             add TCFLSH and FIONREAD support.
24  * 2018-12-08     Ernest Chen  add DMA choice
25  * 2020-09-14     WillianChan  add a line feed to the carriage return character
26  *                             when using interrupt tx
27  * 2020-12-14     Meco Man     implement function of setting window's size(TIOCSWINSZ)
28  * 2021-08-22     Meco Man     implement function of getting window's size(TIOCGWINSZ)
29  * 2023-09-15     xqyjlj       perf rt_hw_interrupt_disable/enable
30  * 2024-11-25     zhujiale     add bypass mode
31  */
32 
33 #include <rthw.h>
34 #include <rtthread.h>
35 #include <rtdevice.h>
36 
37 #define DBG_TAG    "UART"
38 #define DBG_LVL    DBG_INFO
39 #include <rtdbg.h>
40 
41 #ifdef RT_USING_POSIX_STDIO
42 #include <dfs_file.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include <poll.h>
46 #include <sys/ioctl.h>
47 
48 #ifdef RT_USING_POSIX_TERMIOS
49 #include <termios.h>
50 #endif
51 
52 /* it's possible the 'getc/putc' is defined by stdio.h in gcc/newlib. */
53 #ifdef getc
54 #undef getc
55 #endif
56 
57 #ifdef putc
58 #undef putc
59 #endif
60 
61 RT_OBJECT_HOOKLIST_DEFINE(rt_hw_serial_rxind);
62 
serial_fops_rx_ind(rt_device_t dev,rt_size_t size)63 static rt_err_t serial_fops_rx_ind(rt_device_t dev, rt_size_t size)
64 {
65     rt_wqueue_wakeup(&(dev->wait_queue), (void*)POLLIN);
66 
67     RT_OBJECT_HOOKLIST_CALL(rt_hw_serial_rxind, (dev, size));
68 
69     return RT_EOK;
70 }
71 
72 /* fops for serial */
serial_fops_open(struct dfs_file * fd)73 static int serial_fops_open(struct dfs_file *fd)
74 {
75     rt_err_t ret = 0;
76     rt_uint16_t flags = 0;
77     rt_device_t device;
78 
79     device = (rt_device_t)fd->vnode->data;
80     RT_ASSERT(device != RT_NULL);
81 
82     switch (fd->flags & O_ACCMODE)
83     {
84         case O_RDONLY:
85             LOG_D("fops open: O_RDONLY!");
86             flags = RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_RDONLY;
87             break;
88         case O_WRONLY:
89             LOG_D("fops open: O_WRONLY!");
90             flags = RT_DEVICE_FLAG_WRONLY;
91             break;
92         case O_RDWR:
93             LOG_D("fops open: O_RDWR!");
94             flags = RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_RDWR;
95             break;
96         default:
97             LOG_E("fops open: unknown mode - %d!", fd->flags & O_ACCMODE);
98             break;
99     }
100 
101     if ((fd->flags & O_ACCMODE) != O_WRONLY)
102         rt_device_set_rx_indicate(device, serial_fops_rx_ind);
103     ret = rt_device_open(device, flags);
104     if (ret == RT_EOK) return 0;
105 
106     return ret;
107 }
108 
serial_fops_close(struct dfs_file * fd)109 static int serial_fops_close(struct dfs_file *fd)
110 {
111     rt_device_t device;
112 
113     device = (rt_device_t)fd->vnode->data;
114 
115     rt_device_set_rx_indicate(device, RT_NULL);
116     rt_device_close(device);
117 
118     return 0;
119 }
120 
serial_fops_ioctl(struct dfs_file * fd,int cmd,void * args)121 static int serial_fops_ioctl(struct dfs_file *fd, int cmd, void *args)
122 {
123     rt_device_t device;
124     int flags = (int)(rt_base_t)args;
125     int mask  = O_NONBLOCK | O_APPEND;
126 
127     device = (rt_device_t)fd->vnode->data;
128     switch (cmd)
129     {
130     case FIONREAD:
131         break;
132     case FIONWRITE:
133         break;
134     case F_SETFL:
135         flags &= mask;
136         fd->flags &= ~mask;
137         fd->flags |= flags;
138         break;
139     }
140 
141     return rt_device_control(device, cmd, args);
142 }
143 
144 #ifdef RT_USING_DFS_V2
serial_fops_read(struct dfs_file * fd,void * buf,size_t count,off_t * pos)145 static ssize_t serial_fops_read(struct dfs_file *fd, void *buf, size_t count, off_t *pos)
146 #else
147 static ssize_t serial_fops_read(struct dfs_file *fd, void *buf, size_t count)
148 #endif
149 {
150     int size = 0;
151     rt_device_t device;
152     int wait_ret;
153 
154     device = (rt_device_t)fd->vnode->data;
155 
156     do
157     {
158         size = rt_device_read(device, -1,  buf, count);
159         if (size <= 0)
160         {
161             if (fd->flags & O_NONBLOCK)
162             {
163                 size = -EAGAIN;
164                 break;
165             }
166 
167             wait_ret = rt_wqueue_wait_interruptible(&(device->wait_queue), 0, RT_WAITING_FOREVER);
168             if (wait_ret != RT_EOK)
169             {
170                 break;
171             }
172         }
173     }while (size <= 0);
174 
175     if (size < 0)
176     {
177         size = 0;
178     }
179     return size;
180 }
181 
182 #ifdef RT_USING_DFS_V2
serial_fops_write(struct dfs_file * fd,const void * buf,size_t count,off_t * pos)183 static ssize_t serial_fops_write(struct dfs_file *fd, const void *buf, size_t count, off_t *pos)
184 #else
185 static ssize_t serial_fops_write(struct dfs_file *fd, const void *buf, size_t count)
186 #endif
187 {
188     rt_device_t device;
189 
190     device = (rt_device_t)fd->vnode->data;
191     return rt_device_write(device, -1, buf, count);
192 }
193 
serial_fops_poll(struct dfs_file * fd,struct rt_pollreq * req)194 static int serial_fops_poll(struct dfs_file *fd, struct rt_pollreq *req)
195 {
196     int mask = 0;
197     int flags = 0;
198     rt_device_t device;
199     struct rt_serial_device *serial;
200 
201     device = (rt_device_t)fd->vnode->data;
202     RT_ASSERT(device != RT_NULL);
203 
204     serial = (struct rt_serial_device *)device;
205 
206     /* only support POLLIN */
207     flags = fd->flags & O_ACCMODE;
208     if (flags == O_RDONLY || flags == O_RDWR)
209     {
210         rt_base_t level;
211         struct rt_serial_rx_fifo* rx_fifo;
212 
213         rt_poll_add(&(device->wait_queue), req);
214 
215         rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx;
216 
217         level = rt_spin_lock_irqsave(&(serial->spinlock));
218         if ((rx_fifo->get_index != rx_fifo->put_index) || (rx_fifo->get_index == rx_fifo->put_index && rx_fifo->is_full == RT_TRUE))
219             mask |= POLLIN;
220         rt_spin_unlock_irqrestore(&(serial->spinlock), level);
221     }
222 
223     return mask;
224 }
225 
226 static const struct dfs_file_ops _serial_fops =
227 {
228     .open   = serial_fops_open,
229     .close  = serial_fops_close,
230     .ioctl  = serial_fops_ioctl,
231     .read   = serial_fops_read,
232     .write  = serial_fops_write,
233     .poll   = serial_fops_poll,
234 };
235 #endif /* RT_USING_POSIX_STDIO */
236 
237 /*
238  * Serial poll routines
239  */
_serial_poll_rx(struct rt_serial_device * serial,rt_uint8_t * data,int length)240 rt_inline int _serial_poll_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
241 {
242     int ch;
243     int size;
244 
245     RT_ASSERT(serial != RT_NULL);
246     size = length;
247 
248     while (length)
249     {
250         ch = serial->ops->getc(serial);
251         if (ch == -1) break;
252 
253         *data = ch;
254         data ++; length --;
255 
256         if(serial->parent.open_flag & RT_DEVICE_FLAG_STREAM)
257         {
258             if (ch == '\n') break;
259         }
260     }
261 
262     return size - length;
263 }
264 
_serial_poll_tx(struct rt_serial_device * serial,const rt_uint8_t * data,int length)265 rt_inline int _serial_poll_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
266 {
267     int size;
268     RT_ASSERT(serial != RT_NULL);
269 
270     size = length;
271     while (length)
272     {
273         /*
274          * to be polite with serial console add a line feed
275          * to the carriage return character
276          */
277         if (*data == '\n' && (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM))
278         {
279             serial->ops->putc(serial, '\r');
280         }
281 
282         if(serial->ops->putc(serial, *data) < 0) {
283             break;
284         }
285 
286         ++ data;
287         -- length;
288     }
289 
290     return size - length;
291 }
292 
293 /*
294  * Serial interrupt routines
295  */
_serial_int_rx(struct rt_serial_device * serial,rt_uint8_t * data,int length)296 rt_inline int _serial_int_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
297 {
298     int size;
299     struct rt_serial_rx_fifo* rx_fifo;
300 
301     RT_ASSERT(serial != RT_NULL);
302     size = length;
303 
304     rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx;
305     RT_ASSERT(rx_fifo != RT_NULL);
306 
307 #ifdef RT_USING_SERIAL_BYPASS
308     if (serial->bypass)
309     {
310         rt_bypass_work_straight(serial);
311         while (length)
312         {
313             rt_uint8_t ch;
314             if (!rt_bypass_getchar(serial, &ch))
315                 break;
316 
317             *data = ch & 0xff;
318             data++; length--;
319         }
320 
321         return size - length;
322     }
323 #endif
324     /* read from software FIFO */
325     while (length)
326     {
327         int ch;
328         rt_base_t level;
329 
330         /* disable interrupt */
331         level = rt_spin_lock_irqsave(&(serial->spinlock));
332 
333         /* there's no data: */
334         if ((rx_fifo->get_index == rx_fifo->put_index) && (rx_fifo->is_full == RT_FALSE))
335         {
336             /* no data, enable interrupt and break out */
337             rt_spin_unlock_irqrestore(&(serial->spinlock), level);
338             break;
339         }
340 
341         /* otherwise there's the data: */
342         ch = rx_fifo->buffer[rx_fifo->get_index];
343         rx_fifo->get_index += 1;
344         if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0;
345 
346         if (rx_fifo->is_full == RT_TRUE)
347         {
348             rx_fifo->is_full = RT_FALSE;
349         }
350 
351         /* enable interrupt */
352         rt_spin_unlock_irqrestore(&(serial->spinlock), level);
353 
354         *data = ch & 0xff;
355         data ++; length --;
356     }
357 
358     return size - length;
359 }
360 
_serial_int_tx(struct rt_serial_device * serial,const rt_uint8_t * data,int length)361 rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
362 {
363     int size;
364     struct rt_serial_tx_fifo *tx;
365 
366     RT_ASSERT(serial != RT_NULL);
367 
368     size = length;
369     tx = (struct rt_serial_tx_fifo*) serial->serial_tx;
370     RT_ASSERT(tx != RT_NULL);
371 
372     while (length)
373     {
374         /*
375          * to be polite with serial console add a line feed
376          * to the carriage return character
377          */
378         if (*data == '\n' && (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM))
379         {
380             if (serial->ops->putc(serial, '\r') == -1)
381             {
382                 rt_completion_wait(&(tx->completion), RT_WAITING_FOREVER);
383                 continue;
384             }
385         }
386 
387         while (serial->ops->putc(serial, *(char*)data) == -1)
388         {
389             rt_completion_wait(&(tx->completion), RT_WAITING_FOREVER);
390         }
391 
392         data ++; length --;
393     }
394 
395     return size - length;
396 }
397 
_serial_check_buffer_size(void)398 static void _serial_check_buffer_size(void)
399 {
400     static rt_bool_t already_output = RT_FALSE;
401 
402     if (already_output == RT_FALSE)
403     {
404 #if !defined(RT_USING_ULOG) || defined(ULOG_USING_ISR_LOG)
405         LOG_W("Warning: There is no enough buffer for saving data,"
406               " please increase the RT_SERIAL_RB_BUFSZ option.");
407 #endif
408         already_output = RT_TRUE;
409     }
410 }
411 
412 #if defined(RT_USING_POSIX_STDIO) || defined(RT_SERIAL_USING_DMA)
_serial_fifo_calc_recved_len(struct rt_serial_device * serial)413 static rt_ssize_t _serial_fifo_calc_recved_len(struct rt_serial_device *serial)
414 {
415     struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
416 
417     RT_ASSERT(rx_fifo != RT_NULL);
418 
419     if (rx_fifo->put_index == rx_fifo->get_index)
420     {
421         return (rx_fifo->is_full == RT_FALSE ? 0 : serial->config.bufsz);
422     }
423     else
424     {
425         if (rx_fifo->put_index > rx_fifo->get_index)
426         {
427             return rx_fifo->put_index - rx_fifo->get_index;
428         }
429         else
430         {
431             return serial->config.bufsz - (rx_fifo->get_index - rx_fifo->put_index);
432         }
433     }
434 }
435 #endif /* RT_USING_POSIX_STDIO || RT_SERIAL_USING_DMA */
436 
437 #ifdef RT_SERIAL_USING_DMA
438 /**
439  * Calculate DMA received data length.
440  *
441  * @param serial serial device
442  *
443  * @return length
444  */
rt_dma_calc_recved_len(struct rt_serial_device * serial)445 static rt_ssize_t rt_dma_calc_recved_len(struct rt_serial_device *serial)
446 {
447     return _serial_fifo_calc_recved_len(serial);
448 }
449 
450 /**
451  * Read data finish by DMA mode then update the get index for receive fifo.
452  *
453  * @param serial serial device
454  * @param len get data length for this operate
455  */
rt_dma_recv_update_get_index(struct rt_serial_device * serial,rt_size_t len)456 static void rt_dma_recv_update_get_index(struct rt_serial_device *serial, rt_size_t len)
457 {
458     struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
459 
460     RT_ASSERT(rx_fifo != RT_NULL);
461     RT_ASSERT(len <= rt_dma_calc_recved_len(serial));
462 
463     if (rx_fifo->is_full && len != 0) rx_fifo->is_full = RT_FALSE;
464 
465     rx_fifo->get_index += (rt_uint16_t)len;
466     if (rx_fifo->get_index >= serial->config.bufsz)
467     {
468         rx_fifo->get_index %= serial->config.bufsz;
469     }
470 }
471 
472 /**
473  * DMA received finish then update put index for receive fifo.
474  *
475  * @param serial serial device
476  * @param len received length for this transmit
477  */
rt_dma_recv_update_put_index(struct rt_serial_device * serial,rt_size_t len)478 static void rt_dma_recv_update_put_index(struct rt_serial_device *serial, rt_size_t len)
479 {
480     struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
481 
482     RT_ASSERT(rx_fifo != RT_NULL);
483 
484     if (rx_fifo->get_index <= rx_fifo->put_index)
485     {
486         rx_fifo->put_index += (rt_uint16_t)len;
487         /* beyond the fifo end */
488         if (rx_fifo->put_index >= serial->config.bufsz)
489         {
490             rx_fifo->put_index %= serial->config.bufsz;
491             /* force overwrite get index */
492             if (rx_fifo->put_index >= rx_fifo->get_index)
493             {
494                 rx_fifo->is_full = RT_TRUE;
495             }
496         }
497     }
498     else
499     {
500         rx_fifo->put_index += (rt_uint16_t)len;
501         if (rx_fifo->put_index >= rx_fifo->get_index)
502         {
503             /* beyond the fifo end */
504             if (rx_fifo->put_index >= serial->config.bufsz)
505             {
506                 rx_fifo->put_index %= serial->config.bufsz;
507             }
508             /* force overwrite get index */
509             rx_fifo->is_full = RT_TRUE;
510         }
511     }
512 
513     if(rx_fifo->is_full == RT_TRUE)
514     {
515         _serial_check_buffer_size();
516         rx_fifo->get_index = rx_fifo->put_index;
517     }
518 }
519 
520 /*
521  * Serial DMA routines
522  */
_serial_dma_rx(struct rt_serial_device * serial,rt_uint8_t * data,int length)523 rt_inline int _serial_dma_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
524 {
525     rt_base_t level;
526 
527     RT_ASSERT((serial != RT_NULL) && (data != RT_NULL));
528 
529     level = rt_spin_lock_irqsave(&(serial->spinlock));
530 
531     if (serial->config.bufsz == 0)
532     {
533         int result = RT_EOK;
534         struct rt_serial_rx_dma *rx_dma;
535 
536         rx_dma = (struct rt_serial_rx_dma*)serial->serial_rx;
537         RT_ASSERT(rx_dma != RT_NULL);
538 
539         if (rx_dma->activated != RT_TRUE)
540         {
541             rx_dma->activated = RT_TRUE;
542             RT_ASSERT(serial->ops->dma_transmit != RT_NULL);
543             serial->ops->dma_transmit(serial, data, length, RT_SERIAL_DMA_RX);
544         }
545         else result = -RT_EBUSY;
546         rt_spin_unlock_irqrestore(&(serial->spinlock), level);
547 
548         if (result == RT_EOK) return length;
549 
550         rt_set_errno(result);
551         return 0;
552     }
553     else
554     {
555         struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
556         rt_size_t recv_len = 0, fifo_recved_len = rt_dma_calc_recved_len(serial);
557 
558         RT_ASSERT(rx_fifo != RT_NULL);
559 
560         if (length < (int)fifo_recved_len)
561             recv_len = length;
562         else
563             recv_len = fifo_recved_len;
564 
565         if (rx_fifo->get_index + recv_len < serial->config.bufsz)
566             rt_memcpy(data, rx_fifo->buffer + rx_fifo->get_index, recv_len);
567         else
568         {
569             rt_memcpy(data, rx_fifo->buffer + rx_fifo->get_index,
570                     serial->config.bufsz - rx_fifo->get_index);
571             rt_memcpy(data + serial->config.bufsz - rx_fifo->get_index, rx_fifo->buffer,
572                     recv_len + rx_fifo->get_index - serial->config.bufsz);
573         }
574         rt_dma_recv_update_get_index(serial, recv_len);
575         rt_spin_unlock_irqrestore(&(serial->spinlock), level);
576         return recv_len;
577     }
578 }
579 
_serial_dma_tx(struct rt_serial_device * serial,const rt_uint8_t * data,int length)580 rt_inline int _serial_dma_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
581 {
582     rt_base_t level;
583     rt_err_t result;
584     struct rt_serial_tx_dma *tx_dma;
585 
586     tx_dma = (struct rt_serial_tx_dma*)(serial->serial_tx);
587 
588     result = rt_data_queue_push(&(tx_dma->data_queue), data, length, RT_WAITING_FOREVER);
589     if (result == RT_EOK)
590     {
591         level = rt_spin_lock_irqsave(&(serial->spinlock));
592         if (tx_dma->activated != RT_TRUE)
593         {
594             tx_dma->activated = RT_TRUE;
595             rt_spin_unlock_irqrestore(&(serial->spinlock), level);
596 
597             /* make a DMA transfer */
598             serial->ops->dma_transmit(serial, (rt_uint8_t *)data, length, RT_SERIAL_DMA_TX);
599         }
600         else
601         {
602             rt_spin_unlock_irqrestore(&(serial->spinlock), level);
603         }
604 
605         return length;
606     }
607     else
608     {
609         rt_set_errno(result);
610         return 0;
611     }
612 }
613 #endif /* RT_SERIAL_USING_DMA */
614 
615 /* RT-Thread Device Interface */
616 /*
617  * This function initializes serial device.
618  */
rt_serial_init(struct rt_device * dev)619 static rt_err_t rt_serial_init(struct rt_device *dev)
620 {
621     rt_err_t result = RT_EOK;
622     struct rt_serial_device *serial;
623 
624     RT_ASSERT(dev != RT_NULL);
625     serial = (struct rt_serial_device *)dev;
626 
627     /* initialize rx/tx */
628     serial->serial_rx = RT_NULL;
629     serial->serial_tx = RT_NULL;
630 
631     rt_memset(&serial->rx_notify, 0, sizeof(struct rt_device_notify));
632 
633     /* apply configuration */
634     if (serial->ops->configure)
635         result = serial->ops->configure(serial, &serial->config);
636 
637     return result;
638 }
639 
rt_serial_open(struct rt_device * dev,rt_uint16_t oflag)640 static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag)
641 {
642     rt_uint16_t stream_flag = 0;
643     struct rt_serial_device *serial;
644 
645     RT_ASSERT(dev != RT_NULL);
646     serial = (struct rt_serial_device *)dev;
647 
648     LOG_D("open serial device: 0x%08x with open flag: 0x%04x",
649         dev, oflag);
650     /* check device flag with the open flag */
651     if ((oflag & RT_DEVICE_FLAG_DMA_RX) && !(dev->flag & RT_DEVICE_FLAG_DMA_RX))
652         return -RT_EIO;
653     if ((oflag & RT_DEVICE_FLAG_DMA_TX) && !(dev->flag & RT_DEVICE_FLAG_DMA_TX))
654         return -RT_EIO;
655     if ((oflag & RT_DEVICE_FLAG_INT_RX) && !(dev->flag & RT_DEVICE_FLAG_INT_RX))
656         return -RT_EIO;
657     if ((oflag & RT_DEVICE_FLAG_INT_TX) && !(dev->flag & RT_DEVICE_FLAG_INT_TX))
658         return -RT_EIO;
659 
660     /* keep steam flag */
661     if ((oflag & RT_DEVICE_FLAG_STREAM) || (dev->open_flag & RT_DEVICE_FLAG_STREAM))
662         stream_flag = RT_DEVICE_FLAG_STREAM;
663 
664     /* get open flags */
665     dev->open_flag = oflag & 0xff;
666 
667 #ifdef RT_USING_PINCTRL
668     /* initialize iomux in DM */
669     rt_pin_ctrl_confs_apply_by_name(dev, RT_NULL);
670 #endif
671 
672     /* initialize the Rx/Tx structure according to open flag */
673     if (serial->serial_rx == RT_NULL)
674     {
675         if (oflag & RT_DEVICE_FLAG_INT_RX)
676         {
677             struct rt_serial_rx_fifo* rx_fifo;
678 
679             rx_fifo = (struct rt_serial_rx_fifo*) rt_malloc (sizeof(struct rt_serial_rx_fifo) +
680                 serial->config.bufsz);
681             RT_ASSERT(rx_fifo != RT_NULL);
682             rx_fifo->buffer = (rt_uint8_t*) (rx_fifo + 1);
683             rt_memset(rx_fifo->buffer, 0, serial->config.bufsz);
684             rx_fifo->put_index = 0;
685             rx_fifo->get_index = 0;
686             rx_fifo->is_full = RT_FALSE;
687 
688             serial->serial_rx = rx_fifo;
689             dev->open_flag |= RT_DEVICE_FLAG_INT_RX;
690             /* configure low level device */
691             serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
692         }
693 #ifdef RT_SERIAL_USING_DMA
694         else if (oflag & RT_DEVICE_FLAG_DMA_RX)
695         {
696             if (serial->config.bufsz == 0) {
697                 struct rt_serial_rx_dma* rx_dma;
698 
699                 rx_dma = (struct rt_serial_rx_dma*) rt_malloc (sizeof(struct rt_serial_rx_dma));
700                 RT_ASSERT(rx_dma != RT_NULL);
701                 rx_dma->activated = RT_FALSE;
702 
703                 serial->serial_rx = rx_dma;
704             } else {
705                 struct rt_serial_rx_fifo* rx_fifo;
706 
707                 rx_fifo = (struct rt_serial_rx_fifo*) rt_malloc (sizeof(struct rt_serial_rx_fifo) +
708                     serial->config.bufsz);
709                 RT_ASSERT(rx_fifo != RT_NULL);
710                 rx_fifo->buffer = (rt_uint8_t*) (rx_fifo + 1);
711                 rt_memset(rx_fifo->buffer, 0, serial->config.bufsz);
712                 rx_fifo->put_index = 0;
713                 rx_fifo->get_index = 0;
714                 rx_fifo->is_full = RT_FALSE;
715                 serial->serial_rx = rx_fifo;
716                 /* configure fifo address and length to low level device */
717                 serial->ops->control(serial, RT_DEVICE_CTRL_CONFIG, (void *) RT_DEVICE_FLAG_DMA_RX);
718             }
719             dev->open_flag |= RT_DEVICE_FLAG_DMA_RX;
720         }
721 #endif /* RT_SERIAL_USING_DMA */
722         else
723         {
724             serial->serial_rx = RT_NULL;
725         }
726     }
727     else
728     {
729         if (oflag & RT_DEVICE_FLAG_INT_RX)
730             dev->open_flag |= RT_DEVICE_FLAG_INT_RX;
731 #ifdef RT_SERIAL_USING_DMA
732         else if (oflag & RT_DEVICE_FLAG_DMA_RX)
733             dev->open_flag |= RT_DEVICE_FLAG_DMA_RX;
734 #endif /* RT_SERIAL_USING_DMA */
735     }
736 
737     if (serial->serial_tx == RT_NULL)
738     {
739         if (oflag & RT_DEVICE_FLAG_INT_TX)
740         {
741             struct rt_serial_tx_fifo *tx_fifo;
742 
743             tx_fifo = (struct rt_serial_tx_fifo*) rt_malloc(sizeof(struct rt_serial_tx_fifo));
744             RT_ASSERT(tx_fifo != RT_NULL);
745 
746             rt_completion_init(&(tx_fifo->completion));
747             serial->serial_tx = tx_fifo;
748 
749             dev->open_flag |= RT_DEVICE_FLAG_INT_TX;
750             /* configure low level device */
751             serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_TX);
752         }
753 #ifdef RT_SERIAL_USING_DMA
754         else if (oflag & RT_DEVICE_FLAG_DMA_TX)
755         {
756             struct rt_serial_tx_dma* tx_dma;
757 
758             tx_dma = (struct rt_serial_tx_dma*) rt_malloc (sizeof(struct rt_serial_tx_dma));
759             RT_ASSERT(tx_dma != RT_NULL);
760             tx_dma->activated = RT_FALSE;
761 
762             rt_data_queue_init(&(tx_dma->data_queue), 8, 4, RT_NULL);
763             serial->serial_tx = tx_dma;
764 
765             dev->open_flag |= RT_DEVICE_FLAG_DMA_TX;
766             /* configure low level device */
767             serial->ops->control(serial, RT_DEVICE_CTRL_CONFIG, (void *)RT_DEVICE_FLAG_DMA_TX);
768         }
769 #endif /* RT_SERIAL_USING_DMA */
770         else
771         {
772             serial->serial_tx = RT_NULL;
773         }
774     }
775     else
776     {
777         if (oflag & RT_DEVICE_FLAG_INT_TX)
778             dev->open_flag |= RT_DEVICE_FLAG_INT_TX;
779 #ifdef RT_SERIAL_USING_DMA
780         else if (oflag & RT_DEVICE_FLAG_DMA_TX)
781             dev->open_flag |= RT_DEVICE_FLAG_DMA_TX;
782 #endif /* RT_SERIAL_USING_DMA */
783     }
784 
785     /* set stream flag */
786     dev->open_flag |= stream_flag;
787 
788     return RT_EOK;
789 }
790 
rt_serial_close(struct rt_device * dev)791 static rt_err_t rt_serial_close(struct rt_device *dev)
792 {
793     struct rt_serial_device *serial;
794 
795     RT_ASSERT(dev != RT_NULL);
796     serial = (struct rt_serial_device *)dev;
797 
798     /* this device has more reference count */
799     if (dev->ref_count > 1) return RT_EOK;
800 
801     if (dev->open_flag & RT_DEVICE_FLAG_INT_RX)
802     {
803         struct rt_serial_rx_fifo* rx_fifo;
804 
805         /* configure low level device */
806         serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_RX);
807         dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX;
808 
809         rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx;
810         RT_ASSERT(rx_fifo != RT_NULL);
811 
812         rt_free(rx_fifo);
813         serial->serial_rx = RT_NULL;
814 
815     }
816 #ifdef RT_SERIAL_USING_DMA
817     else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX)
818     {
819         /* configure low level device */
820         serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *) RT_DEVICE_FLAG_DMA_RX);
821         dev->open_flag &= ~RT_DEVICE_FLAG_DMA_RX;
822 
823         if (serial->config.bufsz == 0)
824         {
825             struct rt_serial_rx_dma* rx_dma;
826 
827             rx_dma = (struct rt_serial_rx_dma*)serial->serial_rx;
828             RT_ASSERT(rx_dma != RT_NULL);
829 
830             rt_free(rx_dma);
831         }
832         else
833         {
834             struct rt_serial_rx_fifo* rx_fifo;
835 
836             rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx;
837             RT_ASSERT(rx_fifo != RT_NULL);
838 
839             rt_free(rx_fifo);
840         }
841         serial->serial_rx = RT_NULL;
842 
843     }
844 #endif /* RT_SERIAL_USING_DMA */
845 
846     if (dev->open_flag & RT_DEVICE_FLAG_INT_TX)
847     {
848         struct rt_serial_tx_fifo* tx_fifo;
849 
850         serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX);
851         dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX;
852 
853         tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_tx;
854         RT_ASSERT(tx_fifo != RT_NULL);
855 
856         rt_free(tx_fifo);
857         serial->serial_tx = RT_NULL;
858 
859         /* configure low level device */
860     }
861 #ifdef RT_SERIAL_USING_DMA
862     else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX)
863     {
864         struct rt_serial_tx_dma* tx_dma;
865 
866         /* configure low level device */
867         serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *) RT_DEVICE_FLAG_DMA_TX);
868         dev->open_flag &= ~RT_DEVICE_FLAG_DMA_TX;
869 
870         tx_dma = (struct rt_serial_tx_dma*)serial->serial_tx;
871         RT_ASSERT(tx_dma != RT_NULL);
872 
873         rt_data_queue_deinit(&(tx_dma->data_queue));
874 
875         rt_free(tx_dma);
876         serial->serial_tx = RT_NULL;
877 
878     }
879 #endif /* RT_SERIAL_USING_DMA */
880 
881     serial->ops->control(serial, RT_DEVICE_CTRL_CLOSE, RT_NULL);
882     dev->flag &= ~RT_DEVICE_FLAG_ACTIVATED;
883 
884     return RT_EOK;
885 }
886 
rt_serial_read(struct rt_device * dev,rt_off_t pos,void * buffer,rt_size_t size)887 static rt_ssize_t rt_serial_read(struct rt_device *dev,
888                                 rt_off_t          pos,
889                                 void             *buffer,
890                                 rt_size_t         size)
891 {
892     struct rt_serial_device *serial;
893 
894     RT_ASSERT(dev != RT_NULL);
895     if (size == 0) return 0;
896 
897     serial = (struct rt_serial_device *)dev;
898 
899     if (dev->open_flag & RT_DEVICE_FLAG_INT_RX)
900     {
901         return _serial_int_rx(serial, (rt_uint8_t *)buffer, size);
902     }
903 #ifdef RT_SERIAL_USING_DMA
904     else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX)
905     {
906         return _serial_dma_rx(serial, (rt_uint8_t *)buffer, size);
907     }
908 #endif /* RT_SERIAL_USING_DMA */
909 
910     return _serial_poll_rx(serial, (rt_uint8_t *)buffer, size);
911 }
912 
rt_serial_write(struct rt_device * dev,rt_off_t pos,const void * buffer,rt_size_t size)913 static rt_ssize_t rt_serial_write(struct rt_device *dev,
914                                  rt_off_t          pos,
915                                  const void       *buffer,
916                                  rt_size_t         size)
917 {
918     struct rt_serial_device *serial;
919 
920     RT_ASSERT(dev != RT_NULL);
921     if (size == 0) return 0;
922 
923     serial = (struct rt_serial_device *)dev;
924 
925     if (dev->open_flag & RT_DEVICE_FLAG_INT_TX)
926     {
927         return _serial_int_tx(serial, (const rt_uint8_t *)buffer, size);
928     }
929 #ifdef RT_SERIAL_USING_DMA
930     else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX)
931     {
932         return _serial_dma_tx(serial, (const rt_uint8_t *)buffer, size);
933     }
934 #endif /* RT_SERIAL_USING_DMA */
935     else
936     {
937         return _serial_poll_tx(serial, (const rt_uint8_t *)buffer, size);
938     }
939 }
940 
941 #if defined(RT_USING_POSIX_TERMIOS)
942 struct speed_baudrate_item
943 {
944     speed_t speed;
945     int baudrate;
946 };
947 
948 static const struct speed_baudrate_item _tbl[] =
949 {
950     {B2400, BAUD_RATE_2400},
951     {B4800, BAUD_RATE_4800},
952     {B9600, BAUD_RATE_9600},
953     {B19200, BAUD_RATE_19200},
954     {B38400, BAUD_RATE_38400},
955     {B57600, BAUD_RATE_57600},
956     {B115200, BAUD_RATE_115200},
957     {B230400, BAUD_RATE_230400},
958     {B460800, BAUD_RATE_460800},
959     {B500000, BAUD_RATE_500000},
960     {B576000, BAUD_RATE_576000},
961     {B921600, BAUD_RATE_921600},
962     {B1000000, BAUD_RATE_1000000},
963     {B1152000, BAUD_RATE_1152000},
964     {B1500000, BAUD_RATE_1500000},
965     {B2000000, BAUD_RATE_2000000},
966     {B2500000, BAUD_RATE_2500000},
967     {B3000000, BAUD_RATE_3000000},
968     {B3500000, BAUD_RATE_3500000},
969     {B4000000, BAUD_RATE_4000000},
970 };
971 
_get_speed(int baudrate)972 static speed_t _get_speed(int baudrate)
973 {
974     size_t index;
975 
976     for (index = 0; index < sizeof(_tbl)/sizeof(_tbl[0]); index ++)
977     {
978         if (_tbl[index].baudrate == baudrate)
979             return _tbl[index].speed;
980     }
981 
982     return B0;
983 }
984 
_get_baudrate(speed_t speed)985 static int _get_baudrate(speed_t speed)
986 {
987     size_t index;
988 
989     for (index = 0; index < sizeof(_tbl)/sizeof(_tbl[0]); index ++)
990     {
991         if (_tbl[index].speed == speed)
992             return _tbl[index].baudrate;
993     }
994 
995     return 0;
996 }
997 
_tc_flush(struct rt_serial_device * serial,int queue)998 static void _tc_flush(struct rt_serial_device *serial, int queue)
999 {
1000     rt_base_t level;
1001     int ch = -1;
1002     struct rt_serial_rx_fifo *rx_fifo = RT_NULL;
1003     struct rt_device *device = RT_NULL;
1004 
1005     RT_ASSERT(serial != RT_NULL);
1006 
1007     device = &(serial->parent);
1008     rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
1009 
1010     switch(queue)
1011     {
1012         case TCIFLUSH:
1013         case TCIOFLUSH:
1014 
1015             RT_ASSERT(rx_fifo != RT_NULL);
1016 
1017             if((device->open_flag & RT_DEVICE_FLAG_INT_RX) || (device->open_flag & RT_DEVICE_FLAG_DMA_RX))
1018             {
1019                 RT_ASSERT(RT_NULL != rx_fifo);
1020                 level = rt_spin_lock_irqsave(&(serial->spinlock));
1021                 rx_fifo->get_index = rx_fifo->put_index;
1022                 rx_fifo->is_full = RT_FALSE;
1023                 rt_spin_unlock_irqrestore(&(serial->spinlock), level);
1024             }
1025             else
1026             {
1027                 while (1)
1028                 {
1029                     ch = serial->ops->getc(serial);
1030                     if (ch == -1) break;
1031                 }
1032             }
1033 
1034             break;
1035 
1036          case TCOFLUSH:
1037             break;
1038     }
1039 
1040 }
1041 
_termio_to_termios(const struct termio * termio,struct termios * termios)1042 static inline int _termio_to_termios(const struct termio *termio, struct termios *termios)
1043 {
1044     termios->c_iflag = termio->c_iflag;
1045     termios->c_oflag = termio->c_oflag;
1046     termios->c_cflag = termio->c_cflag;
1047     termios->c_lflag = termio->c_lflag;
1048     termios->c_line = termio->c_line;
1049     rt_memcpy(termios->c_cc, termio->c_cc, NCC);
1050 
1051     return 0;
1052 }
1053 
_termios_to_termio(const struct termios * termios,struct termio * termio)1054 static inline int _termios_to_termio(const struct termios *termios, struct termio *termio)
1055 {
1056     termio->c_iflag = (unsigned short)termios->c_iflag;
1057     termio->c_oflag = (unsigned short)termios->c_oflag;
1058     termio->c_cflag = (unsigned short)termios->c_cflag;
1059     termio->c_lflag = (unsigned short)termios->c_lflag;
1060     termio->c_line = termios->c_line;
1061     rt_memcpy(termio->c_cc, termios->c_cc, NCC);
1062 
1063     return 0;
1064 }
1065 #endif /* RT_USING_POSIX_TERMIOS */
1066 
rt_serial_control(struct rt_device * dev,int cmd,void * args)1067 static rt_err_t rt_serial_control(struct rt_device *dev,
1068                                   int              cmd,
1069                                   void             *args)
1070 {
1071     rt_err_t ret = RT_EOK;
1072     struct rt_serial_device *serial;
1073 
1074     RT_ASSERT(dev != RT_NULL);
1075     serial = (struct rt_serial_device *)dev;
1076 
1077     switch (cmd)
1078     {
1079         case RT_DEVICE_CTRL_SUSPEND:
1080             /* suspend device */
1081             dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
1082             break;
1083 
1084         case RT_DEVICE_CTRL_RESUME:
1085             /* resume device */
1086             dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
1087             break;
1088 
1089         case RT_DEVICE_CTRL_CONFIG:
1090             if (args)
1091             {
1092                 struct serial_configure *pconfig = (struct serial_configure *) args;
1093                 if (pconfig->bufsz != serial->config.bufsz && serial->parent.ref_count)
1094                 {
1095                     /*can not change buffer size*/
1096                     return -RT_EBUSY;
1097                 }
1098                 /* set serial configure */
1099                 serial->config = *pconfig;
1100                 if (serial->parent.ref_count)
1101                 {
1102                     /* serial device has been opened, to configure it */
1103                     serial->ops->configure(serial, (struct serial_configure *) args);
1104                 }
1105             }
1106             break;
1107         case RT_DEVICE_CTRL_NOTIFY_SET:
1108             if (args)
1109             {
1110                 rt_memcpy(&serial->rx_notify, args, sizeof(struct rt_device_notify));
1111             }
1112             break;
1113 
1114         case RT_DEVICE_CTRL_CONSOLE_OFLAG:
1115             if (args)
1116             {
1117                 *(rt_uint16_t*)args = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM;
1118             }
1119             break;
1120 #ifdef RT_USING_POSIX_STDIO
1121 #if defined(RT_USING_POSIX_TERMIOS)
1122         case TCGETA:
1123         case TCGETS:
1124             {
1125                 struct termios *tio, tmp;
1126 
1127                 if (cmd == TCGETS)
1128                 {
1129                     tio = (struct termios*)args;
1130                 }
1131                 else
1132                 {
1133                     tio = &tmp;
1134                 }
1135 
1136                 if (tio == RT_NULL) return -RT_EINVAL;
1137 
1138                 tio->c_iflag = 0;
1139                 tio->c_oflag = 0;
1140                 tio->c_lflag = 0;
1141 
1142                 /* update oflag for console device */
1143                 if (rt_console_get_device() == dev)
1144                     tio->c_oflag = OPOST | ONLCR;
1145 
1146                 /* set cflag */
1147                 tio->c_cflag = 0;
1148                 if (serial->config.data_bits == DATA_BITS_5)
1149                     tio->c_cflag = CS5;
1150                 else if (serial->config.data_bits == DATA_BITS_6)
1151                     tio->c_cflag = CS6;
1152                 else if (serial->config.data_bits == DATA_BITS_7)
1153                     tio->c_cflag = CS7;
1154                 else if (serial->config.data_bits == DATA_BITS_8)
1155                     tio->c_cflag = CS8;
1156 
1157                 if (serial->config.stop_bits == STOP_BITS_2)
1158                     tio->c_cflag |= CSTOPB;
1159 
1160                 if (serial->config.parity == PARITY_EVEN)
1161                     tio->c_cflag |= PARENB;
1162                 else if (serial->config.parity == PARITY_ODD)
1163                     tio->c_cflag |= (PARODD | PARENB);
1164 
1165                 cfsetospeed(tio, _get_speed(serial->config.baud_rate));
1166 
1167                 if (cmd == TCGETA)
1168                 {
1169                     _termios_to_termio(tio, args);
1170                 }
1171             }
1172             break;
1173         case TCSETAW:
1174         case TCSETAF:
1175         case TCSETA:
1176         case TCSETSW:
1177         case TCSETSF:
1178         case TCSETS:
1179             {
1180                 int baudrate;
1181                 struct serial_configure config;
1182                 struct termios *tio, tmp;
1183 
1184                 if ((cmd >= TCSETA) && (cmd <= TCSETA + 2))
1185                 {
1186                     _termio_to_termios(args, &tmp);
1187                     tio = &tmp;
1188                 }
1189                 else
1190                 {
1191                     tio = (struct termios*)args;
1192                 }
1193 
1194                 if (tio == RT_NULL) return -RT_EINVAL;
1195 
1196                 config = serial->config;
1197                 baudrate = _get_baudrate(cfgetospeed(tio));
1198                 config.baud_rate = baudrate;
1199 
1200                 switch (tio->c_cflag & CSIZE)
1201                 {
1202                 case CS5:
1203                     config.data_bits = DATA_BITS_5;
1204                     break;
1205                 case CS6:
1206                     config.data_bits = DATA_BITS_6;
1207                     break;
1208                 case CS7:
1209                     config.data_bits = DATA_BITS_7;
1210                     break;
1211                 default:
1212                     config.data_bits = DATA_BITS_8;
1213                     break;
1214                 }
1215 
1216                 if (tio->c_cflag & CSTOPB) config.stop_bits = STOP_BITS_2;
1217                 else config.stop_bits = STOP_BITS_1;
1218 
1219                 if (tio->c_cflag & PARENB)
1220                 {
1221                     if (tio->c_cflag & PARODD) config.parity = PARITY_ODD;
1222                     else config.parity = PARITY_EVEN;
1223                 }
1224                 else config.parity = PARITY_NONE;
1225 
1226                 serial->ops->configure(serial, &config);
1227             }
1228             break;
1229 #ifndef RT_USING_TTY
1230         case TCFLSH:
1231             {
1232                 int queue = (int)(rt_ubase_t)args;
1233 
1234                 _tc_flush(serial, queue);
1235             }
1236 
1237             break;
1238         case TCXONC:
1239             break;
1240 #endif /*RT_USING_TTY*/
1241 #endif /*RT_USING_POSIX_TERMIOS*/
1242         case TIOCSWINSZ:
1243             {
1244                 struct winsize* p_winsize;
1245 
1246                 p_winsize = (struct winsize*)args;
1247                 rt_kprintf("\x1b[8;%d;%dt", p_winsize->ws_col, p_winsize->ws_row);
1248             }
1249             break;
1250         case TIOCGWINSZ:
1251             {
1252                 struct winsize* p_winsize;
1253                 p_winsize = (struct winsize*)args;
1254 
1255                 if(rt_thread_self() != rt_thread_find("tshell"))
1256                 {
1257                     /* only can be used in tshell thread; otherwise, return default size */
1258                     p_winsize->ws_col = 80;
1259                     p_winsize->ws_row = 24;
1260                 }
1261                 else
1262                 {
1263                     #include <shell.h>
1264                     #define _TIO_BUFLEN 20
1265                     char _tio_buf[_TIO_BUFLEN];
1266                     unsigned char cnt1, cnt2, cnt3, i;
1267                     char row_s[4], col_s[4];
1268                     char *p;
1269 
1270                     rt_memset(_tio_buf, 0, _TIO_BUFLEN);
1271 
1272                     /* send the command to terminal for getting the window size of the terminal */
1273                     rt_kprintf("\033[18t");
1274 
1275                     /* waiting for the response from the terminal */
1276                     i = 0;
1277                     while(i < _TIO_BUFLEN)
1278                     {
1279                         _tio_buf[i] = finsh_getchar();
1280                         if(_tio_buf[i] != 't')
1281                         {
1282                             i ++;
1283                         }
1284                         else
1285                         {
1286                             break;
1287                         }
1288                     }
1289                     if(i == _TIO_BUFLEN)
1290                     {
1291                         /* buffer overloaded, and return default size */
1292                         p_winsize->ws_col = 80;
1293                         p_winsize->ws_row = 24;
1294                         break;
1295                     }
1296 
1297                     /* interpreting data eg: "\033[8;1;15t" which means row is 1 and col is 15 (unit: size of ONE character) */
1298                     rt_memset(row_s,0,4);
1299                     rt_memset(col_s,0,4);
1300                     cnt1 = 0;
1301                     while(cnt1 < _TIO_BUFLEN && _tio_buf[cnt1] != ';')
1302                     {
1303                         cnt1++;
1304                     }
1305                     cnt2 = ++cnt1;
1306                     while(cnt2 < _TIO_BUFLEN && _tio_buf[cnt2] != ';')
1307                     {
1308                         cnt2++;
1309                     }
1310                     p = row_s;
1311                     while(cnt1 < cnt2)
1312                     {
1313                         *p++ = _tio_buf[cnt1++];
1314                     }
1315                     p = col_s;
1316                     cnt2++;
1317                     cnt3 = rt_strlen(_tio_buf) - 1;
1318                     while(cnt2 < cnt3)
1319                     {
1320                         *p++ = _tio_buf[cnt2++];
1321                     }
1322 
1323                     /* load the window size date */
1324                     p_winsize->ws_col = atoi(col_s);
1325                     p_winsize->ws_row = atoi(row_s);
1326                 #undef _TIO_BUFLEN
1327                 }
1328 
1329                 p_winsize->ws_xpixel = 0;/* unused */
1330                 p_winsize->ws_ypixel = 0;/* unused */
1331             }
1332             break;
1333         case FIONREAD:
1334             {
1335                 rt_size_t recved = 0;
1336                 rt_base_t level;
1337 
1338                 level = rt_spin_lock_irqsave(&(serial->spinlock));
1339                 recved = _serial_fifo_calc_recved_len(serial);
1340                 rt_spin_unlock_irqrestore(&(serial->spinlock), level);
1341 
1342                 *(rt_size_t *)args = recved;
1343             }
1344             break;
1345 #endif /* RT_USING_POSIX_STDIO */
1346         default :
1347             /* control device */
1348             ret = serial->ops->control(serial, cmd, args);
1349             break;
1350     }
1351 
1352     return ret;
1353 }
1354 
1355 #ifdef RT_USING_DEVICE_OPS
1356 const static struct rt_device_ops serial_ops =
1357 {
1358     rt_serial_init,
1359     rt_serial_open,
1360     rt_serial_close,
1361     rt_serial_read,
1362     rt_serial_write,
1363     rt_serial_control
1364 };
1365 #endif
1366 
1367 /*
1368  * serial register
1369  */
rt_hw_serial_register(struct rt_serial_device * serial,const char * name,rt_uint32_t flag,void * data)1370 rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
1371                                const char              *name,
1372                                rt_uint32_t              flag,
1373                                void                    *data)
1374 {
1375     rt_err_t ret;
1376     struct rt_device *device;
1377     RT_ASSERT(serial != RT_NULL);
1378 
1379     rt_spin_lock_init(&(serial->spinlock));
1380 
1381     device = &(serial->parent);
1382 
1383     device->type        = RT_Device_Class_Char;
1384     device->rx_indicate = RT_NULL;
1385     device->tx_complete = RT_NULL;
1386 
1387 #ifdef RT_USING_DEVICE_OPS
1388     device->ops         = &serial_ops;
1389 #else
1390     device->init        = rt_serial_init;
1391     device->open        = rt_serial_open;
1392     device->close       = rt_serial_close;
1393     device->read        = rt_serial_read;
1394     device->write       = rt_serial_write;
1395     device->control     = rt_serial_control;
1396 #endif
1397     device->user_data   = data;
1398 
1399     /* register a character device */
1400     ret = rt_device_register(device, name, flag);
1401 
1402 #ifdef RT_USING_POSIX_STDIO
1403     /* set fops */
1404     device->fops        = &_serial_fops;
1405 #endif
1406 
1407 #if defined(RT_USING_SMART)
1408     rt_hw_serial_register_tty(serial);
1409 #endif
1410 
1411     return ret;
1412 }
1413 
1414 /* ISR for serial interrupt */
rt_hw_serial_isr(struct rt_serial_device * serial,int event)1415 void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
1416 {
1417     switch (event & 0xff)
1418     {
1419         case RT_SERIAL_EVENT_RX_IND:
1420         {
1421             int ch = -1;
1422             rt_base_t level;
1423             struct rt_serial_rx_fifo* rx_fifo;
1424 
1425             /* interrupt mode receive */
1426             rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx;
1427             RT_ASSERT(rx_fifo != RT_NULL);
1428 
1429             while (1)
1430             {
1431                 ch = serial->ops->getc(serial);
1432                 if (ch == -1) break;
1433 
1434                 /* disable interrupt */
1435 #ifdef RT_USING_SERIAL_BYPASS
1436                 if (serial->bypass && serial->bypass->upper_h && (serial->bypass->upper_h->head.next != &serial->bypass->upper_h->head))
1437                 {
1438                     rt_bool_t skip = RT_FALSE;
1439                     char buf = (char)ch;
1440                     int ret;
1441                     rt_list_t* node = serial->bypass->upper_h->head.next;
1442                     do {
1443                         struct rt_serial_bypass_func* bypass_run = rt_container_of(node, struct rt_serial_bypass_func, node);
1444                         ret = bypass_run->bypass(serial, buf, bypass_run->data);
1445                         if (!ret)
1446                         {
1447                             skip = RT_TRUE;
1448                             break;
1449                         }
1450                         node = node->next;
1451                     } while (node != &serial->bypass->upper_h->head);
1452 
1453                     if (skip)
1454                         continue;
1455                 }
1456 
1457 #endif
1458                 level = rt_spin_lock_irqsave(&(serial->spinlock));
1459                 rx_fifo->buffer[rx_fifo->put_index] = ch;
1460                 rx_fifo->put_index += 1;
1461                 if (rx_fifo->put_index >= serial->config.bufsz) rx_fifo->put_index = 0;
1462 
1463                 /* if the next position is read index, discard this 'read char' */
1464                 if (rx_fifo->put_index == rx_fifo->get_index)
1465                 {
1466                     rx_fifo->get_index = rx_fifo->put_index;
1467                     rx_fifo->is_full = RT_TRUE;
1468 
1469                     _serial_check_buffer_size();
1470                 }
1471 
1472                 /* enable interrupt */
1473                 rt_spin_unlock_irqrestore(&(serial->spinlock), level);
1474             }
1475 
1476 #ifdef RT_USING_SERIAL_BYPASS
1477             if (serial->bypass && serial->bypass->lower_h)
1478                 rt_workqueue_dowork(serial->bypass->lower_workq, &serial->bypass->work);
1479 #endif
1480 
1481             if (serial->parent.rx_indicate != RT_NULL)
1482             {
1483                 rt_size_t rx_length;
1484 
1485                 /* get rx length */
1486                 level = rt_spin_lock_irqsave(&(serial->spinlock));
1487                 rx_length = (rx_fifo->put_index >= rx_fifo->get_index)? (rx_fifo->put_index - rx_fifo->get_index):
1488                     (serial->config.bufsz - (rx_fifo->get_index - rx_fifo->put_index));
1489                 rt_spin_unlock_irqrestore(&(serial->spinlock), level);
1490 
1491                 if (rx_length)
1492                 {
1493                     serial->parent.rx_indicate(&serial->parent, rx_length);
1494                 }
1495             }
1496             break;
1497         }
1498         case RT_SERIAL_EVENT_TX_DONE:
1499         {
1500             struct rt_serial_tx_fifo* tx_fifo;
1501 
1502             tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_tx;
1503             rt_completion_done(&(tx_fifo->completion));
1504             break;
1505         }
1506 #ifdef RT_SERIAL_USING_DMA
1507         case RT_SERIAL_EVENT_TX_DMADONE:
1508         {
1509             const void *data_ptr;
1510             rt_size_t data_size;
1511             const void *last_data_ptr;
1512             struct rt_serial_tx_dma *tx_dma;
1513 
1514             tx_dma = (struct rt_serial_tx_dma*) serial->serial_tx;
1515 
1516             rt_data_queue_pop(&(tx_dma->data_queue), &last_data_ptr, &data_size, 0);
1517             if (rt_data_queue_peek(&(tx_dma->data_queue), &data_ptr, &data_size) == RT_EOK)
1518             {
1519                 /* transmit next data node */
1520                 tx_dma->activated = RT_TRUE;
1521                 serial->ops->dma_transmit(serial, (rt_uint8_t *)data_ptr, data_size, RT_SERIAL_DMA_TX);
1522             }
1523             else
1524             {
1525                 tx_dma->activated = RT_FALSE;
1526             }
1527 
1528             /* invoke callback */
1529             if (serial->parent.tx_complete != RT_NULL)
1530             {
1531                 serial->parent.tx_complete(&serial->parent, (void*)last_data_ptr);
1532             }
1533             break;
1534         }
1535         case RT_SERIAL_EVENT_RX_DMADONE:
1536         {
1537             int length;
1538             rt_base_t level;
1539 
1540             /* get DMA rx length */
1541             length = (event & (~0xff)) >> 8;
1542 
1543             if (serial->config.bufsz == 0)
1544             {
1545                 struct rt_serial_rx_dma* rx_dma;
1546 
1547                 rx_dma = (struct rt_serial_rx_dma*) serial->serial_rx;
1548                 RT_ASSERT(rx_dma != RT_NULL);
1549 
1550                 RT_ASSERT(serial->parent.rx_indicate != RT_NULL);
1551                 serial->parent.rx_indicate(&(serial->parent), length);
1552                 rx_dma->activated = RT_FALSE;
1553             }
1554             else
1555             {
1556                 /* disable interrupt */
1557                 level = rt_spin_lock_irqsave(&(serial->spinlock));
1558                 /* update fifo put index */
1559                 rt_dma_recv_update_put_index(serial, length);
1560                 /* calculate received total length */
1561                 length = rt_dma_calc_recved_len(serial);
1562                 /* enable interrupt */
1563                 rt_spin_unlock_irqrestore(&(serial->spinlock), level);
1564                 /* invoke callback */
1565                 if (serial->parent.rx_indicate != RT_NULL)
1566                 {
1567                     serial->parent.rx_indicate(&(serial->parent), length);
1568                 }
1569             }
1570             break;
1571         }
1572 #endif /* RT_SERIAL_USING_DMA */
1573     }
1574 }
1575