xref: /nrf52832-nimble/rt-thread/components/drivers/serial/serial.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero  * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero  *
4*10465441SEvalZero  * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero  *
6*10465441SEvalZero  * Change Logs:
7*10465441SEvalZero  * Date           Author       Notes
8*10465441SEvalZero  * 2006-03-13     bernard      first version
9*10465441SEvalZero  * 2012-05-15     lgnq         modified according bernard's implementation.
10*10465441SEvalZero  * 2012-05-28     bernard      code cleanup
11*10465441SEvalZero  * 2012-11-23     bernard      fix compiler warning.
12*10465441SEvalZero  * 2013-02-20     bernard      use RT_SERIAL_RB_BUFSZ to define
13*10465441SEvalZero  *                             the size of ring buffer.
14*10465441SEvalZero  * 2014-07-10     bernard      rewrite serial framework
15*10465441SEvalZero  * 2014-12-31     bernard      use open_flag for poll_tx stream mode.
16*10465441SEvalZero  * 2015-05-19     Quintin      fix DMA tx mod tx_dma->activated flag !=RT_FALSE BUG
17*10465441SEvalZero  *                             in open function.
18*10465441SEvalZero  * 2015-11-10     bernard      fix the poll rx issue when there is no data.
19*10465441SEvalZero  * 2016-05-10     armink       add fifo mode to DMA rx when serial->config.bufsz != 0.
20*10465441SEvalZero  * 2017-01-19     aubr.cool    prevent change serial rx bufsz when serial is opened.
21*10465441SEvalZero  * 2017-11-07     JasonJia     fix data bits error issue when using tcsetattr.
22*10465441SEvalZero  * 2017-11-15     JasonJia     fix poll rx issue when data is full.
23*10465441SEvalZero  *                             add TCFLSH and FIONREAD support.
24*10465441SEvalZero  * 2018-12-08     Ernest Chen  add DMA choice
25*10465441SEvalZero  */
26*10465441SEvalZero 
27*10465441SEvalZero #include <rthw.h>
28*10465441SEvalZero #include <rtthread.h>
29*10465441SEvalZero #include <rtdevice.h>
30*10465441SEvalZero 
31*10465441SEvalZero // #define DEBUG_ENABLE
32*10465441SEvalZero #define DEBUG_LEVEL         DBG_LOG
33*10465441SEvalZero #define DBG_SECTION_NAME    "UART"
34*10465441SEvalZero #define DEBUG_COLOR
35*10465441SEvalZero #include <rtdbg.h>
36*10465441SEvalZero 
37*10465441SEvalZero #ifdef RT_USING_POSIX
38*10465441SEvalZero #include <dfs_posix.h>
39*10465441SEvalZero #include <dfs_poll.h>
40*10465441SEvalZero 
41*10465441SEvalZero #ifdef RT_USING_POSIX_TERMIOS
42*10465441SEvalZero #include <posix_termios.h>
43*10465441SEvalZero #endif
44*10465441SEvalZero 
45*10465441SEvalZero /* it's possible the 'getc/putc' is defined by stdio.h in gcc/newlib. */
46*10465441SEvalZero #ifdef getc
47*10465441SEvalZero #undef getc
48*10465441SEvalZero #endif
49*10465441SEvalZero 
50*10465441SEvalZero #ifdef putc
51*10465441SEvalZero #undef putc
52*10465441SEvalZero #endif
53*10465441SEvalZero 
serial_fops_rx_ind(rt_device_t dev,rt_size_t size)54*10465441SEvalZero static rt_err_t serial_fops_rx_ind(rt_device_t dev, rt_size_t size)
55*10465441SEvalZero {
56*10465441SEvalZero     rt_wqueue_wakeup(&(dev->wait_queue), (void*)POLLIN);
57*10465441SEvalZero 
58*10465441SEvalZero     return RT_EOK;
59*10465441SEvalZero }
60*10465441SEvalZero 
61*10465441SEvalZero /* fops for serial */
serial_fops_open(struct dfs_fd * fd)62*10465441SEvalZero static int serial_fops_open(struct dfs_fd *fd)
63*10465441SEvalZero {
64*10465441SEvalZero     rt_err_t ret = 0;
65*10465441SEvalZero     rt_uint16_t flags = 0;
66*10465441SEvalZero     rt_device_t device;
67*10465441SEvalZero 
68*10465441SEvalZero     device = (rt_device_t)fd->data;
69*10465441SEvalZero     RT_ASSERT(device != RT_NULL);
70*10465441SEvalZero 
71*10465441SEvalZero     switch (fd->flags & O_ACCMODE)
72*10465441SEvalZero     {
73*10465441SEvalZero     case O_RDONLY:
74*10465441SEvalZero         LOG_D("fops open: O_RDONLY!");
75*10465441SEvalZero         flags = RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_RDONLY;
76*10465441SEvalZero         break;
77*10465441SEvalZero     case O_WRONLY:
78*10465441SEvalZero         LOG_D("fops open: O_WRONLY!");
79*10465441SEvalZero         flags = RT_DEVICE_FLAG_WRONLY;
80*10465441SEvalZero         break;
81*10465441SEvalZero     case O_RDWR:
82*10465441SEvalZero         LOG_D("fops open: O_RDWR!");
83*10465441SEvalZero         flags = RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_RDWR;
84*10465441SEvalZero         break;
85*10465441SEvalZero     default:
86*10465441SEvalZero         LOG_E("fops open: unknown mode - %d!", fd->flags & O_ACCMODE);
87*10465441SEvalZero         break;
88*10465441SEvalZero     }
89*10465441SEvalZero 
90*10465441SEvalZero     if ((fd->flags & O_ACCMODE) != O_WRONLY)
91*10465441SEvalZero         rt_device_set_rx_indicate(device, serial_fops_rx_ind);
92*10465441SEvalZero     ret = rt_device_open(device, flags);
93*10465441SEvalZero     if (ret == RT_EOK) return 0;
94*10465441SEvalZero 
95*10465441SEvalZero     return ret;
96*10465441SEvalZero }
97*10465441SEvalZero 
serial_fops_close(struct dfs_fd * fd)98*10465441SEvalZero static int serial_fops_close(struct dfs_fd *fd)
99*10465441SEvalZero {
100*10465441SEvalZero     rt_device_t device;
101*10465441SEvalZero 
102*10465441SEvalZero     device = (rt_device_t)fd->data;
103*10465441SEvalZero 
104*10465441SEvalZero     rt_device_set_rx_indicate(device, RT_NULL);
105*10465441SEvalZero     rt_device_close(device);
106*10465441SEvalZero 
107*10465441SEvalZero     return 0;
108*10465441SEvalZero }
109*10465441SEvalZero 
serial_fops_ioctl(struct dfs_fd * fd,int cmd,void * args)110*10465441SEvalZero static int serial_fops_ioctl(struct dfs_fd *fd, int cmd, void *args)
111*10465441SEvalZero {
112*10465441SEvalZero     rt_device_t device;
113*10465441SEvalZero 
114*10465441SEvalZero     device = (rt_device_t)fd->data;
115*10465441SEvalZero     switch (cmd)
116*10465441SEvalZero     {
117*10465441SEvalZero     case FIONREAD:
118*10465441SEvalZero         break;
119*10465441SEvalZero     case FIONWRITE:
120*10465441SEvalZero         break;
121*10465441SEvalZero     }
122*10465441SEvalZero 
123*10465441SEvalZero     return rt_device_control(device, cmd, args);
124*10465441SEvalZero }
125*10465441SEvalZero 
serial_fops_read(struct dfs_fd * fd,void * buf,size_t count)126*10465441SEvalZero static int serial_fops_read(struct dfs_fd *fd, void *buf, size_t count)
127*10465441SEvalZero {
128*10465441SEvalZero     int size = 0;
129*10465441SEvalZero     rt_device_t device;
130*10465441SEvalZero 
131*10465441SEvalZero     device = (rt_device_t)fd->data;
132*10465441SEvalZero 
133*10465441SEvalZero     do
134*10465441SEvalZero     {
135*10465441SEvalZero         size = rt_device_read(device, -1,  buf, count);
136*10465441SEvalZero         if (size <= 0)
137*10465441SEvalZero         {
138*10465441SEvalZero             if (fd->flags & O_NONBLOCK)
139*10465441SEvalZero             {
140*10465441SEvalZero                 size = -EAGAIN;
141*10465441SEvalZero                 break;
142*10465441SEvalZero             }
143*10465441SEvalZero 
144*10465441SEvalZero             rt_wqueue_wait(&(device->wait_queue), 0, RT_WAITING_FOREVER);
145*10465441SEvalZero         }
146*10465441SEvalZero     }while (size <= 0);
147*10465441SEvalZero 
148*10465441SEvalZero     return size;
149*10465441SEvalZero }
150*10465441SEvalZero 
serial_fops_write(struct dfs_fd * fd,const void * buf,size_t count)151*10465441SEvalZero static int serial_fops_write(struct dfs_fd *fd, const void *buf, size_t count)
152*10465441SEvalZero {
153*10465441SEvalZero     rt_device_t device;
154*10465441SEvalZero 
155*10465441SEvalZero     device = (rt_device_t)fd->data;
156*10465441SEvalZero     return rt_device_write(device, -1, buf, count);
157*10465441SEvalZero }
158*10465441SEvalZero 
serial_fops_poll(struct dfs_fd * fd,struct rt_pollreq * req)159*10465441SEvalZero static int serial_fops_poll(struct dfs_fd *fd, struct rt_pollreq *req)
160*10465441SEvalZero {
161*10465441SEvalZero     int mask = 0;
162*10465441SEvalZero     int flags = 0;
163*10465441SEvalZero     rt_device_t device;
164*10465441SEvalZero     struct rt_serial_device *serial;
165*10465441SEvalZero 
166*10465441SEvalZero     device = (rt_device_t)fd->data;
167*10465441SEvalZero     RT_ASSERT(device != RT_NULL);
168*10465441SEvalZero 
169*10465441SEvalZero     serial = (struct rt_serial_device *)device;
170*10465441SEvalZero 
171*10465441SEvalZero     /* only support POLLIN */
172*10465441SEvalZero     flags = fd->flags & O_ACCMODE;
173*10465441SEvalZero     if (flags == O_RDONLY || flags == O_RDWR)
174*10465441SEvalZero     {
175*10465441SEvalZero         rt_base_t level;
176*10465441SEvalZero         struct rt_serial_rx_fifo* rx_fifo;
177*10465441SEvalZero 
178*10465441SEvalZero         rt_poll_add(&(device->wait_queue), req);
179*10465441SEvalZero 
180*10465441SEvalZero         rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx;
181*10465441SEvalZero 
182*10465441SEvalZero         level = rt_hw_interrupt_disable();
183*10465441SEvalZero         if ((rx_fifo->get_index != rx_fifo->put_index) || (rx_fifo->get_index == rx_fifo->put_index && rx_fifo->is_full == RT_TRUE))
184*10465441SEvalZero             mask |= POLLIN;
185*10465441SEvalZero         rt_hw_interrupt_enable(level);
186*10465441SEvalZero     }
187*10465441SEvalZero 
188*10465441SEvalZero     return mask;
189*10465441SEvalZero }
190*10465441SEvalZero 
191*10465441SEvalZero const static struct dfs_file_ops _serial_fops =
192*10465441SEvalZero {
193*10465441SEvalZero     serial_fops_open,
194*10465441SEvalZero     serial_fops_close,
195*10465441SEvalZero     serial_fops_ioctl,
196*10465441SEvalZero     serial_fops_read,
197*10465441SEvalZero     serial_fops_write,
198*10465441SEvalZero     RT_NULL, /* flush */
199*10465441SEvalZero     RT_NULL, /* lseek */
200*10465441SEvalZero     RT_NULL, /* getdents */
201*10465441SEvalZero     serial_fops_poll,
202*10465441SEvalZero };
203*10465441SEvalZero #endif
204*10465441SEvalZero 
205*10465441SEvalZero /*
206*10465441SEvalZero  * Serial poll routines
207*10465441SEvalZero  */
_serial_poll_rx(struct rt_serial_device * serial,rt_uint8_t * data,int length)208*10465441SEvalZero rt_inline int _serial_poll_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
209*10465441SEvalZero {
210*10465441SEvalZero     int ch;
211*10465441SEvalZero     int size;
212*10465441SEvalZero 
213*10465441SEvalZero     RT_ASSERT(serial != RT_NULL);
214*10465441SEvalZero     size = length;
215*10465441SEvalZero 
216*10465441SEvalZero     while (length)
217*10465441SEvalZero     {
218*10465441SEvalZero         ch = serial->ops->getc(serial);
219*10465441SEvalZero         if (ch == -1) break;
220*10465441SEvalZero 
221*10465441SEvalZero         *data = ch;
222*10465441SEvalZero         data ++; length --;
223*10465441SEvalZero 
224*10465441SEvalZero         if (ch == '\n') break;
225*10465441SEvalZero     }
226*10465441SEvalZero 
227*10465441SEvalZero     return size - length;
228*10465441SEvalZero }
229*10465441SEvalZero 
_serial_poll_tx(struct rt_serial_device * serial,const rt_uint8_t * data,int length)230*10465441SEvalZero rt_inline int _serial_poll_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
231*10465441SEvalZero {
232*10465441SEvalZero     int size;
233*10465441SEvalZero     RT_ASSERT(serial != RT_NULL);
234*10465441SEvalZero 
235*10465441SEvalZero     size = length;
236*10465441SEvalZero     while (length)
237*10465441SEvalZero     {
238*10465441SEvalZero         /*
239*10465441SEvalZero          * to be polite with serial console add a line feed
240*10465441SEvalZero          * to the carriage return character
241*10465441SEvalZero          */
242*10465441SEvalZero         if (*data == '\n' && (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM))
243*10465441SEvalZero         {
244*10465441SEvalZero             serial->ops->putc(serial, '\r');
245*10465441SEvalZero         }
246*10465441SEvalZero 
247*10465441SEvalZero         serial->ops->putc(serial, *data);
248*10465441SEvalZero 
249*10465441SEvalZero         ++ data;
250*10465441SEvalZero         -- length;
251*10465441SEvalZero     }
252*10465441SEvalZero 
253*10465441SEvalZero     return size - length;
254*10465441SEvalZero }
255*10465441SEvalZero 
256*10465441SEvalZero /*
257*10465441SEvalZero  * Serial interrupt routines
258*10465441SEvalZero  */
_serial_int_rx(struct rt_serial_device * serial,rt_uint8_t * data,int length)259*10465441SEvalZero rt_inline int _serial_int_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
260*10465441SEvalZero {
261*10465441SEvalZero     int size;
262*10465441SEvalZero     struct rt_serial_rx_fifo* rx_fifo;
263*10465441SEvalZero 
264*10465441SEvalZero     RT_ASSERT(serial != RT_NULL);
265*10465441SEvalZero     size = length;
266*10465441SEvalZero 
267*10465441SEvalZero     rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx;
268*10465441SEvalZero     RT_ASSERT(rx_fifo != RT_NULL);
269*10465441SEvalZero 
270*10465441SEvalZero     /* read from software FIFO */
271*10465441SEvalZero     while (length)
272*10465441SEvalZero     {
273*10465441SEvalZero         int ch;
274*10465441SEvalZero         rt_base_t level;
275*10465441SEvalZero 
276*10465441SEvalZero         /* disable interrupt */
277*10465441SEvalZero         level = rt_hw_interrupt_disable();
278*10465441SEvalZero 
279*10465441SEvalZero         /* there's no data: */
280*10465441SEvalZero         if ((rx_fifo->get_index == rx_fifo->put_index) && (rx_fifo->is_full == RT_FALSE))
281*10465441SEvalZero         {
282*10465441SEvalZero             /* no data, enable interrupt and break out */
283*10465441SEvalZero             rt_hw_interrupt_enable(level);
284*10465441SEvalZero             break;
285*10465441SEvalZero         }
286*10465441SEvalZero 
287*10465441SEvalZero         /* otherwise there's the data: */
288*10465441SEvalZero         ch = rx_fifo->buffer[rx_fifo->get_index];
289*10465441SEvalZero         rx_fifo->get_index += 1;
290*10465441SEvalZero         if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0;
291*10465441SEvalZero 
292*10465441SEvalZero         if (rx_fifo->is_full == RT_TRUE)
293*10465441SEvalZero         {
294*10465441SEvalZero             rx_fifo->is_full = RT_FALSE;
295*10465441SEvalZero         }
296*10465441SEvalZero 
297*10465441SEvalZero         /* enable interrupt */
298*10465441SEvalZero         rt_hw_interrupt_enable(level);
299*10465441SEvalZero 
300*10465441SEvalZero         *data = ch & 0xff;
301*10465441SEvalZero         data ++; length --;
302*10465441SEvalZero     }
303*10465441SEvalZero 
304*10465441SEvalZero     return size - length;
305*10465441SEvalZero }
306*10465441SEvalZero 
_serial_int_tx(struct rt_serial_device * serial,const rt_uint8_t * data,int length)307*10465441SEvalZero rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
308*10465441SEvalZero {
309*10465441SEvalZero     int size;
310*10465441SEvalZero     struct rt_serial_tx_fifo *tx;
311*10465441SEvalZero 
312*10465441SEvalZero     RT_ASSERT(serial != RT_NULL);
313*10465441SEvalZero 
314*10465441SEvalZero     size = length;
315*10465441SEvalZero     tx = (struct rt_serial_tx_fifo*) serial->serial_tx;
316*10465441SEvalZero     RT_ASSERT(tx != RT_NULL);
317*10465441SEvalZero 
318*10465441SEvalZero     while (length)
319*10465441SEvalZero     {
320*10465441SEvalZero         if (serial->ops->putc(serial, *(char*)data) == -1)
321*10465441SEvalZero         {
322*10465441SEvalZero             rt_completion_wait(&(tx->completion), RT_WAITING_FOREVER);
323*10465441SEvalZero             continue;
324*10465441SEvalZero         }
325*10465441SEvalZero 
326*10465441SEvalZero         data ++; length --;
327*10465441SEvalZero     }
328*10465441SEvalZero 
329*10465441SEvalZero     return size - length;
330*10465441SEvalZero }
331*10465441SEvalZero 
332*10465441SEvalZero #if defined(RT_USING_POSIX) || defined(RT_SERIAL_USING_DMA)
_serial_fifo_calc_recved_len(struct rt_serial_device * serial)333*10465441SEvalZero static rt_size_t _serial_fifo_calc_recved_len(struct rt_serial_device *serial)
334*10465441SEvalZero {
335*10465441SEvalZero     struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
336*10465441SEvalZero 
337*10465441SEvalZero     RT_ASSERT(rx_fifo != RT_NULL);
338*10465441SEvalZero 
339*10465441SEvalZero     if (rx_fifo->put_index == rx_fifo->get_index)
340*10465441SEvalZero     {
341*10465441SEvalZero         return (rx_fifo->is_full == RT_FALSE ? 0 : serial->config.bufsz);
342*10465441SEvalZero     }
343*10465441SEvalZero     else
344*10465441SEvalZero     {
345*10465441SEvalZero         if (rx_fifo->put_index > rx_fifo->get_index)
346*10465441SEvalZero         {
347*10465441SEvalZero             return rx_fifo->put_index - rx_fifo->get_index;
348*10465441SEvalZero         }
349*10465441SEvalZero         else
350*10465441SEvalZero         {
351*10465441SEvalZero             return serial->config.bufsz - (rx_fifo->get_index - rx_fifo->put_index);
352*10465441SEvalZero         }
353*10465441SEvalZero     }
354*10465441SEvalZero }
355*10465441SEvalZero #endif /* RT_USING_POSIX || RT_SERIAL_USING_DMA */
356*10465441SEvalZero 
357*10465441SEvalZero #ifdef RT_SERIAL_USING_DMA
358*10465441SEvalZero /**
359*10465441SEvalZero  * Calculate DMA received data length.
360*10465441SEvalZero  *
361*10465441SEvalZero  * @param serial serial device
362*10465441SEvalZero  *
363*10465441SEvalZero  * @return length
364*10465441SEvalZero  */
rt_dma_calc_recved_len(struct rt_serial_device * serial)365*10465441SEvalZero static rt_size_t rt_dma_calc_recved_len(struct rt_serial_device *serial)
366*10465441SEvalZero {
367*10465441SEvalZero     return _serial_fifo_calc_recved_len(serial);
368*10465441SEvalZero }
369*10465441SEvalZero 
370*10465441SEvalZero /**
371*10465441SEvalZero  * Read data finish by DMA mode then update the get index for receive fifo.
372*10465441SEvalZero  *
373*10465441SEvalZero  * @param serial serial device
374*10465441SEvalZero  * @param len get data length for this operate
375*10465441SEvalZero  */
rt_dma_recv_update_get_index(struct rt_serial_device * serial,rt_size_t len)376*10465441SEvalZero static void rt_dma_recv_update_get_index(struct rt_serial_device *serial, rt_size_t len)
377*10465441SEvalZero {
378*10465441SEvalZero     struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
379*10465441SEvalZero 
380*10465441SEvalZero     RT_ASSERT(rx_fifo != RT_NULL);
381*10465441SEvalZero     RT_ASSERT(len <= rt_dma_calc_recved_len(serial));
382*10465441SEvalZero 
383*10465441SEvalZero     if (rx_fifo->is_full && len != 0) rx_fifo->is_full = RT_FALSE;
384*10465441SEvalZero 
385*10465441SEvalZero     rx_fifo->get_index += len;
386*10465441SEvalZero     if (rx_fifo->get_index >= serial->config.bufsz)
387*10465441SEvalZero     {
388*10465441SEvalZero         rx_fifo->get_index %= serial->config.bufsz;
389*10465441SEvalZero     }
390*10465441SEvalZero }
391*10465441SEvalZero 
392*10465441SEvalZero /**
393*10465441SEvalZero  * DMA received finish then update put index for receive fifo.
394*10465441SEvalZero  *
395*10465441SEvalZero  * @param serial serial device
396*10465441SEvalZero  * @param len received length for this transmit
397*10465441SEvalZero  */
rt_dma_recv_update_put_index(struct rt_serial_device * serial,rt_size_t len)398*10465441SEvalZero static void rt_dma_recv_update_put_index(struct rt_serial_device *serial, rt_size_t len)
399*10465441SEvalZero {
400*10465441SEvalZero     struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
401*10465441SEvalZero 
402*10465441SEvalZero     RT_ASSERT(rx_fifo != RT_NULL);
403*10465441SEvalZero 
404*10465441SEvalZero     if (rx_fifo->get_index <= rx_fifo->put_index)
405*10465441SEvalZero     {
406*10465441SEvalZero         rx_fifo->put_index += len;
407*10465441SEvalZero         /* beyond the fifo end */
408*10465441SEvalZero         if (rx_fifo->put_index >= serial->config.bufsz)
409*10465441SEvalZero         {
410*10465441SEvalZero             rx_fifo->put_index %= serial->config.bufsz;
411*10465441SEvalZero             /* force overwrite get index */
412*10465441SEvalZero             if (rx_fifo->put_index >= rx_fifo->get_index)
413*10465441SEvalZero             {
414*10465441SEvalZero                 rx_fifo->is_full = RT_TRUE;
415*10465441SEvalZero             }
416*10465441SEvalZero         }
417*10465441SEvalZero     }
418*10465441SEvalZero     else
419*10465441SEvalZero     {
420*10465441SEvalZero         rx_fifo->put_index += len;
421*10465441SEvalZero         if (rx_fifo->put_index >= rx_fifo->get_index)
422*10465441SEvalZero         {
423*10465441SEvalZero             /* beyond the fifo end */
424*10465441SEvalZero             if (rx_fifo->put_index >= serial->config.bufsz)
425*10465441SEvalZero             {
426*10465441SEvalZero                 rx_fifo->put_index %= serial->config.bufsz;
427*10465441SEvalZero             }
428*10465441SEvalZero             /* force overwrite get index */
429*10465441SEvalZero             rx_fifo->is_full = RT_TRUE;
430*10465441SEvalZero         }
431*10465441SEvalZero     }
432*10465441SEvalZero 
433*10465441SEvalZero     if(rx_fifo->is_full == RT_TRUE)
434*10465441SEvalZero     {
435*10465441SEvalZero         rx_fifo->get_index = rx_fifo->put_index;
436*10465441SEvalZero     }
437*10465441SEvalZero 
438*10465441SEvalZero     if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0;
439*10465441SEvalZero }
440*10465441SEvalZero 
441*10465441SEvalZero /*
442*10465441SEvalZero  * Serial DMA routines
443*10465441SEvalZero  */
_serial_dma_rx(struct rt_serial_device * serial,rt_uint8_t * data,int length)444*10465441SEvalZero rt_inline int _serial_dma_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length)
445*10465441SEvalZero {
446*10465441SEvalZero     rt_base_t level;
447*10465441SEvalZero 
448*10465441SEvalZero     RT_ASSERT((serial != RT_NULL) && (data != RT_NULL));
449*10465441SEvalZero 
450*10465441SEvalZero     level = rt_hw_interrupt_disable();
451*10465441SEvalZero 
452*10465441SEvalZero     if (serial->config.bufsz == 0)
453*10465441SEvalZero     {
454*10465441SEvalZero         int result = RT_EOK;
455*10465441SEvalZero         struct rt_serial_rx_dma *rx_dma;
456*10465441SEvalZero 
457*10465441SEvalZero         rx_dma = (struct rt_serial_rx_dma*)serial->serial_rx;
458*10465441SEvalZero         RT_ASSERT(rx_dma != RT_NULL);
459*10465441SEvalZero 
460*10465441SEvalZero         if (rx_dma->activated != RT_TRUE)
461*10465441SEvalZero         {
462*10465441SEvalZero             rx_dma->activated = RT_TRUE;
463*10465441SEvalZero             RT_ASSERT(serial->ops->dma_transmit != RT_NULL);
464*10465441SEvalZero             serial->ops->dma_transmit(serial, data, length, RT_SERIAL_DMA_RX);
465*10465441SEvalZero         }
466*10465441SEvalZero         else result = -RT_EBUSY;
467*10465441SEvalZero         rt_hw_interrupt_enable(level);
468*10465441SEvalZero 
469*10465441SEvalZero         if (result == RT_EOK) return length;
470*10465441SEvalZero 
471*10465441SEvalZero         rt_set_errno(result);
472*10465441SEvalZero         return 0;
473*10465441SEvalZero     }
474*10465441SEvalZero     else
475*10465441SEvalZero     {
476*10465441SEvalZero         struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
477*10465441SEvalZero         rt_size_t recv_len = 0, fifo_recved_len = rt_dma_calc_recved_len(serial);
478*10465441SEvalZero 
479*10465441SEvalZero         RT_ASSERT(rx_fifo != RT_NULL);
480*10465441SEvalZero 
481*10465441SEvalZero         if (length < fifo_recved_len)
482*10465441SEvalZero             recv_len = length;
483*10465441SEvalZero         else
484*10465441SEvalZero             recv_len = fifo_recved_len;
485*10465441SEvalZero 
486*10465441SEvalZero         if (rx_fifo->get_index + recv_len < serial->config.bufsz)
487*10465441SEvalZero             rt_memcpy(data, rx_fifo->buffer + rx_fifo->get_index, recv_len);
488*10465441SEvalZero         else
489*10465441SEvalZero         {
490*10465441SEvalZero             rt_memcpy(data, rx_fifo->buffer + rx_fifo->get_index,
491*10465441SEvalZero                     serial->config.bufsz - rx_fifo->get_index);
492*10465441SEvalZero             rt_memcpy(data + serial->config.bufsz - rx_fifo->get_index, rx_fifo->buffer,
493*10465441SEvalZero                     recv_len + rx_fifo->get_index - serial->config.bufsz);
494*10465441SEvalZero         }
495*10465441SEvalZero         rt_dma_recv_update_get_index(serial, recv_len);
496*10465441SEvalZero         rt_hw_interrupt_enable(level);
497*10465441SEvalZero         return recv_len;
498*10465441SEvalZero     }
499*10465441SEvalZero }
500*10465441SEvalZero 
_serial_dma_tx(struct rt_serial_device * serial,const rt_uint8_t * data,int length)501*10465441SEvalZero rt_inline int _serial_dma_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
502*10465441SEvalZero {
503*10465441SEvalZero     rt_base_t level;
504*10465441SEvalZero     rt_err_t result;
505*10465441SEvalZero     struct rt_serial_tx_dma *tx_dma;
506*10465441SEvalZero 
507*10465441SEvalZero     tx_dma = (struct rt_serial_tx_dma*)(serial->serial_tx);
508*10465441SEvalZero 
509*10465441SEvalZero     result = rt_data_queue_push(&(tx_dma->data_queue), data, length, RT_WAITING_FOREVER);
510*10465441SEvalZero     if (result == RT_EOK)
511*10465441SEvalZero     {
512*10465441SEvalZero         level = rt_hw_interrupt_disable();
513*10465441SEvalZero         if (tx_dma->activated != RT_TRUE)
514*10465441SEvalZero         {
515*10465441SEvalZero             tx_dma->activated = RT_TRUE;
516*10465441SEvalZero             rt_hw_interrupt_enable(level);
517*10465441SEvalZero 
518*10465441SEvalZero             /* make a DMA transfer */
519*10465441SEvalZero             serial->ops->dma_transmit(serial, (rt_uint8_t *)data, length, RT_SERIAL_DMA_TX);
520*10465441SEvalZero         }
521*10465441SEvalZero         else
522*10465441SEvalZero         {
523*10465441SEvalZero             rt_hw_interrupt_enable(level);
524*10465441SEvalZero         }
525*10465441SEvalZero 
526*10465441SEvalZero         return length;
527*10465441SEvalZero     }
528*10465441SEvalZero     else
529*10465441SEvalZero     {
530*10465441SEvalZero         rt_set_errno(result);
531*10465441SEvalZero         return 0;
532*10465441SEvalZero     }
533*10465441SEvalZero }
534*10465441SEvalZero #endif /* RT_SERIAL_USING_DMA */
535*10465441SEvalZero 
536*10465441SEvalZero /* RT-Thread Device Interface */
537*10465441SEvalZero /*
538*10465441SEvalZero  * This function initializes serial device.
539*10465441SEvalZero  */
rt_serial_init(struct rt_device * dev)540*10465441SEvalZero static rt_err_t rt_serial_init(struct rt_device *dev)
541*10465441SEvalZero {
542*10465441SEvalZero     rt_err_t result = RT_EOK;
543*10465441SEvalZero     struct rt_serial_device *serial;
544*10465441SEvalZero 
545*10465441SEvalZero     RT_ASSERT(dev != RT_NULL);
546*10465441SEvalZero     serial = (struct rt_serial_device *)dev;
547*10465441SEvalZero 
548*10465441SEvalZero     /* initialize rx/tx */
549*10465441SEvalZero     serial->serial_rx = RT_NULL;
550*10465441SEvalZero     serial->serial_tx = RT_NULL;
551*10465441SEvalZero 
552*10465441SEvalZero     /* apply configuration */
553*10465441SEvalZero     if (serial->ops->configure)
554*10465441SEvalZero         result = serial->ops->configure(serial, &serial->config);
555*10465441SEvalZero 
556*10465441SEvalZero     return result;
557*10465441SEvalZero }
558*10465441SEvalZero 
rt_serial_open(struct rt_device * dev,rt_uint16_t oflag)559*10465441SEvalZero static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag)
560*10465441SEvalZero {
561*10465441SEvalZero     rt_uint16_t stream_flag = 0;
562*10465441SEvalZero     struct rt_serial_device *serial;
563*10465441SEvalZero 
564*10465441SEvalZero     RT_ASSERT(dev != RT_NULL);
565*10465441SEvalZero     serial = (struct rt_serial_device *)dev;
566*10465441SEvalZero 
567*10465441SEvalZero     LOG_D("open serial device: 0x%08x with open flag: 0x%04x",
568*10465441SEvalZero         dev, oflag);
569*10465441SEvalZero     /* check device flag with the open flag */
570*10465441SEvalZero     if ((oflag & RT_DEVICE_FLAG_DMA_RX) && !(dev->flag & RT_DEVICE_FLAG_DMA_RX))
571*10465441SEvalZero         return -RT_EIO;
572*10465441SEvalZero     if ((oflag & RT_DEVICE_FLAG_DMA_TX) && !(dev->flag & RT_DEVICE_FLAG_DMA_TX))
573*10465441SEvalZero         return -RT_EIO;
574*10465441SEvalZero     if ((oflag & RT_DEVICE_FLAG_INT_RX) && !(dev->flag & RT_DEVICE_FLAG_INT_RX))
575*10465441SEvalZero         return -RT_EIO;
576*10465441SEvalZero     if ((oflag & RT_DEVICE_FLAG_INT_TX) && !(dev->flag & RT_DEVICE_FLAG_INT_TX))
577*10465441SEvalZero         return -RT_EIO;
578*10465441SEvalZero 
579*10465441SEvalZero     /* keep steam flag */
580*10465441SEvalZero     if ((oflag & RT_DEVICE_FLAG_STREAM) || (dev->open_flag & RT_DEVICE_FLAG_STREAM))
581*10465441SEvalZero         stream_flag = RT_DEVICE_FLAG_STREAM;
582*10465441SEvalZero 
583*10465441SEvalZero     /* get open flags */
584*10465441SEvalZero     dev->open_flag = oflag & 0xff;
585*10465441SEvalZero 
586*10465441SEvalZero     /* initialize the Rx/Tx structure according to open flag */
587*10465441SEvalZero     if (serial->serial_rx == RT_NULL)
588*10465441SEvalZero     {
589*10465441SEvalZero         if (oflag & RT_DEVICE_FLAG_INT_RX)
590*10465441SEvalZero         {
591*10465441SEvalZero             struct rt_serial_rx_fifo* rx_fifo;
592*10465441SEvalZero 
593*10465441SEvalZero             rx_fifo = (struct rt_serial_rx_fifo*) rt_malloc (sizeof(struct rt_serial_rx_fifo) +
594*10465441SEvalZero                 serial->config.bufsz);
595*10465441SEvalZero             RT_ASSERT(rx_fifo != RT_NULL);
596*10465441SEvalZero             rx_fifo->buffer = (rt_uint8_t*) (rx_fifo + 1);
597*10465441SEvalZero             rt_memset(rx_fifo->buffer, 0, serial->config.bufsz);
598*10465441SEvalZero             rx_fifo->put_index = 0;
599*10465441SEvalZero             rx_fifo->get_index = 0;
600*10465441SEvalZero             rx_fifo->is_full = RT_FALSE;
601*10465441SEvalZero 
602*10465441SEvalZero             serial->serial_rx = rx_fifo;
603*10465441SEvalZero             dev->open_flag |= RT_DEVICE_FLAG_INT_RX;
604*10465441SEvalZero             /* configure low level device */
605*10465441SEvalZero             serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX);
606*10465441SEvalZero         }
607*10465441SEvalZero #ifdef RT_SERIAL_USING_DMA
608*10465441SEvalZero         else if (oflag & RT_DEVICE_FLAG_DMA_RX)
609*10465441SEvalZero         {
610*10465441SEvalZero             if (serial->config.bufsz == 0) {
611*10465441SEvalZero                 struct rt_serial_rx_dma* rx_dma;
612*10465441SEvalZero 
613*10465441SEvalZero                 rx_dma = (struct rt_serial_rx_dma*) rt_malloc (sizeof(struct rt_serial_rx_dma));
614*10465441SEvalZero                 RT_ASSERT(rx_dma != RT_NULL);
615*10465441SEvalZero                 rx_dma->activated = RT_FALSE;
616*10465441SEvalZero 
617*10465441SEvalZero                 serial->serial_rx = rx_dma;
618*10465441SEvalZero             } else {
619*10465441SEvalZero                 struct rt_serial_rx_fifo* rx_fifo;
620*10465441SEvalZero 
621*10465441SEvalZero                 rx_fifo = (struct rt_serial_rx_fifo*) rt_malloc (sizeof(struct rt_serial_rx_fifo) +
622*10465441SEvalZero                     serial->config.bufsz);
623*10465441SEvalZero                 RT_ASSERT(rx_fifo != RT_NULL);
624*10465441SEvalZero                 rx_fifo->buffer = (rt_uint8_t*) (rx_fifo + 1);
625*10465441SEvalZero                 rt_memset(rx_fifo->buffer, 0, serial->config.bufsz);
626*10465441SEvalZero                 rx_fifo->put_index = 0;
627*10465441SEvalZero                 rx_fifo->get_index = 0;
628*10465441SEvalZero                 rx_fifo->is_full = RT_FALSE;
629*10465441SEvalZero                 serial->serial_rx = rx_fifo;
630*10465441SEvalZero                 /* configure fifo address and length to low level device */
631*10465441SEvalZero                 serial->ops->control(serial, RT_DEVICE_CTRL_CONFIG, (void *) RT_DEVICE_FLAG_DMA_RX);
632*10465441SEvalZero             }
633*10465441SEvalZero             dev->open_flag |= RT_DEVICE_FLAG_DMA_RX;
634*10465441SEvalZero         }
635*10465441SEvalZero #endif /* RT_SERIAL_USING_DMA */
636*10465441SEvalZero         else
637*10465441SEvalZero         {
638*10465441SEvalZero             serial->serial_rx = RT_NULL;
639*10465441SEvalZero         }
640*10465441SEvalZero     }
641*10465441SEvalZero     else
642*10465441SEvalZero     {
643*10465441SEvalZero         if (oflag & RT_DEVICE_FLAG_INT_RX)
644*10465441SEvalZero             dev->open_flag |= RT_DEVICE_FLAG_INT_RX;
645*10465441SEvalZero #ifdef RT_SERIAL_USING_DMA
646*10465441SEvalZero         else if (oflag & RT_DEVICE_FLAG_DMA_RX)
647*10465441SEvalZero             dev->open_flag |= RT_DEVICE_FLAG_DMA_RX;
648*10465441SEvalZero #endif /* RT_SERIAL_USING_DMA */
649*10465441SEvalZero     }
650*10465441SEvalZero 
651*10465441SEvalZero     if (serial->serial_tx == RT_NULL)
652*10465441SEvalZero     {
653*10465441SEvalZero         if (oflag & RT_DEVICE_FLAG_INT_TX)
654*10465441SEvalZero         {
655*10465441SEvalZero             struct rt_serial_tx_fifo *tx_fifo;
656*10465441SEvalZero 
657*10465441SEvalZero             tx_fifo = (struct rt_serial_tx_fifo*) rt_malloc(sizeof(struct rt_serial_tx_fifo));
658*10465441SEvalZero             RT_ASSERT(tx_fifo != RT_NULL);
659*10465441SEvalZero 
660*10465441SEvalZero             rt_completion_init(&(tx_fifo->completion));
661*10465441SEvalZero             serial->serial_tx = tx_fifo;
662*10465441SEvalZero 
663*10465441SEvalZero             dev->open_flag |= RT_DEVICE_FLAG_INT_TX;
664*10465441SEvalZero             /* configure low level device */
665*10465441SEvalZero             serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_TX);
666*10465441SEvalZero         }
667*10465441SEvalZero #ifdef RT_SERIAL_USING_DMA
668*10465441SEvalZero         else if (oflag & RT_DEVICE_FLAG_DMA_TX)
669*10465441SEvalZero         {
670*10465441SEvalZero             struct rt_serial_tx_dma* tx_dma;
671*10465441SEvalZero 
672*10465441SEvalZero             tx_dma = (struct rt_serial_tx_dma*) rt_malloc (sizeof(struct rt_serial_tx_dma));
673*10465441SEvalZero             RT_ASSERT(tx_dma != RT_NULL);
674*10465441SEvalZero             tx_dma->activated = RT_FALSE;
675*10465441SEvalZero 
676*10465441SEvalZero             rt_data_queue_init(&(tx_dma->data_queue), 8, 4, RT_NULL);
677*10465441SEvalZero             serial->serial_tx = tx_dma;
678*10465441SEvalZero 
679*10465441SEvalZero             dev->open_flag |= RT_DEVICE_FLAG_DMA_TX;
680*10465441SEvalZero         }
681*10465441SEvalZero #endif /* RT_SERIAL_USING_DMA */
682*10465441SEvalZero         else
683*10465441SEvalZero         {
684*10465441SEvalZero             serial->serial_tx = RT_NULL;
685*10465441SEvalZero         }
686*10465441SEvalZero     }
687*10465441SEvalZero     else
688*10465441SEvalZero     {
689*10465441SEvalZero         if (oflag & RT_DEVICE_FLAG_INT_TX)
690*10465441SEvalZero             dev->open_flag |= RT_DEVICE_FLAG_INT_TX;
691*10465441SEvalZero #ifdef RT_SERIAL_USING_DMA
692*10465441SEvalZero         else if (oflag & RT_DEVICE_FLAG_DMA_TX)
693*10465441SEvalZero             dev->open_flag |= RT_DEVICE_FLAG_DMA_TX;
694*10465441SEvalZero #endif /* RT_SERIAL_USING_DMA */
695*10465441SEvalZero     }
696*10465441SEvalZero 
697*10465441SEvalZero     /* set stream flag */
698*10465441SEvalZero     dev->open_flag |= stream_flag;
699*10465441SEvalZero 
700*10465441SEvalZero     return RT_EOK;
701*10465441SEvalZero }
702*10465441SEvalZero 
rt_serial_close(struct rt_device * dev)703*10465441SEvalZero static rt_err_t rt_serial_close(struct rt_device *dev)
704*10465441SEvalZero {
705*10465441SEvalZero     struct rt_serial_device *serial;
706*10465441SEvalZero 
707*10465441SEvalZero     RT_ASSERT(dev != RT_NULL);
708*10465441SEvalZero     serial = (struct rt_serial_device *)dev;
709*10465441SEvalZero 
710*10465441SEvalZero     /* this device has more reference count */
711*10465441SEvalZero     if (dev->ref_count > 1) return RT_EOK;
712*10465441SEvalZero 
713*10465441SEvalZero     if (dev->open_flag & RT_DEVICE_FLAG_INT_RX)
714*10465441SEvalZero     {
715*10465441SEvalZero         struct rt_serial_rx_fifo* rx_fifo;
716*10465441SEvalZero 
717*10465441SEvalZero         rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx;
718*10465441SEvalZero         RT_ASSERT(rx_fifo != RT_NULL);
719*10465441SEvalZero 
720*10465441SEvalZero         rt_free(rx_fifo);
721*10465441SEvalZero         serial->serial_rx = RT_NULL;
722*10465441SEvalZero         dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX;
723*10465441SEvalZero         /* configure low level device */
724*10465441SEvalZero         serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_RX);
725*10465441SEvalZero     }
726*10465441SEvalZero #ifdef RT_SERIAL_USING_DMA
727*10465441SEvalZero     else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX)
728*10465441SEvalZero     {
729*10465441SEvalZero         if (serial->config.bufsz == 0) {
730*10465441SEvalZero             struct rt_serial_rx_dma* rx_dma;
731*10465441SEvalZero 
732*10465441SEvalZero             rx_dma = (struct rt_serial_rx_dma*)serial->serial_rx;
733*10465441SEvalZero             RT_ASSERT(rx_dma != RT_NULL);
734*10465441SEvalZero 
735*10465441SEvalZero             rt_free(rx_dma);
736*10465441SEvalZero         } else {
737*10465441SEvalZero             struct rt_serial_rx_fifo* rx_fifo;
738*10465441SEvalZero 
739*10465441SEvalZero             rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx;
740*10465441SEvalZero             RT_ASSERT(rx_fifo != RT_NULL);
741*10465441SEvalZero 
742*10465441SEvalZero             rt_free(rx_fifo);
743*10465441SEvalZero         }
744*10465441SEvalZero         /* configure low level device */
745*10465441SEvalZero         serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *) RT_DEVICE_FLAG_DMA_RX);
746*10465441SEvalZero         serial->serial_rx = RT_NULL;
747*10465441SEvalZero         dev->open_flag &= ~RT_DEVICE_FLAG_DMA_RX;
748*10465441SEvalZero     }
749*10465441SEvalZero #endif /* RT_SERIAL_USING_DMA */
750*10465441SEvalZero 
751*10465441SEvalZero     if (dev->open_flag & RT_DEVICE_FLAG_INT_TX)
752*10465441SEvalZero     {
753*10465441SEvalZero         struct rt_serial_tx_fifo* tx_fifo;
754*10465441SEvalZero 
755*10465441SEvalZero         tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_tx;
756*10465441SEvalZero         RT_ASSERT(tx_fifo != RT_NULL);
757*10465441SEvalZero 
758*10465441SEvalZero         rt_free(tx_fifo);
759*10465441SEvalZero         serial->serial_tx = RT_NULL;
760*10465441SEvalZero         dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX;
761*10465441SEvalZero         /* configure low level device */
762*10465441SEvalZero         serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX);
763*10465441SEvalZero     }
764*10465441SEvalZero #ifdef RT_SERIAL_USING_DMA
765*10465441SEvalZero     else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX)
766*10465441SEvalZero     {
767*10465441SEvalZero         struct rt_serial_tx_dma* tx_dma;
768*10465441SEvalZero 
769*10465441SEvalZero         tx_dma = (struct rt_serial_tx_dma*)serial->serial_tx;
770*10465441SEvalZero         RT_ASSERT(tx_dma != RT_NULL);
771*10465441SEvalZero 
772*10465441SEvalZero         rt_free(tx_dma);
773*10465441SEvalZero         serial->serial_tx = RT_NULL;
774*10465441SEvalZero         dev->open_flag &= ~RT_DEVICE_FLAG_DMA_TX;
775*10465441SEvalZero     }
776*10465441SEvalZero #endif /* RT_SERIAL_USING_DMA */
777*10465441SEvalZero     return RT_EOK;
778*10465441SEvalZero }
779*10465441SEvalZero 
rt_serial_read(struct rt_device * dev,rt_off_t pos,void * buffer,rt_size_t size)780*10465441SEvalZero static rt_size_t rt_serial_read(struct rt_device *dev,
781*10465441SEvalZero                                 rt_off_t          pos,
782*10465441SEvalZero                                 void             *buffer,
783*10465441SEvalZero                                 rt_size_t         size)
784*10465441SEvalZero {
785*10465441SEvalZero     struct rt_serial_device *serial;
786*10465441SEvalZero 
787*10465441SEvalZero     RT_ASSERT(dev != RT_NULL);
788*10465441SEvalZero     if (size == 0) return 0;
789*10465441SEvalZero 
790*10465441SEvalZero     serial = (struct rt_serial_device *)dev;
791*10465441SEvalZero 
792*10465441SEvalZero     if (dev->open_flag & RT_DEVICE_FLAG_INT_RX)
793*10465441SEvalZero     {
794*10465441SEvalZero         return _serial_int_rx(serial, buffer, size);
795*10465441SEvalZero     }
796*10465441SEvalZero #ifdef RT_SERIAL_USING_DMA
797*10465441SEvalZero     else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX)
798*10465441SEvalZero     {
799*10465441SEvalZero         return _serial_dma_rx(serial, buffer, size);
800*10465441SEvalZero     }
801*10465441SEvalZero #endif /* RT_SERIAL_USING_DMA */
802*10465441SEvalZero 
803*10465441SEvalZero     return _serial_poll_rx(serial, buffer, size);
804*10465441SEvalZero }
805*10465441SEvalZero 
rt_serial_write(struct rt_device * dev,rt_off_t pos,const void * buffer,rt_size_t size)806*10465441SEvalZero static rt_size_t rt_serial_write(struct rt_device *dev,
807*10465441SEvalZero                                  rt_off_t          pos,
808*10465441SEvalZero                                  const void       *buffer,
809*10465441SEvalZero                                  rt_size_t         size)
810*10465441SEvalZero {
811*10465441SEvalZero     struct rt_serial_device *serial;
812*10465441SEvalZero 
813*10465441SEvalZero     RT_ASSERT(dev != RT_NULL);
814*10465441SEvalZero     if (size == 0) return 0;
815*10465441SEvalZero 
816*10465441SEvalZero     serial = (struct rt_serial_device *)dev;
817*10465441SEvalZero 
818*10465441SEvalZero     if (dev->open_flag & RT_DEVICE_FLAG_INT_TX)
819*10465441SEvalZero     {
820*10465441SEvalZero         return _serial_int_tx(serial, buffer, size);
821*10465441SEvalZero     }
822*10465441SEvalZero #ifdef RT_SERIAL_USING_DMA
823*10465441SEvalZero     else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX)
824*10465441SEvalZero     {
825*10465441SEvalZero         return _serial_dma_tx(serial, buffer, size);
826*10465441SEvalZero     }
827*10465441SEvalZero #endif /* RT_SERIAL_USING_DMA */
828*10465441SEvalZero     else
829*10465441SEvalZero     {
830*10465441SEvalZero         return _serial_poll_tx(serial, buffer, size);
831*10465441SEvalZero     }
832*10465441SEvalZero }
833*10465441SEvalZero 
834*10465441SEvalZero #ifdef RT_USING_POSIX_TERMIOS
835*10465441SEvalZero struct speed_baudrate_item
836*10465441SEvalZero {
837*10465441SEvalZero     speed_t speed;
838*10465441SEvalZero     int baudrate;
839*10465441SEvalZero };
840*10465441SEvalZero 
841*10465441SEvalZero const static struct speed_baudrate_item _tbl[] =
842*10465441SEvalZero {
843*10465441SEvalZero     {B2400, BAUD_RATE_2400},
844*10465441SEvalZero     {B4800, BAUD_RATE_4800},
845*10465441SEvalZero     {B9600, BAUD_RATE_9600},
846*10465441SEvalZero     {B19200, BAUD_RATE_19200},
847*10465441SEvalZero     {B38400, BAUD_RATE_38400},
848*10465441SEvalZero     {B57600, BAUD_RATE_57600},
849*10465441SEvalZero     {B115200, BAUD_RATE_115200},
850*10465441SEvalZero     {B230400, BAUD_RATE_230400},
851*10465441SEvalZero     {B460800, BAUD_RATE_460800},
852*10465441SEvalZero     {B921600, BAUD_RATE_921600},
853*10465441SEvalZero     {B2000000, BAUD_RATE_2000000},
854*10465441SEvalZero     {B3000000, BAUD_RATE_3000000},
855*10465441SEvalZero };
856*10465441SEvalZero 
_get_speed(int baudrate)857*10465441SEvalZero static speed_t _get_speed(int baudrate)
858*10465441SEvalZero {
859*10465441SEvalZero     int index;
860*10465441SEvalZero 
861*10465441SEvalZero     for (index = 0; index < sizeof(_tbl)/sizeof(_tbl[0]); index ++)
862*10465441SEvalZero     {
863*10465441SEvalZero         if (_tbl[index].baudrate == baudrate)
864*10465441SEvalZero             return _tbl[index].speed;
865*10465441SEvalZero     }
866*10465441SEvalZero 
867*10465441SEvalZero     return B0;
868*10465441SEvalZero }
869*10465441SEvalZero 
_get_baudrate(speed_t speed)870*10465441SEvalZero static int _get_baudrate(speed_t speed)
871*10465441SEvalZero {
872*10465441SEvalZero     int index;
873*10465441SEvalZero 
874*10465441SEvalZero     for (index = 0; index < sizeof(_tbl)/sizeof(_tbl[0]); index ++)
875*10465441SEvalZero     {
876*10465441SEvalZero         if (_tbl[index].speed == speed)
877*10465441SEvalZero             return _tbl[index].baudrate;
878*10465441SEvalZero     }
879*10465441SEvalZero 
880*10465441SEvalZero     return 0;
881*10465441SEvalZero }
882*10465441SEvalZero 
_tc_flush(struct rt_serial_device * serial,int queue)883*10465441SEvalZero static void _tc_flush(struct rt_serial_device *serial, int queue)
884*10465441SEvalZero {
885*10465441SEvalZero     int ch = -1;
886*10465441SEvalZero     struct rt_serial_rx_fifo *rx_fifo = RT_NULL;
887*10465441SEvalZero     struct rt_device *device = RT_NULL;
888*10465441SEvalZero 
889*10465441SEvalZero     RT_ASSERT(serial != RT_NULL);
890*10465441SEvalZero 
891*10465441SEvalZero     device = &(serial->parent);
892*10465441SEvalZero     rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
893*10465441SEvalZero 
894*10465441SEvalZero     switch(queue)
895*10465441SEvalZero     {
896*10465441SEvalZero         case TCIFLUSH:
897*10465441SEvalZero         case TCIOFLUSH:
898*10465441SEvalZero 
899*10465441SEvalZero             RT_ASSERT(rx_fifo != RT_NULL);
900*10465441SEvalZero 
901*10465441SEvalZero             if((device->open_flag & RT_DEVICE_FLAG_INT_RX) || (device->open_flag & RT_DEVICE_FLAG_DMA_RX))
902*10465441SEvalZero             {
903*10465441SEvalZero                 RT_ASSERT(RT_NULL != rx_fifo);
904*10465441SEvalZero                 rt_memset(rx_fifo->buffer, 0, serial->config.bufsz);
905*10465441SEvalZero                 rx_fifo->put_index = 0;
906*10465441SEvalZero                 rx_fifo->get_index = 0;
907*10465441SEvalZero                 rx_fifo->is_full = RT_FALSE;
908*10465441SEvalZero             }
909*10465441SEvalZero             else
910*10465441SEvalZero             {
911*10465441SEvalZero                 while (1)
912*10465441SEvalZero                 {
913*10465441SEvalZero                     ch = serial->ops->getc(serial);
914*10465441SEvalZero                     if (ch == -1) break;
915*10465441SEvalZero                 }
916*10465441SEvalZero             }
917*10465441SEvalZero 
918*10465441SEvalZero             break;
919*10465441SEvalZero 
920*10465441SEvalZero          case TCOFLUSH:
921*10465441SEvalZero             break;
922*10465441SEvalZero     }
923*10465441SEvalZero 
924*10465441SEvalZero }
925*10465441SEvalZero 
926*10465441SEvalZero #endif
927*10465441SEvalZero 
rt_serial_control(struct rt_device * dev,int cmd,void * args)928*10465441SEvalZero static rt_err_t rt_serial_control(struct rt_device *dev,
929*10465441SEvalZero                                   int              cmd,
930*10465441SEvalZero                                   void             *args)
931*10465441SEvalZero {
932*10465441SEvalZero     rt_err_t ret = RT_EOK;
933*10465441SEvalZero     struct rt_serial_device *serial;
934*10465441SEvalZero 
935*10465441SEvalZero     RT_ASSERT(dev != RT_NULL);
936*10465441SEvalZero     serial = (struct rt_serial_device *)dev;
937*10465441SEvalZero 
938*10465441SEvalZero     switch (cmd)
939*10465441SEvalZero     {
940*10465441SEvalZero         case RT_DEVICE_CTRL_SUSPEND:
941*10465441SEvalZero             /* suspend device */
942*10465441SEvalZero             dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
943*10465441SEvalZero             break;
944*10465441SEvalZero 
945*10465441SEvalZero         case RT_DEVICE_CTRL_RESUME:
946*10465441SEvalZero             /* resume device */
947*10465441SEvalZero             dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
948*10465441SEvalZero             break;
949*10465441SEvalZero 
950*10465441SEvalZero         case RT_DEVICE_CTRL_CONFIG:
951*10465441SEvalZero             if (args)
952*10465441SEvalZero             {
953*10465441SEvalZero                 struct serial_configure *pconfig = (struct serial_configure *) args;
954*10465441SEvalZero                 if (pconfig->bufsz != serial->config.bufsz && serial->parent.ref_count)
955*10465441SEvalZero                 {
956*10465441SEvalZero                     /*can not change buffer size*/
957*10465441SEvalZero                     return RT_EBUSY;
958*10465441SEvalZero                 }
959*10465441SEvalZero                 /* set serial configure */
960*10465441SEvalZero                 serial->config = *pconfig;
961*10465441SEvalZero                 if (serial->parent.ref_count)
962*10465441SEvalZero                 {
963*10465441SEvalZero                     /* serial device has been opened, to configure it */
964*10465441SEvalZero                     serial->ops->configure(serial, (struct serial_configure *) args);
965*10465441SEvalZero                 }
966*10465441SEvalZero             }
967*10465441SEvalZero 
968*10465441SEvalZero             break;
969*10465441SEvalZero 
970*10465441SEvalZero #ifdef RT_USING_POSIX_TERMIOS
971*10465441SEvalZero         case TCGETA:
972*10465441SEvalZero             {
973*10465441SEvalZero                 struct termios *tio = (struct termios*)args;
974*10465441SEvalZero                 if (tio == RT_NULL) return -RT_EINVAL;
975*10465441SEvalZero 
976*10465441SEvalZero                 tio->c_iflag = 0;
977*10465441SEvalZero                 tio->c_oflag = 0;
978*10465441SEvalZero                 tio->c_lflag = 0;
979*10465441SEvalZero 
980*10465441SEvalZero                 /* update oflag for console device */
981*10465441SEvalZero                 if (rt_console_get_device() == dev)
982*10465441SEvalZero                     tio->c_oflag = OPOST | ONLCR;
983*10465441SEvalZero 
984*10465441SEvalZero                 /* set cflag */
985*10465441SEvalZero                 tio->c_cflag = 0;
986*10465441SEvalZero                 if (serial->config.data_bits == DATA_BITS_5)
987*10465441SEvalZero                     tio->c_cflag = CS5;
988*10465441SEvalZero                 else if (serial->config.data_bits == DATA_BITS_6)
989*10465441SEvalZero                     tio->c_cflag = CS6;
990*10465441SEvalZero                 else if (serial->config.data_bits == DATA_BITS_7)
991*10465441SEvalZero                     tio->c_cflag = CS7;
992*10465441SEvalZero                 else if (serial->config.data_bits == DATA_BITS_8)
993*10465441SEvalZero                     tio->c_cflag = CS8;
994*10465441SEvalZero 
995*10465441SEvalZero                 if (serial->config.stop_bits == STOP_BITS_2)
996*10465441SEvalZero                     tio->c_cflag |= CSTOPB;
997*10465441SEvalZero 
998*10465441SEvalZero                 if (serial->config.parity == PARITY_EVEN)
999*10465441SEvalZero                     tio->c_cflag |= PARENB;
1000*10465441SEvalZero                 else if (serial->config.parity == PARITY_ODD)
1001*10465441SEvalZero                     tio->c_cflag |= (PARODD | PARENB);
1002*10465441SEvalZero 
1003*10465441SEvalZero                 cfsetospeed(tio, _get_speed(serial->config.baud_rate));
1004*10465441SEvalZero             }
1005*10465441SEvalZero             break;
1006*10465441SEvalZero 
1007*10465441SEvalZero         case TCSETAW:
1008*10465441SEvalZero         case TCSETAF:
1009*10465441SEvalZero         case TCSETA:
1010*10465441SEvalZero             {
1011*10465441SEvalZero                 int baudrate;
1012*10465441SEvalZero                 struct serial_configure config;
1013*10465441SEvalZero 
1014*10465441SEvalZero                 struct termios *tio = (struct termios*)args;
1015*10465441SEvalZero                 if (tio == RT_NULL) return -RT_EINVAL;
1016*10465441SEvalZero 
1017*10465441SEvalZero                 config = serial->config;
1018*10465441SEvalZero 
1019*10465441SEvalZero                 baudrate = _get_baudrate(cfgetospeed(tio));
1020*10465441SEvalZero                 config.baud_rate = baudrate;
1021*10465441SEvalZero 
1022*10465441SEvalZero                 switch (tio->c_cflag & CSIZE)
1023*10465441SEvalZero                 {
1024*10465441SEvalZero                 case CS5:
1025*10465441SEvalZero                     config.data_bits = DATA_BITS_5;
1026*10465441SEvalZero                     break;
1027*10465441SEvalZero                 case CS6:
1028*10465441SEvalZero                     config.data_bits = DATA_BITS_6;
1029*10465441SEvalZero                     break;
1030*10465441SEvalZero                 case CS7:
1031*10465441SEvalZero                     config.data_bits = DATA_BITS_7;
1032*10465441SEvalZero                     break;
1033*10465441SEvalZero                 default:
1034*10465441SEvalZero                     config.data_bits = DATA_BITS_8;
1035*10465441SEvalZero                     break;
1036*10465441SEvalZero                 }
1037*10465441SEvalZero 
1038*10465441SEvalZero                 if (tio->c_cflag & CSTOPB) config.stop_bits = STOP_BITS_2;
1039*10465441SEvalZero                 else config.stop_bits = STOP_BITS_1;
1040*10465441SEvalZero 
1041*10465441SEvalZero                 if (tio->c_cflag & PARENB)
1042*10465441SEvalZero                 {
1043*10465441SEvalZero                     if (tio->c_cflag & PARODD) config.parity = PARITY_ODD;
1044*10465441SEvalZero                     else config.parity = PARITY_EVEN;
1045*10465441SEvalZero                 }
1046*10465441SEvalZero                 else config.parity = PARITY_NONE;
1047*10465441SEvalZero 
1048*10465441SEvalZero                 serial->ops->configure(serial, &config);
1049*10465441SEvalZero             }
1050*10465441SEvalZero             break;
1051*10465441SEvalZero         case TCFLSH:
1052*10465441SEvalZero             {
1053*10465441SEvalZero                 int queue = (int)args;
1054*10465441SEvalZero 
1055*10465441SEvalZero                 _tc_flush(serial, queue);
1056*10465441SEvalZero             }
1057*10465441SEvalZero 
1058*10465441SEvalZero             break;
1059*10465441SEvalZero         case TCXONC:
1060*10465441SEvalZero             break;
1061*10465441SEvalZero #endif
1062*10465441SEvalZero #ifdef RT_USING_POSIX
1063*10465441SEvalZero         case FIONREAD:
1064*10465441SEvalZero             {
1065*10465441SEvalZero                 rt_size_t recved = 0;
1066*10465441SEvalZero                 rt_base_t level;
1067*10465441SEvalZero 
1068*10465441SEvalZero                 level = rt_hw_interrupt_disable();
1069*10465441SEvalZero                 recved = _serial_fifo_calc_recved_len(serial);
1070*10465441SEvalZero                 rt_hw_interrupt_enable(level);
1071*10465441SEvalZero 
1072*10465441SEvalZero                 *(rt_size_t *)args = recved;
1073*10465441SEvalZero             }
1074*10465441SEvalZero             break;
1075*10465441SEvalZero #endif
1076*10465441SEvalZero         default :
1077*10465441SEvalZero             /* control device */
1078*10465441SEvalZero             ret = serial->ops->control(serial, cmd, args);
1079*10465441SEvalZero             break;
1080*10465441SEvalZero     }
1081*10465441SEvalZero 
1082*10465441SEvalZero     return ret;
1083*10465441SEvalZero }
1084*10465441SEvalZero 
1085*10465441SEvalZero #ifdef RT_USING_DEVICE_OPS
1086*10465441SEvalZero const static struct rt_device_ops serial_ops =
1087*10465441SEvalZero {
1088*10465441SEvalZero     rt_serial_init,
1089*10465441SEvalZero     rt_serial_open,
1090*10465441SEvalZero     rt_serial_close,
1091*10465441SEvalZero     rt_serial_read,
1092*10465441SEvalZero     rt_serial_write,
1093*10465441SEvalZero     rt_serial_control
1094*10465441SEvalZero };
1095*10465441SEvalZero #endif
1096*10465441SEvalZero 
1097*10465441SEvalZero /*
1098*10465441SEvalZero  * serial register
1099*10465441SEvalZero  */
rt_hw_serial_register(struct rt_serial_device * serial,const char * name,rt_uint32_t flag,void * data)1100*10465441SEvalZero rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
1101*10465441SEvalZero                                const char              *name,
1102*10465441SEvalZero                                rt_uint32_t              flag,
1103*10465441SEvalZero                                void                    *data)
1104*10465441SEvalZero {
1105*10465441SEvalZero     rt_err_t ret;
1106*10465441SEvalZero     struct rt_device *device;
1107*10465441SEvalZero     RT_ASSERT(serial != RT_NULL);
1108*10465441SEvalZero 
1109*10465441SEvalZero     device = &(serial->parent);
1110*10465441SEvalZero 
1111*10465441SEvalZero     device->type        = RT_Device_Class_Char;
1112*10465441SEvalZero     device->rx_indicate = RT_NULL;
1113*10465441SEvalZero     device->tx_complete = RT_NULL;
1114*10465441SEvalZero 
1115*10465441SEvalZero #ifdef RT_USING_DEVICE_OPS
1116*10465441SEvalZero     device->ops         = &serial_ops;
1117*10465441SEvalZero #else
1118*10465441SEvalZero     device->init        = rt_serial_init;
1119*10465441SEvalZero     device->open        = rt_serial_open;
1120*10465441SEvalZero     device->close       = rt_serial_close;
1121*10465441SEvalZero     device->read        = rt_serial_read;
1122*10465441SEvalZero     device->write       = rt_serial_write;
1123*10465441SEvalZero     device->control     = rt_serial_control;
1124*10465441SEvalZero #endif
1125*10465441SEvalZero     device->user_data   = data;
1126*10465441SEvalZero 
1127*10465441SEvalZero     /* register a character device */
1128*10465441SEvalZero     ret = rt_device_register(device, name, flag);
1129*10465441SEvalZero 
1130*10465441SEvalZero #if defined(RT_USING_POSIX)
1131*10465441SEvalZero     /* set fops */
1132*10465441SEvalZero     device->fops        = &_serial_fops;
1133*10465441SEvalZero #endif
1134*10465441SEvalZero 
1135*10465441SEvalZero     return ret;
1136*10465441SEvalZero }
1137*10465441SEvalZero 
1138*10465441SEvalZero /* ISR for serial interrupt */
rt_hw_serial_isr(struct rt_serial_device * serial,int event)1139*10465441SEvalZero void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
1140*10465441SEvalZero {
1141*10465441SEvalZero     switch (event & 0xff)
1142*10465441SEvalZero     {
1143*10465441SEvalZero         case RT_SERIAL_EVENT_RX_IND:
1144*10465441SEvalZero         {
1145*10465441SEvalZero             int ch = -1;
1146*10465441SEvalZero             rt_base_t level;
1147*10465441SEvalZero             struct rt_serial_rx_fifo* rx_fifo;
1148*10465441SEvalZero 
1149*10465441SEvalZero             /* interrupt mode receive */
1150*10465441SEvalZero             rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx;
1151*10465441SEvalZero             RT_ASSERT(rx_fifo != RT_NULL);
1152*10465441SEvalZero 
1153*10465441SEvalZero             while (1)
1154*10465441SEvalZero             {
1155*10465441SEvalZero                 ch = serial->ops->getc(serial);
1156*10465441SEvalZero                 if (ch == -1) break;
1157*10465441SEvalZero 
1158*10465441SEvalZero 
1159*10465441SEvalZero                 /* disable interrupt */
1160*10465441SEvalZero                 level = rt_hw_interrupt_disable();
1161*10465441SEvalZero 
1162*10465441SEvalZero                 rx_fifo->buffer[rx_fifo->put_index] = ch;
1163*10465441SEvalZero                 rx_fifo->put_index += 1;
1164*10465441SEvalZero                 if (rx_fifo->put_index >= serial->config.bufsz) rx_fifo->put_index = 0;
1165*10465441SEvalZero 
1166*10465441SEvalZero                 /* if the next position is read index, discard this 'read char' */
1167*10465441SEvalZero                 if (rx_fifo->put_index == rx_fifo->get_index)
1168*10465441SEvalZero                 {
1169*10465441SEvalZero                     rx_fifo->get_index += 1;
1170*10465441SEvalZero                     rx_fifo->is_full = RT_TRUE;
1171*10465441SEvalZero                     if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0;
1172*10465441SEvalZero                 }
1173*10465441SEvalZero 
1174*10465441SEvalZero                 /* enable interrupt */
1175*10465441SEvalZero                 rt_hw_interrupt_enable(level);
1176*10465441SEvalZero             }
1177*10465441SEvalZero 
1178*10465441SEvalZero             /* invoke callback */
1179*10465441SEvalZero             if (serial->parent.rx_indicate != RT_NULL)
1180*10465441SEvalZero             {
1181*10465441SEvalZero                 rt_size_t rx_length;
1182*10465441SEvalZero 
1183*10465441SEvalZero                 /* get rx length */
1184*10465441SEvalZero                 level = rt_hw_interrupt_disable();
1185*10465441SEvalZero                 rx_length = (rx_fifo->put_index >= rx_fifo->get_index)? (rx_fifo->put_index - rx_fifo->get_index):
1186*10465441SEvalZero                     (serial->config.bufsz - (rx_fifo->get_index - rx_fifo->put_index));
1187*10465441SEvalZero                 rt_hw_interrupt_enable(level);
1188*10465441SEvalZero 
1189*10465441SEvalZero                 if (rx_length)
1190*10465441SEvalZero                 {
1191*10465441SEvalZero                     serial->parent.rx_indicate(&serial->parent, rx_length);
1192*10465441SEvalZero                 }
1193*10465441SEvalZero             }
1194*10465441SEvalZero             break;
1195*10465441SEvalZero         }
1196*10465441SEvalZero         case RT_SERIAL_EVENT_TX_DONE:
1197*10465441SEvalZero         {
1198*10465441SEvalZero             struct rt_serial_tx_fifo* tx_fifo;
1199*10465441SEvalZero 
1200*10465441SEvalZero             tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_tx;
1201*10465441SEvalZero             rt_completion_done(&(tx_fifo->completion));
1202*10465441SEvalZero             break;
1203*10465441SEvalZero         }
1204*10465441SEvalZero #ifdef RT_SERIAL_USING_DMA
1205*10465441SEvalZero         case RT_SERIAL_EVENT_TX_DMADONE:
1206*10465441SEvalZero         {
1207*10465441SEvalZero             const void *data_ptr;
1208*10465441SEvalZero             rt_size_t data_size;
1209*10465441SEvalZero             const void *last_data_ptr;
1210*10465441SEvalZero             struct rt_serial_tx_dma *tx_dma;
1211*10465441SEvalZero 
1212*10465441SEvalZero             tx_dma = (struct rt_serial_tx_dma*) serial->serial_tx;
1213*10465441SEvalZero 
1214*10465441SEvalZero             rt_data_queue_pop(&(tx_dma->data_queue), &last_data_ptr, &data_size, 0);
1215*10465441SEvalZero             if (rt_data_queue_peak(&(tx_dma->data_queue), &data_ptr, &data_size) == RT_EOK)
1216*10465441SEvalZero             {
1217*10465441SEvalZero                 /* transmit next data node */
1218*10465441SEvalZero                 tx_dma->activated = RT_TRUE;
1219*10465441SEvalZero                 serial->ops->dma_transmit(serial, (rt_uint8_t *)data_ptr, data_size, RT_SERIAL_DMA_TX);
1220*10465441SEvalZero             }
1221*10465441SEvalZero             else
1222*10465441SEvalZero             {
1223*10465441SEvalZero                 tx_dma->activated = RT_FALSE;
1224*10465441SEvalZero             }
1225*10465441SEvalZero 
1226*10465441SEvalZero             /* invoke callback */
1227*10465441SEvalZero             if (serial->parent.tx_complete != RT_NULL)
1228*10465441SEvalZero             {
1229*10465441SEvalZero                 serial->parent.tx_complete(&serial->parent, (void*)last_data_ptr);
1230*10465441SEvalZero             }
1231*10465441SEvalZero             break;
1232*10465441SEvalZero         }
1233*10465441SEvalZero         case RT_SERIAL_EVENT_RX_DMADONE:
1234*10465441SEvalZero         {
1235*10465441SEvalZero             int length;
1236*10465441SEvalZero             rt_base_t level;
1237*10465441SEvalZero 
1238*10465441SEvalZero             /* get DMA rx length */
1239*10465441SEvalZero             length = (event & (~0xff)) >> 8;
1240*10465441SEvalZero 
1241*10465441SEvalZero             if (serial->config.bufsz == 0)
1242*10465441SEvalZero             {
1243*10465441SEvalZero                 struct rt_serial_rx_dma* rx_dma;
1244*10465441SEvalZero 
1245*10465441SEvalZero                 rx_dma = (struct rt_serial_rx_dma*) serial->serial_rx;
1246*10465441SEvalZero                 RT_ASSERT(rx_dma != RT_NULL);
1247*10465441SEvalZero 
1248*10465441SEvalZero                 RT_ASSERT(serial->parent.rx_indicate != RT_NULL);
1249*10465441SEvalZero                 serial->parent.rx_indicate(&(serial->parent), length);
1250*10465441SEvalZero                 rx_dma->activated = RT_FALSE;
1251*10465441SEvalZero             }
1252*10465441SEvalZero             else
1253*10465441SEvalZero             {
1254*10465441SEvalZero                 /* disable interrupt */
1255*10465441SEvalZero                 level = rt_hw_interrupt_disable();
1256*10465441SEvalZero                 /* update fifo put index */
1257*10465441SEvalZero                 rt_dma_recv_update_put_index(serial, length);
1258*10465441SEvalZero                 /* calculate received total length */
1259*10465441SEvalZero                 length = rt_dma_calc_recved_len(serial);
1260*10465441SEvalZero                 /* enable interrupt */
1261*10465441SEvalZero                 rt_hw_interrupt_enable(level);
1262*10465441SEvalZero                 /* invoke callback */
1263*10465441SEvalZero                 if (serial->parent.rx_indicate != RT_NULL)
1264*10465441SEvalZero                 {
1265*10465441SEvalZero                     serial->parent.rx_indicate(&(serial->parent), length);
1266*10465441SEvalZero                 }
1267*10465441SEvalZero             }
1268*10465441SEvalZero             break;
1269*10465441SEvalZero         }
1270*10465441SEvalZero #endif /* RT_SERIAL_USING_DMA */
1271*10465441SEvalZero     }
1272*10465441SEvalZero }
1273*10465441SEvalZero 
1274