Update example-cdc

This commit is contained in:
NIIBE Yutaka
2016-05-12 18:14:47 +09:00
parent 5730641ffd
commit fabd271196
5 changed files with 185 additions and 30 deletions

View File

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

View File

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

View File

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

View File

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

View File

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