8000 samd: Fix USB CDC RX handling to not block when unprocessed. · robert-hh/micropython@69c3504 · GitHub
[go: up one dir, main page]

Skip to content

Commit 69c3504

Browse files
committed
samd: Fix USB CDC RX handling to not block when unprocessed.
Porting PR micropython#8040 of @hoihu for SAMD, following the commit 5873390. One small addition: Before executing keyboard interrupt, the input buffer is cleared.
1 parent f0432aa commit 69c3504

File tree

3 files changed

+57
-20
lines changed

3 files changed

+57
-20
lines changed

ports/samd/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ SRC_C += \
132132
shared/libc/string0.c \
133133
shared/readline/readline.c \
134134
shared/runtime/gchelper_native.c \
135+
shared/runtime/interrupt_char.c \
135136
shared/runtime/pyexec.c \
136137
shared/runtime/stdout_helpers.c \
137138
shared/runtime/sys_stdio_mphal.c \

ports/samd/mphalport.c

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,54 @@
3333
#include "samd_soc.h"
3434
#include "tusb.h"
3535

36-
#if MICROPY_KBD_EXCEPTION
37-
int mp_interrupt_char = -1;
38-
39-
void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) {
40-
(void)itf;
41-
(void)wanted_char;
42-
tud_cdc_read_char(); // discard interrupt char
43-
mp_sched_keyboard_interrupt();
44-
}
36+
#ifndef MICROPY_HW_STDIN_BUFFER_LEN
37+
#define MICROPY_HW_STDIN_BUFFER_LEN 128
38+
#endif
39+
40+
STATIC uint8_t stdin_ringbuf_array[MICROPY_HW_STDIN_BUFFER_LEN];
41+
ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0 };
4542

46-
void mp_hal_set_interrupt_char(int c) {
47-
mp_interrupt_char = c;
48-
tud_cdc_set_wanted_char(c);
43+
uint8_t cdc_itf_pending; // keep track of cdc interfaces which need attention to poll
44+
45+
void poll_cdc_interfaces(void) {
46+
// any CDC interfaces left to poll?
47+
if (cdc_itf_pending && ringbuf_free(&stdin_ringbuf)) {
48+
for (uint8_t itf = 0; itf < 8; ++itf) {
49+
if (cdc_itf_pending & (1 << itf)) {
50+
tud_cdc_rx_cb(itf);
51+
if (!cdc_itf_pending) {
52+
break;
53+
}
54+
}
55+
}
56+
}
4957
}
5058

51-
#endif
59+
void tud_cdc_rx_cb(uint8_t itf) {
60+
// consume pending USB data immediately to free usb buffer and keep the endpoint from stalling.
61+
// in case the ringbuffer is full, mark the CDC interface that need attention later on for polling
62+
cdc_itf_pending &= ~(1 << itf);
63+
for (uint32_t bytes_avail = tud_cdc_n_available(itf); bytes_avail > 0; --bytes_avail) {
64+
if (ringbuf_free(&stdin_ringbuf)) {
65+
int data_char = tud_cdc_read_char();
66+
#if MICROPY_KBD_EXCEPTION
67+
if (data_char == mp_interrupt_char) {
68+
// Clear the ring buffer
69+
stdin_ringbuf.iget = stdin_ringbuf.iput = 0;
70+
// and stop
71+
mp_sched_keyboard_interrupt();
72+
} else {
73+
ringbuf_put(&stdin_ringbuf, data_char);
74+
}
75+
#else
76+
ringbuf_put(&stdin_ringbuf, data_char);
77+
#endif
78+
} else {
79+
cdc_itf_pending |= (1 << itf);
80+
return;
81+
}
82+
}
83+
}
5284

5385
void mp_hal_set_pin_mux(mp_hal_pin_obj_t pin, uint8_t mux) {
5486
int pin_grp = pin / 32;
@@ -90,9 +122,12 @@ void mp_hal_delay_us(mp_uint_t us) {
90122

91123
uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
92124
uintptr_t ret = 0;
93-
if (tud_cdc_connected() && tud_cdc_available()) {
125+
126+
poll_cdc_interfaces();
127+
if ((poll_flags & MP_STREAM_POLL_RD) && ringbuf_peek(&stdin_ringbuf) != -1) {
94128
ret |= MP_STREAM_POLL_RD;
95129
}
130+
96131
#if MICROPY_PY_OS_DUPTERM
97132
ret |= mp_uos_dupterm_poll(poll_flags);
98133
#endif
@@ -101,13 +136,13 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
101136

102137
int mp_hal_stdin_rx_chr(void) {
103138
for (;;) {
104-
if (tud_cdc_connected() && tud_cdc_available()) {
105-
uint8_t buf[1];
106-
uint32_t count = tud_cdc_read(buf, sizeof(buf));
107-
if (count) {
108-
return buf[0];
109-
}
139+
140+
poll_cdc_interfaces();
141+
int c = ringbuf_get(&stdin_ringbuf);
142+
if (c != -1) {
143+
return c;
110144
}
145+
111146
#if MICROPY_PY_OS_DUPTERM
112147
int dupterm_c = mp_uos_dupterm_rx_chr();
113148
if (dupterm_c >= 0) {

ports/samd/mphalport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#ifndef MICROPY_INCLUDED_SAMD_MPHALPORT_H
2828
#define MICROPY_INCLUDED_SAMD_MPHALPORT_H
2929

30+
#include "py/ringbuf.h"
3031
#include "py/mpconfig.h"
3132

3233
// ASF4

0 commit comments

Comments
 (0)
0