USB-USART improvement: flush buffer, send_break, use callbacks.

This commit is contained in:
NIIBE Yutaka
2017-12-18 13:53:01 +09:00
parent 199db97025
commit ce3cd63144
5 changed files with 148 additions and 84 deletions

View File

@@ -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;
}

View File

@@ -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?

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 *