From 8a44c7dbfb1cd76eda0e5f76ef7ef67b1089ebf1 Mon Sep 17 00:00:00 2001 From: heyuanjie87 Date: Mon, 1 Sep 2014 23:43:50 +0800 Subject: [PATCH] [Serial] BUG Fix: data be send twice in mode that other than polling --- components/drivers/serial/serial.c | 728 +++++++++++++++-------------- 1 file changed, 365 insertions(+), 363 deletions(-) diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index 776316baf5..f04b1df4f4 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -37,48 +37,48 @@ */ rt_inline int _serial_poll_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length) { - int ch; - int size; - - RT_ASSERT(serial != RT_NULL); - size = length; + int ch; + int size; + + RT_ASSERT(serial != RT_NULL); + size = length; - while (length) - { - ch = serial->ops->getc(serial); - *data = ch; - data ++; length --; + while (length) + { + ch = serial->ops->getc(serial); + *data = ch; + data ++; length --; - if (ch == '\n') break; - } + if (ch == '\n') break; + } - return size - length; + return size - length; } rt_inline int _serial_poll_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length) { - int size; - RT_ASSERT(serial != RT_NULL); + int size; + RT_ASSERT(serial != RT_NULL); - size = length; - while (length) - { - /* - * to be polite with serial console add a line feed - * to the carriage return character - */ - if (*data == '\n' && (serial->parent.flag & RT_DEVICE_FLAG_STREAM)) - { - serial->ops->putc(serial, '\r'); - } - - serial->ops->putc(serial, *data); - - ++ data; - -- length; - } + size = length; + while (length) + { + /* + * to be polite with serial console add a line feed + * to the carriage return character + */ + if (*data == '\n' && (serial->parent.flag & RT_DEVICE_FLAG_STREAM)) + { + serial->ops->putc(serial, '\r'); + } + + serial->ops->putc(serial, *data); + + ++ data; + -- length; + } - return size - length; + return size - length; } /* @@ -86,69 +86,69 @@ rt_inline int _serial_poll_tx(struct rt_serial_device *serial, const rt_uint8_t */ rt_inline int _serial_int_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length) { - int size; - struct rt_serial_rx_fifo* rx_fifo; + int size; + struct rt_serial_rx_fifo* rx_fifo; - RT_ASSERT(serial != RT_NULL); - size = length; - - rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx; - RT_ASSERT(rx_fifo != RT_NULL); + RT_ASSERT(serial != RT_NULL); + size = length; + + rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); - /* read from software FIFO */ - while (length) - { - int ch; - rt_base_t level; + /* read from software FIFO */ + while (length) + { + int ch; + rt_base_t level; - /* 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 - { - /* no data, enable interrupt and break out */ - rt_hw_interrupt_enable(level); - break; - } + /* 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 + { + /* no data, enable interrupt and break out */ + rt_hw_interrupt_enable(level); + break; + } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + /* enable interrupt */ + rt_hw_interrupt_enable(level); - *data = ch & 0xff; - data ++; length --; - } + *data = ch & 0xff; + data ++; length --; + } - return size - length; + return size - length; } rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length) { - int size; - struct rt_serial_tx_fifo *tx; - - RT_ASSERT(serial != RT_NULL); + int size; + struct rt_serial_tx_fifo *tx; + + RT_ASSERT(serial != RT_NULL); - size = length; - tx = (struct rt_serial_tx_fifo*) serial->serial_tx; - RT_ASSERT(tx != RT_NULL); + size = length; + tx = (struct rt_serial_tx_fifo*) serial->serial_tx; + RT_ASSERT(tx != RT_NULL); - while (length) - { - if (serial->ops->putc(serial, *(char*)data) == -1) - { - rt_completion_wait(&(tx->completion), RT_WAITING_FOREVER); - continue; - } + while (length) + { + if (serial->ops->putc(serial, *(char*)data) == -1) + { + rt_completion_wait(&(tx->completion), RT_WAITING_FOREVER); + continue; + } - data ++; length --; - } + data ++; length --; + } - return size - length; + return size - length; } /* @@ -156,61 +156,61 @@ rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t * */ rt_inline int _serial_dma_rx(struct rt_serial_device *serial, rt_uint8_t *data, int length) { - rt_base_t level; - int result = RT_EOK; - struct rt_serial_rx_dma *rx_dma; + rt_base_t level; + int result = RT_EOK; + struct rt_serial_rx_dma *rx_dma; - RT_ASSERT((serial != RT_NULL) && (data != RT_NULL)); - rx_dma = (struct rt_serial_rx_dma*)serial->serial_rx; - RT_ASSERT(rx_dma != RT_NULL); + RT_ASSERT((serial != RT_NULL) && (data != RT_NULL)); + rx_dma = (struct rt_serial_rx_dma*)serial->serial_rx; + RT_ASSERT(rx_dma != RT_NULL); - level = rt_hw_interrupt_disable(); - if (rx_dma->activated != RT_TRUE) - { - rx_dma->activated = RT_TRUE; - serial->ops->dma_transmit(serial, data, length, RT_SERIAL_DMA_RX); - } - else result = -RT_EBUSY; - rt_hw_interrupt_enable(level); + level = rt_hw_interrupt_disable(); + if (rx_dma->activated != RT_TRUE) + { + rx_dma->activated = RT_TRUE; + serial->ops->dma_transmit(serial, data, length, RT_SERIAL_DMA_RX); + } + else result = -RT_EBUSY; + rt_hw_interrupt_enable(level); - if (result == RT_EOK) return length; + if (result == RT_EOK) return length; - rt_set_errno(result); - return 0; + rt_set_errno(result); + return 0; } rt_inline int _serial_dma_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length) { - rt_base_t level; - rt_err_t result; - struct rt_serial_tx_dma *tx_dma; + rt_base_t level; + rt_err_t result; + struct rt_serial_tx_dma *tx_dma; - tx_dma = (struct rt_serial_tx_dma*)(serial->serial_tx); - - result = rt_data_queue_push(&(tx_dma->data_queue), data, length, RT_WAITING_FOREVER); - if (result == RT_EOK) - { - level = rt_hw_interrupt_disable(); - if (tx_dma->activated != RT_TRUE) - { - tx_dma->activated = RT_TRUE; - rt_hw_interrupt_enable(level); + tx_dma = (struct rt_serial_tx_dma*)(serial->serial_tx); + + result = rt_data_queue_push(&(tx_dma->data_queue), data, length, RT_WAITING_FOREVER); + if (result == RT_EOK) + { + level = rt_hw_interrupt_disable(); + if (tx_dma->activated != RT_TRUE) + { + tx_dma->activated = RT_TRUE; + rt_hw_interrupt_enable(level); - /* make a DMA transfer */ - serial->ops->dma_transmit(serial, data, length, RT_SERIAL_DMA_TX); - } - else - { - rt_hw_interrupt_enable(level); - } + /* make a DMA transfer */ + serial->ops->dma_transmit(serial, data, length, RT_SERIAL_DMA_TX); + } + else + { + rt_hw_interrupt_enable(level); + } - return length; - } - else - { - rt_set_errno(result); - return 0; - } + return length; + } + else + { + rt_set_errno(result); + return 0; + } } /* RT-Thread Device Interface */ @@ -225,15 +225,15 @@ static rt_err_t rt_serial_init(struct rt_device *dev) RT_ASSERT(dev != RT_NULL); serial = (struct rt_serial_device *)dev; - /* initialize rx/tx */ - serial->serial_rx = RT_NULL; - serial->serial_tx = RT_NULL; + /* initialize rx/tx */ + serial->serial_rx = RT_NULL; + serial->serial_tx = RT_NULL; - /* apply configuration */ - if (serial->ops->configure) - result = serial->ops->configure(serial, &serial->config); + /* apply configuration */ + if (serial->ops->configure) + result = serial->ops->configure(serial, &serial->config); - return result; + return result; } static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) @@ -243,89 +243,89 @@ 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; - /* 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; - 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)) - return -RT_EIO; + /* 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; + 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)) + return -RT_EIO; - /* get open flags */ - dev->open_flag = oflag & 0xff; - - /* initialize the Rx/Tx structure according to open flag */ - if (serial->serial_rx == RT_NULL) - { - if (oflag & RT_DEVICE_FLAG_DMA_RX) - { - struct rt_serial_rx_dma* rx_dma; + /* get open flags */ + dev->open_flag = oflag & 0xff; + + /* initialize the Rx/Tx structure according to open flag */ + if (serial->serial_rx == RT_NULL) + { + if (oflag & RT_DEVICE_FLAG_DMA_RX) + { + struct rt_serial_rx_dma* rx_dma; - rx_dma = (struct rt_serial_rx_dma*) rt_malloc (sizeof(struct rt_serial_rx_dma)); - RT_ASSERT(rx_dma != RT_NULL); - rx_dma->activated = RT_FALSE; + rx_dma = (struct rt_serial_rx_dma*) rt_malloc (sizeof(struct rt_serial_rx_dma)); + RT_ASSERT(rx_dma != RT_NULL); + rx_dma->activated = RT_FALSE; - serial->serial_rx = rx_dma; - dev->open_flag |= RT_DEVICE_FLAG_DMA_RX; - } - else if (oflag & RT_DEVICE_FLAG_INT_RX) - { - struct rt_serial_rx_fifo* rx_fifo; + serial->serial_rx = rx_dma; + 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, RT_SERIAL_RB_BUFSZ); - rx_fifo->put_index = 0; - rx_fifo->get_index = 0; + 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, RT_SERIAL_RB_BUFSZ); + rx_fifo->put_index = 0; + rx_fifo->get_index = 0; - 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); - } - else - { - serial->serial_rx = RT_NULL; - } - } + 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); + } + else + { + serial->serial_rx = RT_NULL; + } + } - if (serial->serial_tx == RT_NULL) - { - if (oflag & RT_DEVICE_FLAG_DMA_TX) - { - struct rt_serial_tx_dma* tx_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); - - rt_data_queue_init(&(tx_dma->data_queue), 8, 4, RT_NULL); - serial->serial_tx = tx_dma; + tx_dma = (struct rt_serial_tx_dma*) rt_malloc (sizeof(struct rt_serial_tx_dma)); + RT_ASSERT(tx_dma != RT_NULL); + + 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) - { - struct rt_serial_tx_fifo *tx_fifo; + dev->open_flag |= RT_DEVICE_FLAG_DMA_TX; + } + else if (oflag & RT_DEVICE_FLAG_INT_TX) + { + struct rt_serial_tx_fifo *tx_fifo; - tx_fifo = (struct rt_serial_tx_fifo*) rt_malloc(sizeof(struct rt_serial_tx_fifo)); - RT_ASSERT(tx_fifo != RT_NULL); + tx_fifo = (struct rt_serial_tx_fifo*) rt_malloc(sizeof(struct rt_serial_tx_fifo)); + RT_ASSERT(tx_fifo != RT_NULL); - rt_completion_init(&(tx_fifo->completion)); - serial->serial_tx = tx_fifo; + rt_completion_init(&(tx_fifo->completion)); + serial->serial_tx = tx_fifo; - dev->open_flag |= RT_DEVICE_FLAG_INT_TX; - /* configure low level device */ - serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_TX); - } - else - { - serial->serial_tx = RT_NULL; - } - } + dev->open_flag |= RT_DEVICE_FLAG_INT_TX; + /* configure low level device */ + serial->ops->control(serial, RT_DEVICE_CTRL_SET_INT, (void *)RT_DEVICE_FLAG_INT_TX); + } + else + { + serial->serial_tx = RT_NULL; + } + } return RT_EOK; } @@ -337,58 +337,58 @@ static rt_err_t rt_serial_close(struct rt_device *dev) RT_ASSERT(dev != RT_NULL); serial = (struct rt_serial_device *)dev; - /* this device has more reference count */ - if (dev->ref_count > 1) return RT_EOK; - - if (dev->open_flag & RT_DEVICE_FLAG_INT_RX) - { - struct rt_serial_rx_fifo* rx_fifo; + /* this device has more reference count */ + if (dev->ref_count > 1) return RT_EOK; + + if (dev->open_flag & RT_DEVICE_FLAG_INT_RX) + { + struct rt_serial_rx_fifo* rx_fifo; - rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx; - RT_ASSERT(rx_fifo != RT_NULL); + rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); - rt_free(rx_fifo); - serial->serial_rx = RT_NULL; - dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX; - /* configure low level device */ - serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX); - } - else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX) - { - struct rt_serial_rx_dma* rx_dma; + rt_free(rx_fifo); + serial->serial_rx = RT_NULL; + dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX; + /* configure low level device */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX); + } + else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX) + { + struct rt_serial_rx_dma* rx_dma; - rx_dma = (struct rt_serial_rx_dma*)serial->serial_tx; - RT_ASSERT(rx_dma != RT_NULL); + rx_dma = (struct rt_serial_rx_dma*)serial->serial_tx; + RT_ASSERT(rx_dma != RT_NULL); - rt_free(rx_dma); - serial->serial_rx = RT_NULL; - dev->open_flag &= ~RT_DEVICE_FLAG_DMA_RX; - } + rt_free(rx_dma); + serial->serial_rx = RT_NULL; + dev->open_flag &= ~RT_DEVICE_FLAG_DMA_RX; + } - if (dev->open_flag & RT_DEVICE_FLAG_INT_TX) - { - struct rt_serial_tx_fifo* tx_fifo; + if (dev->open_flag & RT_DEVICE_FLAG_INT_TX) + { + struct rt_serial_tx_fifo* tx_fifo; - tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_rx; - RT_ASSERT(tx_fifo != RT_NULL); + tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_rx; + RT_ASSERT(tx_fifo != RT_NULL); - rt_free(tx_fifo); - serial->serial_tx = RT_NULL; - dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX; - /* configure low level device */ - serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX); - } - else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX) - { - struct rt_serial_tx_dma* tx_dma; + rt_free(tx_fifo); + serial->serial_tx = RT_NULL; + dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX; + /* configure low level device */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX); + } + else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX) + { + struct rt_serial_tx_dma* tx_dma; - tx_dma = (struct rt_serial_tx_dma*)serial->serial_tx; - RT_ASSERT(tx_dma != RT_NULL); + tx_dma = (struct rt_serial_tx_dma*)serial->serial_tx; + RT_ASSERT(tx_dma != RT_NULL); - rt_free(tx_dma); - serial->serial_tx = RT_NULL; - dev->open_flag &= ~RT_DEVICE_FLAG_DMA_TX; - } + rt_free(tx_dma); + serial->serial_tx = RT_NULL; + dev->open_flag &= ~RT_DEVICE_FLAG_DMA_TX; + } return RT_EOK; } @@ -405,16 +405,16 @@ static rt_size_t rt_serial_read(struct rt_device *dev, serial = (struct rt_serial_device *)dev; - if (dev->open_flag & RT_DEVICE_FLAG_INT_RX) - { - return _serial_int_rx(serial, buffer, size); - } - else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX) - { - return _serial_dma_rx(serial, buffer, size); - } + if (dev->open_flag & RT_DEVICE_FLAG_INT_RX) + { + return _serial_int_rx(serial, buffer, size); + } + else if (dev->open_flag & RT_DEVICE_FLAG_DMA_RX) + { + return _serial_dma_rx(serial, buffer, size); + } - return _serial_poll_rx(serial, buffer, size); + return _serial_poll_rx(serial, buffer, size); } static rt_size_t rt_serial_write(struct rt_device *dev, @@ -429,16 +429,18 @@ static rt_size_t rt_serial_write(struct rt_device *dev, serial = (struct rt_serial_device *)dev; - if (dev->open_flag & RT_DEVICE_FLAG_INT_TX) - { - _serial_int_tx(serial, buffer, size); - } - else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX) - { - _serial_dma_tx(serial, buffer, size); - } - - return _serial_poll_tx(serial, buffer, size); + if (dev->open_flag & RT_DEVICE_FLAG_INT_TX) + { + return _serial_int_tx(serial, buffer, size); + } + else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX) + { + return _serial_dma_tx(serial, buffer, size); + } + else + { + return _serial_poll_tx(serial, buffer, size); + } } static rt_err_t rt_serial_control(struct rt_device *dev, @@ -508,106 +510,106 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial, /* ISR for serial interrupt */ void rt_hw_serial_isr(struct rt_serial_device *serial, int event) { - switch (event & 0xff) - { - case RT_SERIAL_EVENT_RX_IND: - { - int ch = -1; - rt_base_t level; - struct rt_serial_rx_fifo* rx_fifo; + switch (event & 0xff) + { + case RT_SERIAL_EVENT_RX_IND: + { + int ch = -1; + rt_base_t level; + struct rt_serial_rx_fifo* rx_fifo; - rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx; - RT_ASSERT(rx_fifo != RT_NULL); - - /* interrupt mode receive */ - RT_ASSERT(serial->parent.open_flag & RT_DEVICE_FLAG_INT_RX); - - while (1) - { - ch = serial->ops->getc(serial); - if (ch == -1) break; + rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + + /* interrupt mode receive */ + RT_ASSERT(serial->parent.open_flag & RT_DEVICE_FLAG_INT_RX); + + while (1) + { + ch = serial->ops->getc(serial); + if (ch == -1) break; - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - - rx_fifo->buffer[rx_fifo->put_index] = ch; - rx_fifo->put_index += 1; - if (rx_fifo->put_index >= serial->config.bufsz) rx_fifo->put_index = 0; - - /* if the next position is read index, discard this 'read char' */ - if (rx_fifo->put_index == rx_fifo->get_index) - { - rx_fifo->get_index += 1; - if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0; - } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - } - - /* invoke callback */ - if (serial->parent.rx_indicate != RT_NULL) - { - rt_size_t rx_length; - - /* get rx length */ - level = rt_hw_interrupt_disable(); - 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)); - rt_hw_interrupt_enable(level); + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + + rx_fifo->buffer[rx_fifo->put_index] = ch; + rx_fifo->put_index += 1; + if (rx_fifo->put_index >= serial->config.bufsz) rx_fifo->put_index = 0; + + /* if the next position is read index, discard this 'read char' */ + if (rx_fifo->put_index == rx_fifo->get_index) + { + rx_fifo->get_index += 1; + if (rx_fifo->get_index >= serial->config.bufsz) rx_fifo->get_index = 0; + } + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + } + + /* invoke callback */ + if (serial->parent.rx_indicate != RT_NULL) + { + rt_size_t rx_length; + + /* get rx length */ + level = rt_hw_interrupt_disable(); + 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)); + rt_hw_interrupt_enable(level); - serial->parent.rx_indicate(&serial->parent, rx_length); - } - break; - } - case RT_SERIAL_EVENT_TX_DONE: - { - struct rt_serial_tx_fifo* tx_fifo; + serial->parent.rx_indicate(&serial->parent, rx_length); + } + break; + } + case RT_SERIAL_EVENT_TX_DONE: + { + struct rt_serial_tx_fifo* tx_fifo; - tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_tx; - rt_completion_done(&(tx_fifo->completion)); - break; - } - 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; + tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_tx; + rt_completion_done(&(tx_fifo->completion)); + break; + } + 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; - tx_dma = (struct rt_serial_tx_dma*) serial->serial_tx; - - rt_data_queue_pop(&(tx_dma->data_queue), &last_data_ptr, &data_size, 0); - if (rt_data_queue_peak(&(tx_dma->data_queue), &data_ptr, &data_size) == RT_EOK) - { - /* transmit next data node */ - tx_dma->activated = RT_TRUE; - serial->ops->dma_transmit(serial, data_ptr, data_size, RT_SERIAL_DMA_TX); - } - else - { - tx_dma->activated = RT_FALSE; - } - - /* invoke callback */ - if (serial->parent.tx_complete != RT_NULL) - { - serial->parent.tx_complete(&serial->parent, (void*)last_data_ptr); - } - break; - } - case RT_SERIAL_EVENT_RX_DMADONE: - { - int length; - struct rt_serial_rx_dma* rx_dma; + tx_dma = (struct rt_serial_tx_dma*) serial->serial_tx; + + rt_data_queue_pop(&(tx_dma->data_queue), &last_data_ptr, &data_size, 0); + if (rt_data_queue_peak(&(tx_dma->data_queue), &data_ptr, &data_size) == RT_EOK) + { + /* transmit next data node */ + tx_dma->activated = RT_TRUE; + serial->ops->dma_transmit(serial, data_ptr, data_size, RT_SERIAL_DMA_TX); + } + else + { + tx_dma->activated = RT_FALSE; + } + + /* invoke callback */ + if (serial->parent.tx_complete != RT_NULL) + { + serial->parent.tx_complete(&serial->parent, (void*)last_data_ptr); + } + break; + } + case RT_SERIAL_EVENT_RX_DMADONE: + { + int length; + struct rt_serial_rx_dma* rx_dma; - rx_dma = (struct rt_serial_rx_dma*)serial->serial_rx; - /* get DMA rx length */ - length = (event & (~0xff)) >> 8; - serial->parent.rx_indicate(&(serial->parent), length); - rx_dma->activated = RT_FALSE; - break; - } - } + rx_dma = (struct rt_serial_rx_dma*)serial->serial_rx; + /* get DMA rx length */ + length = (event & (~0xff)) >> 8; + serial->parent.rx_indicate(&(serial->parent), length); + rx_dma->activated = RT_FALSE; + break; + } + } }