1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2026-01-01 01:41:18 +01:00

Merge pull request #12402 from ant9000/pr/usbus_cdc_acm_stdio_fix

Fix to avoid lost characters on USBUS CDC ACM STDIO
This commit is contained in:
Koen Zandberg 2020-01-15 19:52:13 +01:00 committed by GitHub
commit 5fd981b2e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 8 deletions

View File

@ -145,15 +145,35 @@ static size_t _gen_full_acm_descriptor(usbus_t *usbus, void *arg)
/* Submit (ACM interface in) */
size_t usbus_cdc_acm_submit(usbus_cdcacm_device_t *cdcacm, const uint8_t *buf, size_t len)
{
return tsrb_add(&cdcacm->tsrb, buf, len);
size_t n;
unsigned old;
if (cdcacm->state != USBUS_CDC_ACM_LINE_STATE_DISCONNECTED) {
old = irq_disable();
n = tsrb_add(&cdcacm->tsrb, buf, len);
irq_restore(old);
return n;
}
/* stuff as much data as possible into tsrb, discarding the oldest */
old = irq_disable();
n = tsrb_free(&cdcacm->tsrb);
if (len > n) {
n += tsrb_drop(&cdcacm->tsrb, len - n);
buf += len - n;
} else {
n = len;
}
tsrb_add(&cdcacm->tsrb, buf, n);
/* behave as if everything has been written correctly */
irq_restore(old);
return len;
}
void usbus_cdc_acm_set_coding_cb(usbus_cdcacm_device_t *cdcacm,
usbus_cdcacm_coding_cb_t coding_cb)
{
irq_disable();
unsigned old = irq_disable();
cdcacm->coding_cb = coding_cb;
irq_enable();
irq_restore(old);
}
/* flush event */
@ -297,6 +317,8 @@ static void _handle_in(usbus_cdcacm_device_t *cdcacm,
(cdcacm->state != USBUS_CDC_ACM_LINE_STATE_DTE)) {
return;
}
/* copy at most USBUS_CDC_ACM_BULK_EP_SIZE chars from input into ep->buf */
unsigned old = irq_disable();
while (!tsrb_empty(&cdcacm->tsrb)) {
int c = tsrb_get_one(&cdcacm->tsrb);
ep->buf[cdcacm->occupied++] = (uint8_t)c;
@ -304,6 +326,7 @@ static void _handle_in(usbus_cdcacm_device_t *cdcacm,
break;
}
}
irq_restore(old);
usbdev_ep_ready(ep, cdcacm->occupied);
}

View File

@ -52,10 +52,15 @@ ssize_t stdio_read(void* buffer, size_t len)
ssize_t stdio_write(const void* buffer, size_t len)
{
usbus_cdc_acm_submit(&cdcacm, buffer, len);
usbus_cdc_acm_flush(&cdcacm);
/* Use tsrb and flush */
return len;
const char *start = buffer;
do {
size_t n = usbus_cdc_acm_submit(&cdcacm, buffer, len);
usbus_cdc_acm_flush(&cdcacm);
/* Use tsrb and flush */
buffer = (char *)buffer + n;
len -= n;
} while (len);
return start - (char *)buffer;
}
static void _cdc_acm_rx_pipe(usbus_cdcacm_device_t *cdcacm,

View File

@ -18,16 +18,46 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include "shell.h"
#include "shell_commands.h"
static int cmd_text(int argc, char **argv)
{
char *usage = "text [length]\n";
if (argc != 2) {
puts(usage);
return -1;
}
int n = atoi(argv[1]);
if (n <= 0) {
puts(usage);
return -1;
}
for (int i=0; i < n; i++) {
if (i && (i % 80 == 0)) {
puts("");
}
putc('0' + (i % 10), stdout);
}
puts("");
return 0;
}
static const shell_command_t shell_commands[] = {
{ "text", "Generates long text for testing stdio buffer", cmd_text },
{ NULL, NULL, NULL }
};
int main(void)
{
(void) puts("RIOT USB CDC ACM shell test");
char line_buf[SHELL_DEFAULT_BUFSIZE];
shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
return 0;
}