USB-USART improvement: flush buffer, send_break, use callbacks.
This commit is contained in:
@@ -293,6 +293,16 @@ rb_ll_get (struct rb *rb)
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
rb_ll_flush (struct rb *rb)
|
||||
{
|
||||
chopstx_mutex_lock (&rb->m);
|
||||
while (!rb->empty)
|
||||
rb_del (rb);
|
||||
chopstx_cond_signal (&rb->space_available);
|
||||
chopstx_mutex_unlock (&rb->m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Application: consumer
|
||||
* Hardware: generator
|
||||
@@ -328,7 +338,8 @@ rb_write (struct rb *rb, uint8_t *buf, uint16_t buflen)
|
||||
int i = 0;
|
||||
|
||||
chopstx_mutex_lock (&rb->m);
|
||||
while (i < buflen)
|
||||
|
||||
do
|
||||
{
|
||||
while (rb->full)
|
||||
chopstx_cond_wait (&rb->space_available, &rb->m);
|
||||
@@ -337,11 +348,16 @@ rb_write (struct rb *rb, uint8_t *buf, uint16_t buflen)
|
||||
{
|
||||
rb_add (rb, buf[i++]);
|
||||
if (rb->full)
|
||||
break;
|
||||
{
|
||||
chopstx_cond_signal (&rb->data_available);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
chopstx_cond_signal (&rb->data_available);
|
||||
}
|
||||
while (i < buflen);
|
||||
|
||||
if (i)
|
||||
chopstx_cond_signal (&rb->data_available);
|
||||
chopstx_mutex_unlock (&rb->m);
|
||||
}
|
||||
|
||||
@@ -554,7 +570,13 @@ usart_read (uint8_t dev_no, char *buf, uint16_t buflen)
|
||||
else
|
||||
return -1;
|
||||
|
||||
return rb_read (rb, (uint8_t *)buf, buflen);
|
||||
if (buf == NULL && buflen == 0)
|
||||
{
|
||||
rb_ll_flush (rb);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return rb_read (rb, (uint8_t *)buf, buflen);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -569,7 +591,10 @@ usart_write (uint8_t dev_no, char *buf, uint16_t buflen)
|
||||
else
|
||||
return -1;
|
||||
|
||||
rb_write (rb, (uint8_t *)buf, buflen);
|
||||
if (buf == NULL && buflen == 0)
|
||||
rb_ll_flush (rb);
|
||||
else
|
||||
rb_write (rb, (uint8_t *)buf, buflen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ TIOCGICOUNT
|
||||
|
||||
|
||||
TODO:
|
||||
* SEND_BREAK support
|
||||
* Use of DMA for serial communication
|
||||
* RS-232 support: GPIO with DTR (out), DCD (in), DSR (in), RI (in)
|
||||
* serial config setting of CTSRTS?
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
|
||||
struct cdc;
|
||||
|
||||
void cdc_init (void);
|
||||
void
|
||||
cdc_init (uint16_t prio, uintptr_t stack_addr, size_t stack_size,
|
||||
void (*sendbrk_callback) (uint8_t dev_no, uint16_t duration),
|
||||
void (*config_callback) (uint8_t dev_no,
|
||||
uint32_t bitrate, uint8_t format,
|
||||
uint8_t paritytype, uint8_t databits));
|
||||
void cdc_wait_configured (void);
|
||||
|
||||
struct cdc *cdc_open (uint8_t num);
|
||||
|
||||
@@ -30,14 +30,19 @@ blk (void *arg)
|
||||
#define PRIO_USART 4
|
||||
#define PRIO_CDC2USART 3
|
||||
#define PRIO_USART2CDC 3
|
||||
#define PRIO_CDC 2
|
||||
|
||||
#define STACK_MAIN
|
||||
#define STACK_PROCESS_1
|
||||
#define STACK_PROCESS_2
|
||||
#define STACK_PROCESS_3
|
||||
#define STACK_PROCESS_4
|
||||
#define STACK_PROCESS_5
|
||||
#define STACK_PROCESS_6
|
||||
#include "stack-def.h"
|
||||
#define STACK_ADDR_CDC ((uintptr_t)process1_base)
|
||||
#define STACK_SIZE_CDC (sizeof process1_base)
|
||||
|
||||
#define STACK_ADDR_USART ((uint32_t)process2_base)
|
||||
#define STACK_SIZE_USART (sizeof process2_base)
|
||||
|
||||
@@ -70,6 +75,10 @@ usart_to_cdc_loop (void *arg)
|
||||
|
||||
cdc_wait_connection (cdc_usart->cdc);
|
||||
|
||||
/* Flush USART buffers */
|
||||
usart_read (cdc_usart->dev_no, NULL, 0);
|
||||
usart_write (cdc_usart->dev_no, NULL, 0);
|
||||
|
||||
chopstx_usec_wait (100*1000);
|
||||
|
||||
while (1)
|
||||
@@ -98,6 +107,10 @@ cdc_to_usart_loop (void *arg)
|
||||
|
||||
cdc_wait_connection (cdc_usart->cdc);
|
||||
|
||||
/* Flush USART buffers */
|
||||
usart_read (cdc_usart->dev_no, NULL, 0);
|
||||
usart_write (cdc_usart->dev_no, NULL, 0);
|
||||
|
||||
chopstx_usec_wait (50*1000);
|
||||
|
||||
/* Send ZLP at the beginning. */
|
||||
@@ -138,6 +151,78 @@ ss_notify (uint8_t dev_no, uint16_t state_bits)
|
||||
return cdc_ss_notify (s, state_bits);
|
||||
}
|
||||
|
||||
static void
|
||||
send_break (uint8_t dev_no, uint16_t duration)
|
||||
{
|
||||
(void)duration; /* Not supported by USART. */
|
||||
usart_send_break (dev_no);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_usart_config (uint8_t dev_no, uint32_t bitrate, uint8_t format,
|
||||
uint8_t paritytype, uint8_t databits)
|
||||
{
|
||||
/* Check supported config(s) */
|
||||
uint32_t config_bits;
|
||||
|
||||
if (bitrate == 9600)
|
||||
config_bits = B9600;
|
||||
else if (bitrate == 19200)
|
||||
config_bits = B19200;
|
||||
else if (bitrate == 57600)
|
||||
config_bits = B57600;
|
||||
else if (bitrate == 115200)
|
||||
config_bits = B115200;
|
||||
else
|
||||
{
|
||||
bitrate = 115200;
|
||||
config_bits = B115200;
|
||||
}
|
||||
|
||||
if (format == 0)
|
||||
config_bits |= STOP1B;
|
||||
else if (format == 1)
|
||||
config_bits |= STOP1B5;
|
||||
else if (format == 2)
|
||||
config_bits |= STOP2B;
|
||||
else
|
||||
{
|
||||
format = 0;
|
||||
config_bits |= STOP1B;
|
||||
}
|
||||
|
||||
if (paritytype == 0)
|
||||
config_bits |= 0;
|
||||
else if (paritytype == 1)
|
||||
config_bits |= (PARENB | PARODD);
|
||||
else if (paritytype == 2)
|
||||
config_bits |= PARENB;
|
||||
else
|
||||
{
|
||||
paritytype = 0;
|
||||
config_bits |= 0;
|
||||
}
|
||||
|
||||
if (databits == 7)
|
||||
config_bits |= CS7;
|
||||
else if (databits == 7)
|
||||
config_bits |= CS8;
|
||||
else
|
||||
{
|
||||
databits = 8;
|
||||
config_bits |= CS8;
|
||||
}
|
||||
|
||||
if (databits == 7 && paritytype == 0)
|
||||
{
|
||||
databits = 8;
|
||||
config_bits &= ~MASK_CS;
|
||||
config_bits |= CS8;
|
||||
}
|
||||
|
||||
usart_config (dev_no, config_bits);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, const char *argv[])
|
||||
@@ -147,7 +232,8 @@ main (int argc, const char *argv[])
|
||||
|
||||
chopstx_usec_wait (200*1000);
|
||||
|
||||
cdc_init ();
|
||||
cdc_init (PRIO_CDC, STACK_ADDR_CDC, STACK_SIZE_CDC,
|
||||
send_break, setup_usart_config);
|
||||
cdc_wait_configured ();
|
||||
|
||||
usart_init (PRIO_USART, STACK_ADDR_USART, STACK_SIZE_USART, ss_notify);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <chopstx.h>
|
||||
#include <string.h>
|
||||
#include <contrib/usart.h>
|
||||
#include <usb_lld.h>
|
||||
#include "cdc.h"
|
||||
|
||||
@@ -48,11 +47,6 @@ struct cdc {
|
||||
#define MAX_CDC 2
|
||||
static struct cdc cdc_table[MAX_CDC];
|
||||
|
||||
#define STACK_PROCESS_1
|
||||
#include "stack-def.h"
|
||||
#define STACK_ADDR_CDC ((uintptr_t)process1_base)
|
||||
#define STACK_SIZE_CDC (sizeof process1_base)
|
||||
|
||||
|
||||
/*
|
||||
* Locate CDC structure from interface number or endpoint number.
|
||||
@@ -340,70 +334,10 @@ usb_device_reset (struct usb_dev *dev)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
setup_usart_config (struct cdc *s)
|
||||
{
|
||||
/* Check supported config(s) */
|
||||
uint32_t config_bits;
|
||||
|
||||
if (s->line_coding.bitrate == 9600)
|
||||
config_bits = B9600;
|
||||
else if (s->line_coding.bitrate == 19200)
|
||||
config_bits = B19200;
|
||||
else if (s->line_coding.bitrate == 57600)
|
||||
config_bits = B57600;
|
||||
else if (s->line_coding.bitrate == 115200)
|
||||
config_bits = B115200;
|
||||
else
|
||||
{
|
||||
s->line_coding.bitrate = 115200;
|
||||
config_bits = B115200;
|
||||
}
|
||||
|
||||
if (s->line_coding.format == 0)
|
||||
config_bits |= STOP1B;
|
||||
else if (s->line_coding.format == 1)
|
||||
config_bits |= STOP1B5;
|
||||
else if (s->line_coding.format == 2)
|
||||
config_bits |= STOP2B;
|
||||
else
|
||||
{
|
||||
s->line_coding.format = 0;
|
||||
config_bits |= STOP1B;
|
||||
}
|
||||
|
||||
if (s->line_coding.paritytype == 0)
|
||||
config_bits |= 0;
|
||||
else if (s->line_coding.paritytype == 1)
|
||||
config_bits |= (PARENB | PARODD);
|
||||
else if (s->line_coding.paritytype == 2)
|
||||
config_bits |= PARENB;
|
||||
else
|
||||
{
|
||||
s->line_coding.paritytype = 0;
|
||||
config_bits |= 0;
|
||||
}
|
||||
|
||||
if (s->line_coding.databits == 7)
|
||||
config_bits |= CS7;
|
||||
else if (s->line_coding.databits == 7)
|
||||
config_bits |= CS8;
|
||||
else
|
||||
{
|
||||
s->line_coding.databits = 8;
|
||||
config_bits |= CS8;
|
||||
}
|
||||
|
||||
if (s->line_coding.databits == 7 && s->line_coding.paritytype == 0)
|
||||
{
|
||||
s->line_coding.databits = 8;
|
||||
config_bits &= ~MASK_CS;
|
||||
config_bits |= CS8;
|
||||
}
|
||||
|
||||
usart_config (s->dev_no, config_bits);
|
||||
}
|
||||
|
||||
void (*send_break) (uint8_t dev_no, uint16_t duration);
|
||||
static void (*setup_usart_config) (uint8_t dev_no, uint32_t bitrate,
|
||||
uint8_t format, uint8_t paritytype,
|
||||
uint8_t databits);
|
||||
|
||||
#define CDC_CTRL_DTR 0x0001
|
||||
|
||||
@@ -419,7 +353,10 @@ usb_ctrl_write_finish (struct usb_dev *dev)
|
||||
struct cdc *s = cdc_get (arg->index, 0);
|
||||
|
||||
if (arg->request == USB_CDC_REQ_SET_LINE_CODING)
|
||||
setup_usart_config (s);
|
||||
(*setup_usart_config) (s->dev_no, s->line_coding.bitrate,
|
||||
s->line_coding.format,
|
||||
s->line_coding.paritytype,
|
||||
s->line_coding.databits);
|
||||
else if (arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
|
||||
{
|
||||
/* Open/close the connection. */
|
||||
@@ -428,6 +365,12 @@ usb_ctrl_write_finish (struct usb_dev *dev)
|
||||
chopstx_cond_broadcast (&s->cnd_rx);
|
||||
chopstx_mutex_unlock (&s->mtx);
|
||||
}
|
||||
else if (arg->request == USB_CDC_REQ_SEND_BREAK)
|
||||
{
|
||||
chopstx_mutex_lock (&s->mtx);
|
||||
send_break (s->dev_no, arg->value);
|
||||
chopstx_mutex_unlock (&s->mtx);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The transaction was already finished. So, it is no use to call
|
||||
@@ -462,6 +405,8 @@ vcom_port_data_setup (struct usb_dev *dev)
|
||||
}
|
||||
else if (arg->request == USB_CDC_REQ_SET_CONTROL_LINE_STATE)
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
else if (arg->request == USB_CDC_REQ_SEND_BREAK)
|
||||
return usb_lld_ctrl_ack (dev);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -712,14 +657,18 @@ usb_rx_ready (uint8_t ep_num, uint16_t len)
|
||||
|
||||
static void *cdc_main (void *arg);
|
||||
|
||||
#define PRIO_CDC 2
|
||||
|
||||
|
||||
void
|
||||
cdc_init (void)
|
||||
cdc_init (uint16_t prio, uintptr_t stack_addr, size_t stack_size,
|
||||
void (*sendbrk_callback) (uint8_t dev_no, uint16_t duration),
|
||||
void (*config_callback) (uint8_t dev_no,
|
||||
uint32_t bitrate, uint8_t format,
|
||||
uint8_t paritytype, uint8_t databits))
|
||||
{
|
||||
int i;
|
||||
|
||||
send_break = sendbrk_callback;
|
||||
setup_usart_config = config_callback;
|
||||
for (i = 0; i < MAX_CDC; i++)
|
||||
{
|
||||
struct cdc *s = &cdc_table[i];
|
||||
@@ -750,7 +699,7 @@ cdc_init (void)
|
||||
}
|
||||
|
||||
device_state = USB_DEVICE_STATE_UNCONNECTED;
|
||||
chopstx_create (PRIO_CDC, STACK_ADDR_CDC, STACK_SIZE_CDC, cdc_main, NULL);
|
||||
chopstx_create (prio, stack_addr, stack_size, cdc_main, NULL);
|
||||
}
|
||||
|
||||
struct cdc *
|
||||
|
||||
Reference in New Issue
Block a user