From afe3b16106292a36b442691a62dab7315bb4b065 Mon Sep 17 00:00:00 2001 From: armink Date: Fri, 17 Mar 2017 13:25:19 +0800 Subject: [PATCH] [DeviceDrivers] Enhanced serial DMA rx driver reliability. --- components/drivers/serial/serial.c | 78 ++++++++++++++++++------------ 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index c55406bcd6..cc6a8bfe91 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -166,14 +166,15 @@ rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t * * * @return length */ -static rt_size_t rt_dma_calc_recved_len(struct rt_serial_device *serial) { - static rt_size_t rx_length; - struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; +static rt_size_t rt_dma_calc_recved_len(struct rt_serial_device *serial) +{ + rt_size_t rx_length; + struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; RT_ASSERT(rx_fifo != RT_NULL); - rx_length = (rx_fifo->put_index >= rx_fifo->get_index)? (rx_fifo->put_index - rx_fifo->get_index): - (serial->config.bufsz - (rx_fifo->get_index - rx_fifo->put_index)); + rx_length = (rx_fifo->put_index >= rx_fifo->get_index) ? (rx_fifo->put_index - rx_fifo->get_index): + (serial->config.bufsz - (rx_fifo->get_index - rx_fifo->put_index)); return rx_length; } @@ -183,14 +184,16 @@ static rt_size_t rt_dma_calc_recved_len(struct rt_serial_device *serial) { * @param serial serial device * @param len get data length for this operate */ -static void rt_dma_recv_update_get_index(struct rt_serial_device *serial, rt_size_t len) { - struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; +static void rt_dma_recv_update_get_index(struct rt_serial_device *serial, rt_size_t len) +{ + struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; RT_ASSERT(rx_fifo != RT_NULL); RT_ASSERT(len <= rt_dma_calc_recved_len(serial)); rx_fifo->get_index += len; - if (rx_fifo->get_index > serial->config.bufsz ) { + if (rx_fifo->get_index > serial->config.bufsz) + { rx_fifo->get_index -= serial->config.bufsz; } } @@ -201,37 +204,41 @@ static void rt_dma_recv_update_get_index(struct rt_serial_device *serial, rt_siz * @param serial serial device * @param len received length for this transmit */ -static void rt_dma_recv_update_put_index(struct rt_serial_device *serial, rt_size_t len) { +static void rt_dma_recv_update_put_index(struct rt_serial_device *serial, rt_size_t len) +{ struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; - rt_size_t i; RT_ASSERT(rx_fifo != RT_NULL); - if (rx_fifo->get_index <= rx_fifo->put_index) { + if (rx_fifo->get_index <= rx_fifo->put_index) + { rx_fifo->put_index += len; /* beyond the fifo end */ - if (rx_fifo->put_index >= serial->config.bufsz) { - for (i = 0; i <= len / serial->config.bufsz; i++) { - rx_fifo->put_index -= serial->config.bufsz; - } + if (rx_fifo->put_index >= serial->config.bufsz) + { + rx_fifo->put_index %= serial->config.bufsz; /* force overwrite get index */ - if (rx_fifo->put_index >= rx_fifo->get_index) { + if (rx_fifo->put_index >= rx_fifo->get_index) + { rx_fifo->get_index = rx_fifo->put_index + 1; } } - } else { + } + else + { rx_fifo->put_index += len; - if(rx_fifo->put_index >= rx_fifo->get_index) { + if (rx_fifo->put_index >= rx_fifo->get_index) + { /* beyond the fifo end */ - if(rx_fifo->put_index >= serial->config.bufsz) { - for (i = 0; i <= len / serial->config.bufsz; i++) { - rx_fifo->put_index -= serial->config.bufsz; - } + if (rx_fifo->put_index >= serial->config.bufsz) + { + rx_fifo->put_index %= serial->config.bufsz; } /* force overwrite get index */ rx_fifo->get_index = rx_fifo->put_index + 1; } } + if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0; } /* @@ -607,17 +614,17 @@ static rt_err_t rt_serial_control(struct rt_device *dev, if (args) { struct serial_configure *pconfig = (struct serial_configure *) args; - if(pconfig->bufsz != serial->config.bufsz && serial->parent.ref_count) + if (pconfig->bufsz != serial->config.bufsz && serial->parent.ref_count) { /*can not change buffer size*/ return RT_EBUSY; } /* set serial configure */ serial->config = *pconfig; - if(serial->parent.ref_count) + if (serial->parent.ref_count) { /* serial device has been opened, to configure it */ - serial->ops->configure(serial, (struct serial_configure *)args); + serial->ops->configure(serial, (struct serial_configure *) args); } } @@ -754,25 +761,36 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event) case RT_SERIAL_EVENT_RX_DMADONE: { int length; + rt_base_t level; /* get DMA rx length */ length = (event & (~0xff)) >> 8; - if (serial->config.bufsz == 0) { + if (serial->config.bufsz == 0) + { struct rt_serial_rx_dma* rx_dma; - rx_dma = (struct rt_serial_rx_dma*)serial->serial_rx; + rx_dma = (struct rt_serial_rx_dma*) serial->serial_rx; RT_ASSERT(rx_dma != RT_NULL); RT_ASSERT(serial->parent.rx_indicate != RT_NULL); serial->parent.rx_indicate(&(serial->parent), length); rx_dma->activated = RT_FALSE; - } else { + } + else + { + /* disable interrupt */ + level = rt_hw_interrupt_disable(); /* update fifo put index */ rt_dma_recv_update_put_index(serial, length); + /* calculate received total length */ + length = rt_dma_calc_recved_len(serial); + /* enable interrupt */ + rt_hw_interrupt_enable(level); /* invoke callback */ - if (serial->parent.rx_indicate != RT_NULL) { - serial->parent.rx_indicate(&(serial->parent), rt_dma_calc_recved_len(serial)); + if (serial->parent.rx_indicate != RT_NULL) + { + serial->parent.rx_indicate(&(serial->parent), length); } } break;