summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorAubr.Cool <[email protected]>2018-01-22 13:18:27 +0800
committerZYH <[email protected]>2018-01-22 13:18:27 +0800
commit537943ed6fae2d71e793c340b195f8be8a3e6cac (patch)
tree0462a63ccaac9da71c825f1945ac8857cf169cff /components
parent765df5b4795968740ea73640ad500ec368f682a3 (diff)
[Components] driver usb vcom fix error for console (#1160)
* [Components] driver usb vcom fix error for console
Diffstat (limited to 'components')
-rw-r--r--components/drivers/usb/usbdevice/class/cdc_vcom.c270
1 files 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);
}