From 537943ed6fae2d71e793c340b195f8be8a3e6cac Mon Sep 17 00:00:00 2001 From: "Aubr.Cool" Date: Mon, 22 Jan 2018 13:18:27 +0800 Subject: [PATCH] [Components] driver usb vcom fix error for console (#1160) * [Components] driver usb vcom fix error for console --- .../drivers/usb/usbdevice/class/cdc_vcom.c | 270 +++++++++++++----- 1 file changed, 193 insertions(+), 77 deletions(-) diff --git a/components/drivers/usb/usbdevice/class/cdc_vcom.c b/components/drivers/usb/usbdevice/class/cdc_vcom.c index a2eb5e66a0..989de152e7 100644 --- a/components/drivers/usb/usbdevice/class/cdc_vcom.c +++ b/components/drivers/usb/usbdevice/class/cdc_vcom.c @@ -37,26 +37,41 @@ #ifdef RT_USB_DEVICE_CDC #define TX_TIMEOUT 1000 -#define CDC_RX_BUFSIZE 2048 +#define CDC_RX_BUFSIZE 128 #define CDC_MAX_PACKET_SIZE 64 #define VCOM_DEVICE "vcom" -#define VCOM_TASK_STK_SIZE 2048 +#ifdef RT_VCOM_TASK_STK_SIZE +#define VCOM_TASK_STK_SIZE RT_VCOM_TASK_STK_SIZE +#else /*!RT_VCOM_TASK_STK_SIZE*/ +#define VCOM_TASK_STK_SIZE 512 +#endif /*RT_VCOM_TASK_STK_SIZE*/ -//#define VCOM_TX_USE_DMA +#ifdef RT_VCOM_TX_USE_DMA +#define VCOM_TX_USE_DMA +#endif /*RT_VCOM_TASK_STK_SIZE*/ + +#ifdef RT_VCOM_SERNO +#define _SER_NO RT_VCOM_SERNO +#else /*!RT_VCOM_SERNO*/ +#define _SER_NO "32021919830108" +#endif /*RT_VCOM_SERNO*/ + +#ifdef RT_VCOM_SER_LEN +#define __SER_NO_LEN RT_VCOM_SER_LEN +#else /*!RT_VCOM_SER_LEN*/ +#define __SER_NO_LEN rt_strlen("32021919830108") +#endif /*RT_VCOM_SER_LEN*/ ALIGN(RT_ALIGN_SIZE) static rt_uint8_t vcom_thread_stack[VCOM_TASK_STK_SIZE]; static struct rt_thread vcom_thread; -#define VCOM_MQ_MSG_SZ 16 -#define VCOM_MQ_MAX_MSG 4 -/* internal of the message queue: every message is associated with a pointer, - * so in order to recveive VCOM_MQ_MAX_MSG messages, we have to allocate more - * than VCOM_MQ_MSG_SZ*VCOM_MQ_MAX_MSG memery. */ -static rt_uint8_t vcom_tx_thread_mq_pool[(VCOM_MQ_MSG_SZ+sizeof(void*))*VCOM_MQ_MAX_MSG]; -static struct rt_messagequeue vcom_tx_thread_mq; static struct ucdc_line_coding line_coding; +#define CDC_TX_BUFSIZE 1024 + +#define CDC_TX_HAS_DATE 0x01 + struct vcom { struct rt_serial_device serial; @@ -67,7 +82,10 @@ struct vcom rt_bool_t in_sending; struct rt_completion wait; rt_uint8_t rx_rbp[CDC_RX_BUFSIZE]; - struct rt_ringbuffer rx_ringbuffer; + struct rt_ringbuffer rx_ringbuffer; + rt_uint8_t tx_rbp[CDC_TX_BUFSIZE]; + struct rt_ringbuffer tx_ringbuffer; + struct rt_event tx_event; }; struct vcom_tx_msg @@ -191,12 +209,17 @@ const static struct ucdc_data_descriptor _data_desc = 0x00, }; +static char serno[_SER_NO_LEN + 1] = {'\0',}; +RT_WEAK rt_err_t vcom_get_stored_serno(char *serno, int size) +{ + return RT_ERROR; +} const static char* _ustring[] = { "Language", "RT-Thread Team.", "RTT Virtual Serial", - "32021919830108", + serno, "Configuration", "Interface", }; @@ -233,7 +256,6 @@ static rt_err_t _ep_in_handler(ufunction_t func, rt_size_t size) RT_ASSERT(func != RT_NULL); RT_DEBUG_LOG(RT_DEBUG_USB, ("_ep_in_handler %d\n", size)); - rt_kprintf("%s size = %d\n",__func__,size); data = (struct vcom*)func->user_data; if ((size != 0) && (size % CDC_MAX_PACKET_SIZE == 0)) { @@ -286,7 +308,7 @@ static rt_err_t _ep_out_handler(ufunction_t func, rt_size_t size) data->ep_out->request.buffer = data->ep_out->buffer; data->ep_out->request.size = EP_MAXPACKET(data->ep_out); - data->ep_out->request.req_type = UIO_REQUEST_READ_BEST; + data->ep_out->request.req_type = UIO_REQUEST_READ_BEST; rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request); return RT_EOK; @@ -442,7 +464,7 @@ static rt_err_t _function_enable(ufunction_t func) data->ep_out->request.buffer = data->ep_out->buffer; data->ep_out->request.size = EP_MAXPACKET(data->ep_out); - data->ep_out->request.req_type = UIO_REQUEST_READ_BEST; + data->ep_out->request.req_type = UIO_REQUEST_READ_BEST; rt_usbd_io_request(func->device, data->ep_out, &data->ep_out->request); return RT_EOK; @@ -522,6 +544,14 @@ ufunction_t rt_usbd_function_cdc_create(udevice_t device) /* parameter check */ RT_ASSERT(device != RT_NULL); + extern rt_err_t vcom_get_stored_serno(char *serno, int size); + + rt_memset(serno, 0, _SER_NO_LEN + 1); + if(vcom_get_stored_serno(serno, _SER_NO_LEN) != RT_EOK) + { + rt_memset(serno, 0, _SER_NO_LEN + 1); + rt_memcpy(serno, _SER_NO, rt_strlen(_SER_NO)); + } /* set usb device string description */ rt_usbd_device_set_string(device, _ustring); @@ -636,113 +666,205 @@ static int _vcom_getc(struct rt_serial_device *serial) return result; } - -#ifdef VCOM_TX_USE_DMA -static rt_size_t _vcom_tx(struct rt_serial_device *serial, const char *buf, rt_size_t size,int direction) +static rt_size_t _vcom_tx(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size,int direction) { - static struct vcom_tx_msg msg; + rt_uint32_t level; + + struct ufunction *func; + struct vcom *data; + + func = (struct ufunction*)serial->parent.user_data; + data = (struct vcom*)func->user_data; + rt_uint32_t baksize = size; + rt_size_t ptr = 0; + int empty = 0; + rt_uint8_t crlf[2] = {'\r', '\n',}; RT_ASSERT(serial != RT_NULL); RT_ASSERT(buf != RT_NULL); - rt_kprintf("%s\n",__func__); - - msg.buf = buf; - msg.serial = serial; - msg.size = size; + RT_DEBUG_LOG(RT_DEBUG_USB, ("%s\n",__func__)); - if (rt_mq_send(&vcom_tx_thread_mq, (void*)&msg, sizeof(struct vcom_tx_msg)) != RT_EOK) + if (data->connected) { - rt_kprintf("vcom send msg fail\n"); - return 0; - } + size = 0; + if((serial->parent.open_flag & RT_DEVICE_FLAG_STREAM)) + { + empty = 0; + while(ptr < baksize) + { + while(ptr < baksize && buf[ptr] != '\n') + { + ptr++; + } + if(ptr < baksize) + { + 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); + 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; + } + if(size == ptr) + { + empty = 1; + break; + } + ptr++; + } + else + { + break; + } + } + } + if(size < baksize && !empty) + { + 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); + } + } return size; } -#else static int _vcom_putc(struct rt_serial_device *serial, char c) { - static struct vcom_tx_msg msg; + rt_uint32_t level; + struct ufunction *func; + struct vcom *data; + + func = (struct ufunction*)serial->parent.user_data; + data = (struct vcom*)func->user_data; RT_ASSERT(serial != RT_NULL); - msg.buf = (void *)((rt_uint32_t)c); - msg.serial = serial; - msg.size = 1; - if (rt_mq_send(&vcom_tx_thread_mq, (void*)&msg, sizeof(struct vcom_tx_msg)) != RT_EOK) + if (data->connected) { -// rt_kprintf("vcom send msg fail\n"); - return -1; + if(c == '\n' && (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM)) + { + level = rt_hw_interrupt_disable(); + rt_ringbuffer_putchar_force(&data->tx_ringbuffer, '\r'); + rt_hw_interrupt_enable(level); + rt_event_send(&data->tx_event, CDC_TX_HAS_DATE); + } + level = rt_hw_interrupt_disable(); + rt_ringbuffer_putchar_force(&data->tx_ringbuffer, c); + rt_hw_interrupt_enable(level); + rt_event_send(&data->tx_event, CDC_TX_HAS_DATE); } return 1; } -#endif static const struct rt_uart_ops usb_vcom_ops = { _vcom_configure, _vcom_control, -#ifndef VCOM_TX_USE_DMA _vcom_putc, _vcom_getc, - RT_NULL -#else - RT_NULL, - _vcom_getc, _vcom_tx -#endif - }; /* Vcom Tx Thread */ static void vcom_tx_thread_entry(void* parameter) { - struct vcom_tx_msg msg; - rt_uint8_t ch; + rt_uint32_t level; + rt_uint32_t res; + struct ufunction *func = (struct ufunction *)parameter; + struct vcom *data = (struct vcom*)func->user_data; + rt_uint8_t ch[64]; + while (1) { - if (rt_mq_recv(&vcom_tx_thread_mq, (void*)&msg, sizeof(struct vcom_tx_msg), RT_WAITING_FOREVER) == RT_EOK) + if + ( + (rt_event_recv(&data->tx_event, CDC_TX_HAS_DATE, + RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, + RT_WAITING_FOREVER, &res) != RT_EOK) || + (!(res & CDC_TX_HAS_DATE)) + ) { - struct ufunction *func; - struct vcom *data; - - func = (struct ufunction*)msg.serial->parent.user_data; - data = (struct vcom*)func->user_data; + continue; + } + if(!res & CDC_TX_HAS_DATE) + { + continue; + } + while(rt_ringbuffer_data_len(&data->tx_ringbuffer)) + { + level = rt_hw_interrupt_disable(); + res = rt_ringbuffer_get(&data->tx_ringbuffer, ch, 64); + rt_hw_interrupt_enable(level); + if(!res) + { + continue; + } if (!data->connected) { + if(data->serial.parent.open_flag & +#ifndef VCOM_TX_USE_DMA + RT_DEVICE_FLAG_INT_TX +#else + RT_DEVICE_FLAG_DMA_TX +#endif + ) + { /* drop msg */ #ifndef VCOM_TX_USE_DMA - rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DONE); + rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DONE); #else - rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DMADONE); + rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DMADONE); #endif + } continue; } - rt_completion_init(&data->wait); -#ifndef VCOM_TX_USE_DMA - ch = (rt_uint8_t)((rt_uint32_t)msg.buf); - data->ep_in->request.buffer = (rt_uint8_t*)&ch; -#else - data->ep_in->request.buffer = (rt_uint8_t*)msg.buf; -#endif - data->ep_in->request.size = msg.size; + data->ep_in->request.buffer = ch; + data->ep_in->request.size = res; + data->ep_in->request.req_type = UIO_REQUEST_WRITE; rt_usbd_io_request(func->device, data->ep_in, &data->ep_in->request); - + if (rt_completion_wait(&data->wait, TX_TIMEOUT) != RT_EOK) { - rt_kprintf("vcom tx timeout\n"); + RT_DEBUG_LOG(RT_DEBUG_USB, ("vcom tx timeout\n")); } + if(data->serial.parent.open_flag & #ifndef VCOM_TX_USE_DMA - rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DONE); + RT_DEVICE_FLAG_INT_TX #else - rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DMADONE); + RT_DEVICE_FLAG_DMA_TX #endif + ) + { +#ifndef VCOM_TX_USE_DMA + rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DONE); +#else + rt_hw_serial_isr(&data->serial,RT_SERIAL_EVENT_TX_DMADONE); +#endif + } } + } } @@ -754,6 +876,9 @@ static void rt_usb_vcom_init(struct ufunction *func) /* initialize ring buffer */ rt_ringbuffer_init(&data->rx_ringbuffer, data->rx_rbp, CDC_RX_BUFSIZE); + rt_ringbuffer_init(&data->tx_ringbuffer, data->tx_rbp, CDC_TX_BUFSIZE); + + rt_event_init(&data->tx_event, "vom", RT_IPC_FLAG_FIFO); config.baud_rate = BAUD_RATE_115200; config.data_bits = DATA_BITS_8; @@ -776,20 +901,11 @@ static void rt_usb_vcom_init(struct ufunction *func) #endif func); - /* create an vcom message queue */ - rt_mq_init(&vcom_tx_thread_mq, - "vcomq", - vcom_tx_thread_mq_pool, - VCOM_MQ_MSG_SZ, - sizeof(vcom_tx_thread_mq_pool), - RT_IPC_FLAG_FIFO); - - /* init usb device thread */ rt_thread_init(&vcom_thread, "vcom", - vcom_tx_thread_entry, RT_NULL, + vcom_tx_thread_entry, func, vcom_thread_stack, VCOM_TASK_STK_SIZE, - 8, 20); + 16, 20); result = rt_thread_startup(&vcom_thread); RT_ASSERT(result == RT_EOK); } -- GitLab