Update example-cdc
This commit is contained in:
@@ -1,5 +1,10 @@
|
|||||||
2016-05-12 NIIBE Yutaka <gniibe@fsij.org>
|
2016-05-12 NIIBE Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* example-cdc/sample.c: Update using chopstx_poll.
|
||||||
|
* example-cdc/sample.ld: Likewise.
|
||||||
|
* example-cdc/stream.h: Likewise.
|
||||||
|
* example-cdc/usb-cdc.c: Likewise.
|
||||||
|
|
||||||
* chopstx.c (chopstx_mutex_init): Initialize OWNER, too.
|
* chopstx.c (chopstx_mutex_init): Initialize OWNER, too.
|
||||||
[__ARM_ARCH_7M__] (preempt): Bug fix for register 0 to inhibit
|
[__ARM_ARCH_7M__] (preempt): Bug fix for register 0 to inhibit
|
||||||
scheduling.
|
scheduling.
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <chopstx.h>
|
#include <chopstx.h>
|
||||||
|
|
||||||
#include "sys.h" /* for set_led */
|
#include "sys.h" /* for set_led */
|
||||||
#include "usb_lld.h"
|
#include "usb_lld.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
@@ -10,7 +11,6 @@ static chopstx_mutex_t mtx;
|
|||||||
static chopstx_cond_t cnd0;
|
static chopstx_cond_t cnd0;
|
||||||
static chopstx_cond_t cnd1;
|
static chopstx_cond_t cnd1;
|
||||||
|
|
||||||
|
|
||||||
static uint8_t u, v;
|
static uint8_t u, v;
|
||||||
static uint8_t m; /* 0..100 */
|
static uint8_t m; /* 0..100 */
|
||||||
|
|
||||||
@@ -113,8 +113,10 @@ const size_t __stacksize_blk = (size_t)&__process2_stack_size__;
|
|||||||
const uint32_t __stackaddr_intr = (uint32_t)&__process3_stack_base__;
|
const uint32_t __stackaddr_intr = (uint32_t)&__process3_stack_base__;
|
||||||
const size_t __stacksize_intr = (size_t)&__process3_stack_size__;
|
const size_t __stacksize_intr = (size_t)&__process3_stack_size__;
|
||||||
|
|
||||||
|
|
||||||
static char hexchar (uint8_t x)
|
static char hexchar (uint8_t x)
|
||||||
{
|
{
|
||||||
|
x &= 0x0f;
|
||||||
if (x <= 0x09)
|
if (x <= 0x09)
|
||||||
return '0' + x;
|
return '0' + x;
|
||||||
else if (x <= 0x0f)
|
else if (x <= 0x0f)
|
||||||
@@ -124,6 +126,18 @@ static char hexchar (uint8_t x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_recv (void *arg)
|
||||||
|
{
|
||||||
|
struct stream *s = arg;
|
||||||
|
if ((s->flags & FLAG_CONNECTED) == 0)
|
||||||
|
return 1;
|
||||||
|
if ((s->flags & FLAG_RECV_AVAIL))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, const char *argv[])
|
main (int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
@@ -163,6 +177,7 @@ main (int argc, const char *argv[])
|
|||||||
{
|
{
|
||||||
uint8_t s[64];
|
uint8_t s[64];
|
||||||
|
|
||||||
|
u = 1;
|
||||||
if (stream_wait_connection (st) < 0)
|
if (stream_wait_connection (st) < 0)
|
||||||
{
|
{
|
||||||
chopstx_usec_wait (1000*1000);
|
chopstx_usec_wait (1000*1000);
|
||||||
@@ -174,7 +189,7 @@ main (int argc, const char *argv[])
|
|||||||
/* Send ZLP at the beginning. */
|
/* Send ZLP at the beginning. */
|
||||||
stream_send (st, s, 0);
|
stream_send (st, s, 0);
|
||||||
|
|
||||||
memcpy (s, "xx: Hello, World with Chopstx!\r\n\000", 32);
|
memcpy (s, "xx: Hello, World with Chopstx!\r\n", 32);
|
||||||
s[0] = hexchar (count >> 4);
|
s[0] = hexchar (count >> 4);
|
||||||
s[1] = hexchar (count & 0x0f);
|
s[1] = hexchar (count & 0x0f);
|
||||||
count++;
|
count++;
|
||||||
@@ -184,15 +199,36 @@ main (int argc, const char *argv[])
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int size = stream_recv (st, s);
|
int size;
|
||||||
|
uint32_t usec;
|
||||||
|
struct chx_poll_desc poll_desc;
|
||||||
|
|
||||||
if (size < 0)
|
poll_desc.type = CHOPSTX_POLL_COND;
|
||||||
break;
|
poll_desc.c.cond = &st->cnd;
|
||||||
|
poll_desc.c.mutex = &st->mtx;
|
||||||
|
poll_desc.c.check = check_recv;
|
||||||
|
poll_desc.c.arg = st;
|
||||||
|
|
||||||
if (size >= 0)
|
/* With chopstx_poll, we can do timed cond_wait */
|
||||||
|
usec = 3000000; /* 3.0 seconds */
|
||||||
|
if (chopstx_poll (&usec, 1, &poll_desc))
|
||||||
{
|
{
|
||||||
if (stream_send (st, s, size) < 0)
|
size = stream_recv (st, s + 4);
|
||||||
|
|
||||||
|
if (size < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (size >= 0)
|
||||||
|
{
|
||||||
|
s[0] = hexchar (size >> 4);
|
||||||
|
s[1] = hexchar (size & 0x0f);
|
||||||
|
s[2] = ':';
|
||||||
|
s[3] = ' ';
|
||||||
|
s[size + 4] = '\r';
|
||||||
|
s[size + 5] = '\n';
|
||||||
|
if (stream_send (st, s, size + 6) < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u ^= 1;
|
u ^= 1;
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
* ST32F103 memory setup.
|
* ST32F103 memory setup.
|
||||||
*/
|
*/
|
||||||
__main_stack_size__ = 0x0100; /* Exception handlers */
|
__main_stack_size__ = 0x0100; /* Exception handlers */
|
||||||
__process0_stack_size__ = 0x0200; /* Main program */
|
__process0_stack_size__ = 0x0400; /* Main program */
|
||||||
__process1_stack_size__ = 0x0200; /* first thread program */
|
__process1_stack_size__ = 0x0200; /* first thread program */
|
||||||
__process2_stack_size__ = 0x0200; /* second thread program */
|
__process2_stack_size__ = 0x0200; /* second thread program */
|
||||||
__process3_stack_size__ = 0x0200; /* third thread program */
|
__process3_stack_size__ = 0x0200; /* third thread program */
|
||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,8 +9,10 @@
|
|||||||
struct stream {
|
struct stream {
|
||||||
chopstx_mutex_t mtx;
|
chopstx_mutex_t mtx;
|
||||||
chopstx_cond_t cnd;
|
chopstx_cond_t cnd;
|
||||||
|
int sending;
|
||||||
|
unsigned int recv_len;
|
||||||
|
uint8_t recv_buf[BUFSIZE]; /* Not yet used. */
|
||||||
uint8_t buf_send[BUFSIZE]; /* Not yet used. */
|
uint8_t buf_send[BUFSIZE]; /* Not yet used. */
|
||||||
uint8_t buf_recv[BUFSIZE]; /* Not yet used. */
|
|
||||||
uint8_t cnt_send_head; /* Not yet used. */
|
uint8_t cnt_send_head; /* Not yet used. */
|
||||||
uint8_t cnt_send_tail; /* Not yet used. */
|
uint8_t cnt_send_tail; /* Not yet used. */
|
||||||
uint8_t cnt_recv_head; /* Not yet used. */
|
uint8_t cnt_recv_head; /* Not yet used. */
|
||||||
|
|||||||
@@ -1,9 +1,18 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <chopstx.h>
|
#include <chopstx.h>
|
||||||
|
#include <string.h>
|
||||||
#include "usb_lld.h"
|
#include "usb_lld.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
|
|
||||||
|
static uint8_t send_buf[64];
|
||||||
|
static unsigned int send_len;
|
||||||
|
|
||||||
|
static unsigned int recv_len;
|
||||||
|
|
||||||
|
static uint8_t inputline[64];
|
||||||
|
static unsigned int inputline_len;
|
||||||
|
|
||||||
static struct stream stream;
|
static struct stream stream;
|
||||||
|
|
||||||
#define ENDP0_RXADDR (0x40)
|
#define ENDP0_RXADDR (0x40)
|
||||||
@@ -190,6 +199,8 @@ usb_cb_ctrl_write_finish (uint8_t req, uint8_t req_no, struct req_args *arg)
|
|||||||
stream.flags &= ~FLAG_CONNECTED;
|
stream.flags &= ~FLAG_CONNECTED;
|
||||||
stream.flags |= ((arg->value & CDC_CTRL_DTR) != 0)? FLAG_CONNECTED : 0;
|
stream.flags |= ((arg->value & CDC_CTRL_DTR) != 0)? FLAG_CONNECTED : 0;
|
||||||
chopstx_cond_signal (&stream.cnd);
|
chopstx_cond_signal (&stream.cnd);
|
||||||
|
recv_len = 0;
|
||||||
|
usb_lld_rx_enable (ENDP3);
|
||||||
chopstx_mutex_unlock (&stream.mtx);
|
chopstx_mutex_unlock (&stream.mtx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,36 +404,136 @@ usb_cb_interface (uint8_t cmd, struct req_args *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
stream_echo_char (int c)
|
||||||
|
{
|
||||||
|
chopstx_mutex_lock (&stream.mtx);
|
||||||
|
if (send_len < sizeof (send_buf))
|
||||||
|
send_buf[send_len++] = c;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* All that we can is ignoring the output. */
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream.sending == 0)
|
||||||
|
{
|
||||||
|
usb_lld_txcpy (send_buf, ENDP1, 0, send_len);
|
||||||
|
usb_lld_tx_enable (ENDP1, send_len);
|
||||||
|
send_len = 0;
|
||||||
|
stream.sending = 1;
|
||||||
|
}
|
||||||
|
chopstx_mutex_unlock (&stream.mtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
usb_cb_tx_done (uint8_t ep_num)
|
usb_cb_tx_done (uint8_t ep_num)
|
||||||
{
|
{
|
||||||
if (ep_num == ENDP1)
|
if (ep_num == ENDP1)
|
||||||
{
|
{
|
||||||
chopstx_mutex_lock (&stream.mtx);
|
chopstx_mutex_lock (&stream.mtx);
|
||||||
if ((stream.flags & FLAG_SEND_AVAIL))
|
stream.sending = 0;
|
||||||
|
if (send_len)
|
||||||
{
|
{
|
||||||
stream.flags &= ~FLAG_SEND_AVAIL;
|
stream.sending = 1;
|
||||||
chopstx_cond_signal (&stream.cnd);
|
usb_lld_txcpy (send_buf, ENDP1, 0, send_len);
|
||||||
|
usb_lld_tx_enable (ENDP1, send_len);
|
||||||
|
send_len = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((stream.flags & FLAG_SEND_AVAIL))
|
||||||
|
{
|
||||||
|
stream.flags &= ~FLAG_SEND_AVAIL;
|
||||||
|
chopstx_cond_signal (&stream.cnd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
chopstx_mutex_unlock (&stream.mtx);
|
chopstx_mutex_unlock (&stream.mtx);
|
||||||
}
|
}
|
||||||
else if (ep_num == ENDP2)
|
else if (ep_num == ENDP2)
|
||||||
{
|
{
|
||||||
|
/* Nothing */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
stream_input_char (int c)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Process DEL, C-U, C-R, and RET as editing command. */
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 0x0d: /* Control-M */
|
||||||
|
stream_echo_char (0x0d);
|
||||||
|
stream_echo_char (0x0a);
|
||||||
|
chopstx_mutex_lock (&stream.mtx);
|
||||||
|
if ((stream.flags & FLAG_RECV_AVAIL) == 0)
|
||||||
|
{
|
||||||
|
memcpy (stream.recv_buf, inputline, inputline_len);
|
||||||
|
stream.recv_len = inputline_len;
|
||||||
|
stream.flags |= FLAG_RECV_AVAIL;
|
||||||
|
chopstx_cond_signal (&stream.cnd);
|
||||||
|
}
|
||||||
|
chopstx_mutex_unlock (&stream.mtx);
|
||||||
|
inputline_len = 0;
|
||||||
|
break;
|
||||||
|
case 0x12: /* Control-R */
|
||||||
|
stream_echo_char ('^');
|
||||||
|
stream_echo_char ('R');
|
||||||
|
stream_echo_char (0x0d);
|
||||||
|
stream_echo_char (0x0a);
|
||||||
|
for (i = 0; i < inputline_len; i++)
|
||||||
|
stream_echo_char (inputline[i]);
|
||||||
|
break;
|
||||||
|
case 0x15: /* Control-U */
|
||||||
|
for (i = 0; i < inputline_len; i++)
|
||||||
|
{
|
||||||
|
stream_echo_char (0x08);
|
||||||
|
stream_echo_char (0x20);
|
||||||
|
stream_echo_char (0x08);
|
||||||
|
}
|
||||||
|
inputline_len = 0;
|
||||||
|
break;
|
||||||
|
case 0x7f: /* DEL */
|
||||||
|
if (inputline_len > 0)
|
||||||
|
{
|
||||||
|
stream_echo_char (0x08);
|
||||||
|
stream_echo_char (0x20);
|
||||||
|
stream_echo_char (0x08);
|
||||||
|
inputline_len--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (inputline_len < sizeof (inputline))
|
||||||
|
{
|
||||||
|
stream_echo_char (c);
|
||||||
|
inputline[inputline_len++] = c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* Beep */
|
||||||
|
stream_echo_char (0x0a);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
usb_cb_rx_ready (uint8_t ep_num)
|
usb_cb_rx_ready (uint8_t ep_num)
|
||||||
{
|
{
|
||||||
|
uint8_t recv_buf[64];
|
||||||
|
|
||||||
if (ep_num == ENDP3)
|
if (ep_num == ENDP3)
|
||||||
{
|
{
|
||||||
chopstx_mutex_lock (&stream.mtx);
|
int i, r;
|
||||||
if ((stream.flags & FLAG_RECV_AVAIL) == 0)
|
|
||||||
{
|
r = usb_lld_rx_data_len (ENDP3);
|
||||||
stream.flags |= FLAG_RECV_AVAIL;
|
usb_lld_rxcpy (recv_buf, ep_num, 0, r);
|
||||||
chopstx_cond_signal (&stream.cnd);
|
for (i = 0; i < r; i++)
|
||||||
}
|
stream_input_char (recv_buf[i]);
|
||||||
chopstx_mutex_unlock (&stream.mtx);
|
|
||||||
|
usb_lld_rx_enable (ENDP3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,7 +567,9 @@ stream_send (struct stream *st, uint8_t *buf, uint8_t count)
|
|||||||
r = -1;
|
r = -1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
usb_lld_write (ENDP1, buf, count);
|
stream.sending = 1;
|
||||||
|
usb_lld_txcpy (buf, ENDP1, 0, count);
|
||||||
|
usb_lld_tx_enable (ENDP1, count);
|
||||||
stream.flags |= FLAG_SEND_AVAIL;
|
stream.flags |= FLAG_SEND_AVAIL;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -471,6 +584,7 @@ stream_send (struct stream *st, uint8_t *buf, uint8_t count)
|
|||||||
}
|
}
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
|
stream.sending = 0;
|
||||||
chopstx_mutex_unlock (&st->mtx);
|
chopstx_mutex_unlock (&st->mtx);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -486,15 +600,13 @@ stream_recv (struct stream *st, uint8_t *buf)
|
|||||||
r = -1;
|
r = -1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
usb_lld_rx_enable (ENDP3);
|
while (1)
|
||||||
stream.flags &= ~FLAG_RECV_AVAIL;
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
chopstx_cond_wait (&st->cnd, &st->mtx);
|
|
||||||
if ((stream.flags & FLAG_RECV_AVAIL))
|
if ((stream.flags & FLAG_RECV_AVAIL))
|
||||||
{
|
{
|
||||||
r = usb_lld_rx_data_len (ENDP3);
|
r = stream.recv_len;
|
||||||
usb_lld_rxcpy (buf, ENDP3, 0, r);
|
memcpy (buf, stream.recv_buf, r);
|
||||||
|
stream.flags &= ~FLAG_RECV_AVAIL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if ((stream.flags & FLAG_CONNECTED) == 0)
|
else if ((stream.flags & FLAG_CONNECTED) == 0)
|
||||||
@@ -502,8 +614,8 @@ stream_recv (struct stream *st, uint8_t *buf)
|
|||||||
r = -1;
|
r = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
chopstx_cond_wait (&st->cnd, &st->mtx);
|
||||||
}
|
}
|
||||||
while (1);
|
|
||||||
}
|
}
|
||||||
chopstx_mutex_unlock (&st->mtx);
|
chopstx_mutex_unlock (&st->mtx);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user