USB-USART supports notification of serial error.

This commit is contained in:
NIIBE Yutaka
2017-12-18 11:11:25 +09:00
parent 1533284ace
commit 199db97025
6 changed files with 141 additions and 27 deletions

View File

@@ -3,14 +3,21 @@ This is an application example using ST Nucleo F103 board.
SB62 and SB63 should be soldered.
ST-Link/V2 is disconnected (SB13 and SB14).
NOTE:
Using the USB CDC-ACM for serial communication is a kind of wrong,
because it's designed for modem; No way to control CTSRTS.
TIOCGICOUNT
TODO:
* serial config setting
* CTSRTS? How by USB? By vendor specific control?
* stats report control
* USB communication class interface notification (interrupt ENDP2) support
SERIAL_STATE
* 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?
By vendor specific control?
* stats report control
By vendor specific control?
* Half-duplex support
* Support of other communication mode: smartcard, IrDA, etc.

View File

@@ -9,3 +9,4 @@ struct cdc *cdc_open (uint8_t num);
void cdc_wait_connection (struct cdc *);
int cdc_send (struct cdc *s, const char *buf, int count);
int cdc_recv (struct cdc *s, char *buf, uint32_t *timeout);
int cdc_ss_notify (struct cdc *s, uint16_t state_bits);

View File

@@ -120,13 +120,28 @@ cdc_to_usart_loop (void *arg)
return NULL;
}
static struct cdc_usart cdc_usart0;
static struct cdc_usart cdc_usart1;
static int
ss_notify (uint8_t dev_no, uint16_t state_bits)
{
struct cdc *s;
if (dev_no == cdc_usart0.dev_no)
s = cdc_usart0.cdc;
else if (dev_no == cdc_usart1.dev_no)
s = cdc_usart1.cdc;
else
return -1;
return cdc_ss_notify (s, state_bits);
}
int
main (int argc, const char *argv[])
{
struct cdc_usart cdc_usart0;
struct cdc_usart cdc_usart1;
(void)argc;
(void)argv;
@@ -135,7 +150,7 @@ main (int argc, const char *argv[])
cdc_init ();
cdc_wait_configured ();
usart_init (PRIO_USART, STACK_ADDR_USART, STACK_SIZE_USART);
usart_init (PRIO_USART, STACK_ADDR_USART, STACK_SIZE_USART, ss_notify);
cdc_usart0.cdc = cdc_open (0);
cdc_usart0.dev_no = 2;

View File

@@ -40,7 +40,8 @@ struct cdc {
uint32_t flag_connected : 1;
uint32_t flag_output_ready: 1;
uint32_t flag_input_avail : 1;
uint32_t : 22;
uint32_t flag_notify_busy : 1;
uint32_t :21;
struct line_coding line_coding;
};
@@ -84,16 +85,19 @@ cdc_get (int interface, uint8_t ep_num)
#define ENDP0_TXADDR (0x80)
#define ENDP1_TXADDR (0xc0)
#define ENDP2_TXADDR (0x100)
#define ENDP3_RXADDR (0x108)
#define ENDP4_TXADDR (0x148)
#define ENDP5_TXADDR (0x188)
#define ENDP6_RXADDR (0x190)
#define ENDP3_RXADDR (0x10A)
#define ENDP4_TXADDR (0x14A)
#define ENDP5_TXADDR (0x18A)
#define ENDP6_RXADDR (0x194)
/* 0x1d4 = 468, 44-byte available */
#define USB_CDC_REQ_SET_LINE_CODING 0x20
#define USB_CDC_REQ_GET_LINE_CODING 0x21
#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22
#define USB_CDC_REQ_SEND_BREAK 0x23
#define USB_CDC_NOTIFY_SERIAL_STATE 0x20
/* USB Device Descriptor */
static const uint8_t vcom_device_desc[18] = {
18, /* bLength */
@@ -169,7 +173,7 @@ static const uint8_t vcom_config_desc[] = {
ENDPOINT_DESCRIPTOR,
ENDP2|0x80, /* bEndpointAddress. */
0x03, /* bmAttributes (Interrupt). */
0x08, 0x00, /* wMaxPacketSize. */
0x0A, 0x00, /* wMaxPacketSize. */
0xFF, /* bInterval. */
/* Interface Descriptor.*/
9,
@@ -242,7 +246,7 @@ static const uint8_t vcom_config_desc[] = {
ENDPOINT_DESCRIPTOR,
ENDP5|0x80, /* bEndpointAddress. */
0x03, /* bmAttributes (Interrupt). */
0x08, 0x00, /* wMaxPacketSize. */
0x0A, 0x00, /* wMaxPacketSize. */
0xFF, /* bInterval. */
/* Interface Descriptor.*/
9,
@@ -675,20 +679,20 @@ usb_tx_done (uint8_t ep_num, uint16_t len)
(void)len;
if (ep_num == ENDP1 || ep_num == ENDP4)
chopstx_mutex_lock (&s->mtx);
if (ep_num == s->endp1)
{
chopstx_mutex_lock (&s->mtx);
if (s->flag_output_ready == 0)
{
s->flag_output_ready = 1;
chopstx_cond_signal (&s->cnd_tx);
}
chopstx_mutex_unlock (&s->mtx);
}
else if (ep_num == ENDP2 || ep_num == ENDP5)
else if (ep_num == s->endp2)
{
/* Nothing */
s->flag_notify_busy = 0;
}
chopstx_mutex_unlock (&s->mtx);
}
@@ -697,7 +701,7 @@ usb_rx_ready (uint8_t ep_num, uint16_t len)
{
struct cdc *s = cdc_get (-1, ep_num);
if (ep_num == ENDP3 || ep_num == ENDP6)
if (ep_num == s->endp3)
{
usb_lld_rxcpy (s->input, ep_num, 0, len);
s->flag_input_avail = 1;
@@ -1043,3 +1047,39 @@ cdc_recv (struct cdc *s, char *buf, uint32_t *timeout)
return r;
}
int
cdc_ss_notify (struct cdc *s, uint16_t state_bits)
{
int busy;
uint8_t notification[10];
int interface;
if (s == &cdc_table[0])
interface = 0;
else
interface = 2;
/* Little endian */
notification[0] = REQUEST_DIR | CLASS_REQUEST | INTERFACE_RECIPIENT;
notification[1] = USB_CDC_NOTIFY_SERIAL_STATE;
notification[2] = notification[3] = 0;
notification[4] = interface;
notification[5] = 0;
notification[6] = 2;
notification[7] = 0;
notification[8] = (state_bits & 0xff);
notification[9] = (state_bits >> 8);
chopstx_mutex_lock (&s->mtx);
busy = s->flag_notify_busy;
if (!busy)
{
usb_lld_write (s->endp2, notification, sizeof notification);
s->flag_notify_busy = 1;
}
chopstx_mutex_unlock (&s->mtx);
return busy;
}