samd/mphalport: Fix USB endpoint handling ignoring Ctrl-C.
Porting PR #8040 by @hoihu to SAMD, following the commit 587339022689187a1acbccc1d0e2425a67385ff7. One small addition: before executing keyboard interrupt, the input buffer is cleared.
This commit is contained in:
parent
b001730462
commit
e9a76310ec
@ -131,6 +131,7 @@ SRC_C += \
|
|||||||
shared/libc/string0.c \
|
shared/libc/string0.c \
|
||||||
shared/readline/readline.c \
|
shared/readline/readline.c \
|
||||||
shared/runtime/gchelper_native.c \
|
shared/runtime/gchelper_native.c \
|
||||||
|
shared/runtime/interrupt_char.c \
|
||||||
shared/runtime/pyexec.c \
|
shared/runtime/pyexec.c \
|
||||||
shared/runtime/softtimer.c \
|
shared/runtime/softtimer.c \
|
||||||
shared/runtime/stdout_helpers.c \
|
shared/runtime/stdout_helpers.c \
|
||||||
|
@ -33,23 +33,55 @@
|
|||||||
#include "samd_soc.h"
|
#include "samd_soc.h"
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
|
|
||||||
#if MICROPY_KBD_EXCEPTION
|
#ifndef MICROPY_HW_STDIN_BUFFER_LEN
|
||||||
int mp_interrupt_char = -1;
|
#define MICROPY_HW_STDIN_BUFFER_LEN 128
|
||||||
|
|
||||||
void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) {
|
|
||||||
(void)itf;
|
|
||||||
(void)wanted_char;
|
|
||||||
tud_cdc_read_char(); // discard interrupt char
|
|
||||||
mp_sched_keyboard_interrupt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void mp_hal_set_interrupt_char(int c) {
|
|
||||||
mp_interrupt_char = c;
|
|
||||||
tud_cdc_set_wanted_char(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
STATIC uint8_t stdin_ringbuf_array[MICROPY_HW_STDIN_BUFFER_LEN];
|
||||||
|
ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0 };
|
||||||
|
|
||||||
|
uint8_t cdc_itf_pending; // keep track of cdc interfaces which need attention to poll
|
||||||
|
|
||||||
|
void poll_cdc_interfaces(void) {
|
||||||
|
// any CDC interfaces left to poll?
|
||||||
|
if (cdc_itf_pending && ringbuf_free(&stdin_ringbuf)) {
|
||||||
|
for (uint8_t itf = 0; itf < 8; ++itf) {
|
||||||
|
if (cdc_itf_pending & (1 << itf)) {
|
||||||
|
tud_cdc_rx_cb(itf);
|
||||||
|
if (!cdc_itf_pending) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tud_cdc_rx_cb(uint8_t itf) {
|
||||||
|
// consume pending USB data immediately to free usb buffer and keep the endpoint from stalling.
|
||||||
|
// in case the ringbuffer is full, mark the CDC interface that need attention later on for polling
|
||||||
|
cdc_itf_pending &= ~(1 << itf);
|
||||||
|
for (uint32_t bytes_avail = tud_cdc_n_available(itf); bytes_avail > 0; --bytes_avail) {
|
||||||
|
if (ringbuf_free(&stdin_ringbuf)) {
|
||||||
|
int data_char = tud_cdc_read_char();
|
||||||
|
#if MICROPY_KBD_EXCEPTION
|
||||||
|
if (data_char == mp_interrupt_char) {
|
||||||
|
// Clear the ring buffer
|
||||||
|
stdin_ringbuf.iget = stdin_ringbuf.iput = 0;
|
||||||
|
// and stop
|
||||||
|
mp_sched_keyboard_interrupt();
|
||||||
|
} else {
|
||||||
|
ringbuf_put(&stdin_ringbuf, data_char);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ringbuf_put(&stdin_ringbuf, data_char);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
cdc_itf_pending |= (1 << itf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void mp_hal_set_pin_mux(mp_hal_pin_obj_t pin, uint8_t mux) {
|
void mp_hal_set_pin_mux(mp_hal_pin_obj_t pin, uint8_t mux) {
|
||||||
int pin_grp = pin / 32;
|
int pin_grp = pin / 32;
|
||||||
int port_grp = (pin % 32) / 2;
|
int port_grp = (pin % 32) / 2;
|
||||||
@ -94,9 +126,12 @@ void mp_hal_delay_us(mp_uint_t us) {
|
|||||||
|
|
||||||
uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
|
uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
|
||||||
uintptr_t ret = 0;
|
uintptr_t ret = 0;
|
||||||
if (tud_cdc_connected() && tud_cdc_available()) {
|
|
||||||
|
poll_cdc_interfaces();
|
||||||
|
if ((poll_flags & MP_STREAM_POLL_RD) && ringbuf_peek(&stdin_ringbuf) != -1) {
|
||||||
ret |= MP_STREAM_POLL_RD;
|
ret |= MP_STREAM_POLL_RD;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MICROPY_PY_OS_DUPTERM
|
#if MICROPY_PY_OS_DUPTERM
|
||||||
ret |= mp_uos_dupterm_poll(poll_flags);
|
ret |= mp_uos_dupterm_poll(poll_flags);
|
||||||
#endif
|
#endif
|
||||||
@ -105,13 +140,13 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
|
|||||||
|
|
||||||
int mp_hal_stdin_rx_chr(void) {
|
int mp_hal_stdin_rx_chr(void) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (tud_cdc_connected() && tud_cdc_available()) {
|
|
||||||
uint8_t buf[1];
|
poll_cdc_interfaces();
|
||||||
uint32_t count = tud_cdc_read(buf, sizeof(buf));
|
int c = ringbuf_get(&stdin_ringbuf);
|
||||||
if (count) {
|
if (c != -1) {
|
||||||
return buf[0];
|
return c;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MICROPY_PY_OS_DUPTERM
|
#if MICROPY_PY_OS_DUPTERM
|
||||||
int dupterm_c = mp_uos_dupterm_rx_chr();
|
int dupterm_c = mp_uos_dupterm_rx_chr();
|
||||||
if (dupterm_c >= 0) {
|
if (dupterm_c >= 0) {
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#ifndef MICROPY_INCLUDED_SAMD_MPHALPORT_H
|
#ifndef MICROPY_INCLUDED_SAMD_MPHALPORT_H
|
||||||
#define MICROPY_INCLUDED_SAMD_MPHALPORT_H
|
#define MICROPY_INCLUDED_SAMD_MPHALPORT_H
|
||||||
|
|
||||||
|
#include "py/ringbuf.h"
|
||||||
#include "py/mpconfig.h"
|
#include "py/mpconfig.h"
|
||||||
|
|
||||||
// ASF4
|
// ASF4
|
||||||
|
Loading…
x
Reference in New Issue
Block a user