From 5098c934d31a3fcff23648a78ec31f036108ef9e Mon Sep 17 00:00:00 2001 From: "chenchaoqun@rt-thread.com" Date: Sat, 8 Dec 2018 11:37:13 +0800 Subject: [PATCH] [add] DMA choice of serial --- components/drivers/Kconfig | 6 ++ components/drivers/serial/serial.c | 110 ++++++++++++++++++----------- 2 files changed, 73 insertions(+), 43 deletions(-) diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index 9e97aac3c3..d8dc5e7458 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -16,6 +16,12 @@ config RT_USING_SERIAL select RT_USING_DEVICE default y +if RT_USING_SERIAL + config RT_SERIAL_USING_DMA + bool "Enable serial DMA mode" + default y +endif + config RT_USING_CAN bool "Using CAN device drivers" default n diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index 959d8444c1..c5932df7d9 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -21,6 +21,7 @@ * 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. + * 2018-12-08 Ernest Chen add DMA choice */ #include @@ -328,6 +329,7 @@ rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t * return size - length; } +#if defined(RT_USING_POSIX) || defined(RT_SERIAL_USING_DMA) 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; @@ -350,7 +352,9 @@ static rt_size_t _serial_fifo_calc_recved_len(struct rt_serial_device *serial) } } } +#endif /* RT_USING_POSIX || RT_SERIAL_USING_DMA */ +#ifdef RT_SERIAL_USING_DMA /** * Calculate DMA received data length. * @@ -527,6 +531,7 @@ rt_inline int _serial_dma_tx(struct rt_serial_device *serial, const rt_uint8_t * return 0; } } +#endif /* RT_SERIAL_USING_DMA */ /* RT-Thread Device Interface */ /* @@ -561,11 +566,13 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) LOG_D("open serial device: 0x%08x with open flag: 0x%04x", dev, oflag); +#ifdef RT_SERIAL_USING_DMA /* check device flag with the open flag */ if ((oflag & RT_DEVICE_FLAG_DMA_RX) && !(dev->flag & RT_DEVICE_FLAG_DMA_RX)) return -RT_EIO; if ((oflag & RT_DEVICE_FLAG_DMA_TX) && !(dev->flag & RT_DEVICE_FLAG_DMA_TX)) return -RT_EIO; +#endif /* RT_SERIAL_USING_DMA */ if ((oflag & RT_DEVICE_FLAG_INT_RX) && !(dev->flag & RT_DEVICE_FLAG_INT_RX)) return -RT_EIO; if ((oflag & RT_DEVICE_FLAG_INT_TX) && !(dev->flag & RT_DEVICE_FLAG_INT_TX)) @@ -580,8 +587,27 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) /* initialize the Rx/Tx structure according to open flag */ if (serial->serial_rx == RT_NULL) - { - if (oflag & RT_DEVICE_FLAG_DMA_RX) + { + if (oflag & RT_DEVICE_FLAG_INT_RX) + { + struct rt_serial_rx_fifo* rx_fifo; + + rx_fifo = (struct rt_serial_rx_fifo*) rt_malloc (sizeof(struct rt_serial_rx_fifo) + + serial->config.bufsz); + RT_ASSERT(rx_fifo != RT_NULL); + rx_fifo->buffer = (rt_uint8_t*) (rx_fifo + 1); + 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; + /* configure low level device */ + serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); + } +#ifdef RT_SERIAL_USING_DMA + else if (oflag & RT_DEVICE_FLAG_DMA_RX) { if (serial->config.bufsz == 0) { struct rt_serial_rx_dma* rx_dma; @@ -608,24 +634,7 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) } dev->open_flag |= RT_DEVICE_FLAG_DMA_RX; } - else if (oflag & RT_DEVICE_FLAG_INT_RX) - { - struct rt_serial_rx_fifo* rx_fifo; - - rx_fifo = (struct rt_serial_rx_fifo*) rt_malloc (sizeof(struct rt_serial_rx_fifo) + - serial->config.bufsz); - RT_ASSERT(rx_fifo != RT_NULL); - rx_fifo->buffer = (rt_uint8_t*) (rx_fifo + 1); - 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; - /* configure low level device */ - serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_RX); - } +#endif /* RT_SERIAL_USING_DMA */ else { serial->serial_rx = RT_NULL; @@ -633,28 +642,17 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) } else { - if (oflag & RT_DEVICE_FLAG_DMA_RX) - dev->open_flag |= RT_DEVICE_FLAG_DMA_RX; - else if (oflag & RT_DEVICE_FLAG_INT_RX) + if (oflag & RT_DEVICE_FLAG_INT_RX) dev->open_flag |= RT_DEVICE_FLAG_INT_RX; +#ifdef RT_SERIAL_USING_DMA + else if (oflag & RT_DEVICE_FLAG_DMA_RX) + dev->open_flag |= RT_DEVICE_FLAG_DMA_RX; +#endif /* RT_SERIAL_USING_DMA */ } if (serial->serial_tx == RT_NULL) { - if (oflag & RT_DEVICE_FLAG_DMA_TX) - { - struct rt_serial_tx_dma* tx_dma; - - tx_dma = (struct rt_serial_tx_dma*) rt_malloc (sizeof(struct rt_serial_tx_dma)); - RT_ASSERT(tx_dma != RT_NULL); - tx_dma->activated = RT_FALSE; - - rt_data_queue_init(&(tx_dma->data_queue), 8, 4, RT_NULL); - serial->serial_tx = tx_dma; - - dev->open_flag |= RT_DEVICE_FLAG_DMA_TX; - } - else if (oflag & RT_DEVICE_FLAG_INT_TX) + if (oflag & RT_DEVICE_FLAG_INT_TX) { struct rt_serial_tx_fifo *tx_fifo; @@ -668,6 +666,21 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) /* configure low level device */ serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_TX); } +#ifdef RT_SERIAL_USING_DMA + else if (oflag & RT_DEVICE_FLAG_DMA_TX) + { + struct rt_serial_tx_dma* tx_dma; + + tx_dma = (struct rt_serial_tx_dma*) rt_malloc (sizeof(struct rt_serial_tx_dma)); + RT_ASSERT(tx_dma != RT_NULL); + tx_dma->activated = RT_FALSE; + + rt_data_queue_init(&(tx_dma->data_queue), 8, 4, RT_NULL); + serial->serial_tx = tx_dma; + + dev->open_flag |= RT_DEVICE_FLAG_DMA_TX; + } +#endif /* RT_SERIAL_USING_DMA */ else { serial->serial_tx = RT_NULL; @@ -675,10 +688,12 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) } else { - if (oflag & RT_DEVICE_FLAG_DMA_TX) - dev->open_flag |= RT_DEVICE_FLAG_DMA_TX; - else if (oflag & RT_DEVICE_FLAG_INT_TX) + if (oflag & RT_DEVICE_FLAG_INT_TX) dev->open_flag |= RT_DEVICE_FLAG_INT_TX; +#ifdef RT_SERIAL_USING_DMA + else if (oflag & RT_DEVICE_FLAG_DMA_TX) + dev->open_flag |= RT_DEVICE_FLAG_DMA_TX; +#endif /* RT_SERIAL_USING_DMA */ } /* set stream flag */ @@ -710,6 +725,7 @@ static rt_err_t rt_serial_close(struct rt_device *dev) /* configure low level device */ serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_RX); } +#ifdef RT_SERIAL_USING_DMA else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX) { if (serial->config.bufsz == 0) { @@ -732,7 +748,8 @@ static rt_err_t rt_serial_close(struct rt_device *dev) serial->serial_rx = RT_NULL; dev->open_flag &= ~RT_DEVICE_FLAG_DMA_RX; } - +#endif /* RT_SERIAL_USING_DMA */ + if (dev->open_flag & RT_DEVICE_FLAG_INT_TX) { struct rt_serial_tx_fifo* tx_fifo; @@ -746,6 +763,7 @@ static rt_err_t rt_serial_close(struct rt_device *dev) /* configure low level device */ serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX); } +#ifdef RT_SERIAL_USING_DMA else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX) { struct rt_serial_tx_dma* tx_dma; @@ -757,7 +775,7 @@ static rt_err_t rt_serial_close(struct rt_device *dev) serial->serial_tx = RT_NULL; dev->open_flag &= ~RT_DEVICE_FLAG_DMA_TX; } - +#endif /* RT_SERIAL_USING_DMA */ return RT_EOK; } @@ -777,10 +795,12 @@ static rt_size_t rt_serial_read(struct rt_device *dev, { return _serial_int_rx(serial, buffer, size); } +#ifdef RT_SERIAL_USING_DMA else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX) { return _serial_dma_rx(serial, buffer, size); } +#endif /* RT_SERIAL_USING_DMA */ return _serial_poll_rx(serial, buffer, size); } @@ -801,10 +821,12 @@ static rt_size_t rt_serial_write(struct rt_device *dev, { return _serial_int_tx(serial, buffer, size); } +#ifdef RT_SERIAL_USING_DMA else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX) { return _serial_dma_tx(serial, buffer, size); } +#endif /* RT_SERIAL_USING_DMA */ else { return _serial_poll_tx(serial, buffer, size); @@ -1181,12 +1203,13 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event) rt_completion_done(&(tx_fifo->completion)); break; } +#ifdef RT_SERIAL_USING_DMA case RT_SERIAL_EVENT_TX_DMADONE: { const void *data_ptr; rt_size_t data_size; const void *last_data_ptr; - struct rt_serial_tx_dma* tx_dma; + struct rt_serial_tx_dma *tx_dma; tx_dma = (struct rt_serial_tx_dma*) serial->serial_tx; @@ -1246,6 +1269,7 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event) } break; } +#endif /* RT_SERIAL_USING_DMA */ } }