From f82191db8b9115379da05be91f7ac14e1d8bd4af Mon Sep 17 00:00:00 2001 From: JasonJiaJie Date: Tue, 7 Nov 2017 10:45:02 +0800 Subject: [PATCH 1/5] [DeviceDriver][serial]Fix data bits error issue when using tcsetattr to set uart parameters. data bits should get from CSIZE. --- components/drivers/serial/serial.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index 52dd65e17b..7ebec7a7b3 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -32,6 +32,7 @@ * 2015-11-10 bernard fix the poll rx issue when there is no data. * 2016-05-10 armink add fifo mode to DMA rx when serial->config.bufsz != 0. * 2017-01-19 aubr.cool prevent change serial rx bufsz when serial is opened. + * 2017-11-07 JasonJia fix data bits error issue when using tcsetattr. */ #include @@ -932,13 +933,24 @@ static rt_err_t rt_serial_control(struct rt_device *dev, baudrate = _get_baudrate(cfgetospeed(tio)); config.baud_rate = baudrate; - if (tio->c_cflag & CS6) config.data_bits = DATA_BITS_6; - else if (tio->c_cflag & CS7) config.data_bits = DATA_BITS_7; - else if (tio->c_cflag & CS8) config.data_bits = DATA_BITS_8; - else config.data_bits = DATA_BITS_5; + switch (tio->c_cflag & CSIZE) + { + case CS5: + config.data_bits = DATA_BITS_5; + break; + case CS6: + config.data_bits = DATA_BITS_6; + break; + case CS7: + config.data_bits = DATA_BITS_7; + break; + default: + config.data_bits = DATA_BITS_8; + break; + } - if (tio->c_cflag & CSTOPB) config.data_bits = STOP_BITS_2; - else config.data_bits = STOP_BITS_1; + if (tio->c_cflag & CSTOPB) config.stop_bits = STOP_BITS_2; + else config.stop_bits = STOP_BITS_1; if (tio->c_cflag & PARENB) { From 20dbd2dd0aefa5b69c848c78de87e7fa6470b242 Mon Sep 17 00:00:00 2001 From: JasonJiaJie Date: Wed, 8 Nov 2017 09:38:18 +0800 Subject: [PATCH 2/5] [Driver][Pipe]Memory leak issue when close a pipe. There is a memory leak issue when close a pipe. --- components/drivers/src/pipe.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/drivers/src/pipe.c b/components/drivers/src/pipe.c index 0553c500ee..83f47cc27a 100644 --- a/components/drivers/src/pipe.c +++ b/components/drivers/src/pipe.c @@ -20,6 +20,7 @@ * Change Logs: * Date Author Notes * 2012-09-30 Bernard first version. + * 2017-11-08 JasonJiaJie fix memory leak issue when close a pipe. */ #include #include @@ -102,7 +103,7 @@ static int pipe_fops_close(struct dfs_fd *fd) if (device->ref_count == 1) { - rt_free(pipe->fifo); + rt_ringbuffer_destroy(pipe->fifo); pipe->fifo = RT_NULL; } device->ref_count --; From b7471649427f409dec0350389223f59e39f997f3 Mon Sep 17 00:00:00 2001 From: JasonJiaJie Date: Wed, 15 Nov 2017 09:40:18 +0800 Subject: [PATCH 3/5] [DeviceDriver][serial] 1.Fix poll rx issue when data is full. 2.Add TCFLSH and FIONREAD support. --- components/drivers/serial/serial.c | 142 ++++++++++++++++++++++------- 1 file changed, 111 insertions(+), 31 deletions(-) diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index 7ebec7a7b3..a5d90b9b99 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -33,6 +33,8 @@ * 2016-05-10 armink add fifo mode to DMA rx when serial->config.bufsz != 0. * 2017-01-19 aubr.cool prevent change serial rx bufsz when serial is opened. * 2017-11-07 JasonJia fix data bits error issue when using tcsetattr. + * 2017-11-15 JasonJia fix poll rx issue when data is full. + * add TCFLSH and FIONREAD support. */ #include @@ -141,7 +143,7 @@ static int serial_fops_read(struct dfs_fd *fd, void *buf, size_t count) device = (rt_device_t)fd->data; - do + do { size = rt_device_read(device, -1, buf, count); if (size <= 0) @@ -173,7 +175,7 @@ static int serial_fops_poll(struct dfs_fd *fd, struct rt_pollreq *req) int flags = 0; rt_device_t device; struct rt_serial_device *serial; - + device = (rt_device_t)fd->data; RT_ASSERT(device != RT_NULL); @@ -187,11 +189,11 @@ static int serial_fops_poll(struct dfs_fd *fd, struct rt_pollreq *req) struct rt_serial_rx_fifo* rx_fifo; rt_poll_add(&(device->wait_queue), req); - + rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx; level = rt_hw_interrupt_disable(); - if (rx_fifo->get_index != rx_fifo->put_index) + if ((rx_fifo->get_index != rx_fifo->put_index) || (rx_fifo->get_index == rx_fifo->put_index && rx_fifo->is_full == RT_TRUE)) mask |= POLLIN; rt_hw_interrupt_enable(level); } @@ -199,7 +201,7 @@ static int serial_fops_poll(struct dfs_fd *fd, struct rt_pollreq *req) return mask; } -const static struct dfs_file_ops _serial_fops = +const static struct dfs_file_ops _serial_fops = { serial_fops_open, serial_fops_close, @@ -286,19 +288,25 @@ rt_inline int _serial_int_rx(struct rt_serial_device *serial, rt_uint8_t *data, /* disable interrupt */ level = rt_hw_interrupt_disable(); - if (rx_fifo->get_index != rx_fifo->put_index) - { - ch = rx_fifo->buffer[rx_fifo->get_index]; - rx_fifo->get_index += 1; - if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0; - } - else + + /* there's no data: */ + if ((rx_fifo->get_index == rx_fifo->put_index) && (rx_fifo->is_full == RT_FALSE)) { /* no data, enable interrupt and break out */ rt_hw_interrupt_enable(level); break; } + /* otherwise there's the data: */ + ch = rx_fifo->buffer[rx_fifo->get_index]; + rx_fifo->get_index += 1; + if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0; + + if (rx_fifo->is_full == RT_TRUE) + { + rx_fifo->is_full = RT_FALSE; + } + /* enable interrupt */ rt_hw_interrupt_enable(level); @@ -334,6 +342,71 @@ rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t * return size - length; } +static rt_size_t _serial_fifo_calc_recved_len(struct rt_serial_device *serial) +{ + struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; + + RT_ASSERT(rx_fifo != RT_NULL); + + if (rx_fifo->put_index == rx_fifo->get_index) + { + return (rx_fifo->is_full == RT_FALSE ? 0 : serial->config.bufsz); + } + else + { + if (rx_fifo->put_index > rx_fifo->get_index) + { + return rx_fifo->put_index - rx_fifo->get_index; + } + else + { + return serial->config.bufsz - (rx_fifo->get_index - rx_fifo->put_index); + } + } +} + +static void _serial_flush(struct rt_serial_device *serial, int queue) +{ + int ch = -1; + struct rt_serial_rx_fifo *rx_fifo = RT_NULL; + struct rt_device *device = RT_NULL; + + RT_ASSERT(serial != RT_NULL); + + device = &(serial->parent); + rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; + + switch(queue) + { + case TCIFLUSH: + case TCIOFLUSH: + + RT_ASSERT(rx_fifo != RT_NULL); + + if((device->open_flag & RT_DEVICE_FLAG_INT_RX) || (device->open_flag & RT_DEVICE_FLAG_DMA_RX)) + { + RT_ASSERT(RT_NULL != rx_fifo); + rt_memset(rx_fifo->buffer, 0, serial->config.bufsz); + rx_fifo->put_index = 0; + rx_fifo->get_index = 0; + rx_fifo->is_full = RT_FALSE; + } + else + { + while (1) + { + ch = serial->ops->getc(serial); + if (ch == -1) break; + } + } + + break; + + case TCOFLUSH: + break; + } + +} /** * Calculate DMA received data length. * @@ -343,25 +416,11 @@ rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t * */ static rt_size_t rt_dma_calc_recved_len(struct rt_serial_device *serial) { - struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; - - RT_ASSERT(rx_fifo != RT_NULL); - - if (rx_fifo->put_index > rx_fifo->get_index) - return rx_fifo->put_index - rx_fifo->get_index; - else if (rx_fifo->put_index < rx_fifo->get_index) - return serial->config.bufsz - (rx_fifo->get_index - rx_fifo->put_index); - else - { - if (rx_fifo->is_full) - return serial->config.bufsz; - else - return 0; - } + return _serial_fifo_calc_recved_len(serial); } /** - * Read data finish by DMA mode then update the gut index for receive fifo. + * Read data finish by DMA mode then update the get index for receive fifo. * * @param serial serial device * @param len get data length for this operate @@ -552,7 +611,7 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) RT_ASSERT(dev != RT_NULL); serial = (struct rt_serial_device *)dev; - dbg_log(DBG_LOG, "open serial device: 0x%08x with open flag: 0x%04x\n", + dbg_log(DBG_LOG, "open serial device: 0x%08x with open flag: 0x%04x\n", dev, oflag); /* check device flag with the open flag */ if ((oflag & RT_DEVICE_FLAG_DMA_RX) && !(dev->flag & RT_DEVICE_FLAG_DMA_RX)) @@ -612,6 +671,7 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) rt_memset(rx_fifo->buffer, 0, serial->config.bufsz); rx_fifo->put_index = 0; rx_fifo->get_index = 0; + rx_fifo->is_full = RT_FALSE; serial->serial_rx = rx_fifo; dev->open_flag |= RT_DEVICE_FLAG_INT_RX; @@ -790,13 +850,13 @@ static rt_size_t rt_serial_write(struct rt_device *dev, } #ifdef RT_USING_POSIX_TERMIOS -struct speed_baudrate_item +struct speed_baudrate_item { speed_t speed; int baudrate; }; -const static struct speed_baudrate_item _tbl[] = +const static struct speed_baudrate_item _tbl[] = { {B2400, BAUD_RATE_2400}, {B4800, BAUD_RATE_4800}, @@ -963,11 +1023,30 @@ static rt_err_t rt_serial_control(struct rt_device *dev, } break; case TCFLSH: + { + int queue = *(int *)args; + + _serial_flush(serial, queue); + } + break; case TCXONC: break; #endif +#ifdef RT_USING_POSIX + case FIONREAD: + { + rt_size_t recved = 0; + rt_base_t level; + level = rt_hw_interrupt_disable(); + recved = _serial_fifo_calc_recved_len(serial); + rt_hw_interrupt_enable(level); + + *(rt_size_t *)args = recved; + } + break; +#endif default : /* control device */ ret = serial->ops->control(serial, cmd, args); @@ -1046,6 +1125,7 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event) if (rx_fifo->put_index == rx_fifo->get_index) { rx_fifo->get_index += 1; + rx_fifo->is_full = RT_TRUE; if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0; } From 9f745c6aafd8c3fcf300dfebe87bedafb8bb2887 Mon Sep 17 00:00:00 2001 From: JasonJiaJie Date: Wed, 15 Nov 2017 09:41:06 +0800 Subject: [PATCH 4/5] [POSIX] 1.Fix parameter error. --- components/libc/termios/posix_termios.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/libc/termios/posix_termios.c b/components/libc/termios/posix_termios.c index 4ec513ef1d..72afa8188d 100644 --- a/components/libc/termios/posix_termios.c +++ b/components/libc/termios/posix_termios.c @@ -111,12 +111,12 @@ int tcsendbreak(int fd, int dur) int tcflush(int fd, int queue) { - return ioctl(fd, TCFLSH, (void*)queue); + return ioctl(fd, TCFLSH, (void*)&queue); } int tcflow(int fd, int action) { - return ioctl(fd, TCXONC, (void*)action); + return ioctl(fd, TCXONC, (void*)&action); } /** From b085bba04c41b82543e213a67042736f73600dbb Mon Sep 17 00:00:00 2001 From: JasonJiaJie Date: Wed, 15 Nov 2017 13:17:42 +0800 Subject: [PATCH 5/5] [Posix]termios parameter issue. --- components/drivers/serial/serial.c | 2 +- components/libc/termios/posix_termios.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index a5d90b9b99..149cfaff3e 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -1024,7 +1024,7 @@ static rt_err_t rt_serial_control(struct rt_device *dev, break; case TCFLSH: { - int queue = *(int *)args; + int queue = (int)args; _serial_flush(serial, queue); } diff --git a/components/libc/termios/posix_termios.c b/components/libc/termios/posix_termios.c index 72afa8188d..4ec513ef1d 100644 --- a/components/libc/termios/posix_termios.c +++ b/components/libc/termios/posix_termios.c @@ -111,12 +111,12 @@ int tcsendbreak(int fd, int dur) int tcflush(int fd, int queue) { - return ioctl(fd, TCFLSH, (void*)&queue); + return ioctl(fd, TCFLSH, (void*)queue); } int tcflow(int fd, int action) { - return ioctl(fd, TCXONC, (void*)&action); + return ioctl(fd, TCXONC, (void*)action); } /**