diff --git a/components/drivers/usb/usbdevice/class/cdc_vcom.c b/components/drivers/usb/usbdevice/class/cdc_vcom.c index 336cfcb152..b6044b37a7 100644 --- a/components/drivers/usb/usbdevice/class/cdc_vcom.c +++ b/components/drivers/usb/usbdevice/class/cdc_vcom.c @@ -63,6 +63,7 @@ static struct ucdc_line_coding line_coding; #define CDC_BULKIN_MAXSIZE (CDC_TX_BUFSIZE / 8) #define CDC_TX_HAS_DATE 0x01 +#define CDC_TX_HAS_SPACE 0x02 struct vcom { @@ -693,23 +694,48 @@ static int _vcom_getc(struct rt_serial_device *serial) return result; } -static rt_size_t _vcom_tx(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size,int direction) + +static rt_size_t _vcom_rb_block_put(struct vcom *data, const rt_uint8_t *buf, rt_size_t size) { rt_uint32_t level; + rt_size_t put_len = 0; + rt_size_t w_ptr = 0; + rt_uint32_t res; + rt_size_t remain_size = size; + while (remain_size) + { + level = rt_hw_interrupt_disable(); + put_len = rt_ringbuffer_put(&data->tx_ringbuffer, (const rt_uint8_t *)&buf[w_ptr], remain_size); + rt_hw_interrupt_enable(level); + w_ptr += put_len; + remain_size -= put_len; + if (put_len == 0) + { + rt_event_recv(&data->tx_event, CDC_TX_HAS_SPACE, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + VCOM_TX_TIMEOUT, &res); + } + else + { + rt_event_send(&data->tx_event, CDC_TX_HAS_DATE); + } + } + + return size; +} + +static rt_size_t _vcom_tx(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size,int direction) +{ struct ufunction *func; struct vcom *data; - rt_uint32_t baksize; + rt_uint32_t send_size = 0; rt_size_t ptr = 0; - int empty = 0; rt_uint8_t crlf[2] = {'\r', '\n',}; func = (struct ufunction*)serial->parent.user_data; data = (struct vcom*)func->user_data; - size = (size >= CDC_BULKIN_MAXSIZE) ? CDC_BULKIN_MAXSIZE : size; - baksize = size; - RT_ASSERT(serial != RT_NULL); RT_ASSERT(buf != RT_NULL); @@ -717,64 +743,37 @@ static rt_size_t _vcom_tx(struct rt_serial_device *serial, rt_uint8_t *buf, rt_s if (data->connected) { - size = 0; if((serial->parent.open_flag & RT_DEVICE_FLAG_STREAM)) { - empty = 0; - while(ptr < baksize) + while(send_size < size) { - while(ptr < baksize && buf[ptr] != '\n') + while(ptr < size && buf[ptr] != '\n') { ptr++; } - if(ptr < baksize) + if(ptr < size) { - level = rt_hw_interrupt_disable(); - size += rt_ringbuffer_put_force(&data->tx_ringbuffer, (const rt_uint8_t *)&buf[size], ptr - size); - rt_hw_interrupt_enable(level); - - /* no data was be ignored */ - if(size == ptr) - { - level = rt_hw_interrupt_disable(); - if(rt_ringbuffer_space_len(&data->tx_ringbuffer) >= 2) - { - rt_ringbuffer_put_force(&data->tx_ringbuffer, crlf, 2); - size++; - } - rt_hw_interrupt_enable(level); - } - else - { - empty = 1; - break; - } - - /* ring buffer is full */ - if(size == ptr) - { - empty = 1; - break; - } + send_size += _vcom_rb_block_put(data, (const rt_uint8_t *)&buf[send_size], ptr - send_size); + _vcom_rb_block_put(data, crlf, 2); + send_size++; ptr++; } + else if (ptr == size) + { + send_size += _vcom_rb_block_put(data, (const rt_uint8_t *)&buf[send_size], ptr - send_size); + } else { break; } } } - - if(size < baksize && !empty) + else { - level = rt_hw_interrupt_disable(); - size += rt_ringbuffer_put_force(&data->tx_ringbuffer, (rt_uint8_t *)&buf[size], baksize - size); - rt_hw_interrupt_enable(level); - } - - if(size) - { - rt_event_send(&data->tx_event, CDC_TX_HAS_DATE); + while (send_size < size) + { + send_size += _vcom_rb_block_put(data, (rt_uint8_t *)&buf[send_size], size - send_size); + } } } else @@ -902,6 +901,7 @@ static void vcom_tx_thread_entry(void* parameter) #else rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DMADONE); #endif + rt_event_send(&data->tx_event, CDC_TX_HAS_SPACE); } }