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