Skip to content

Commit c98789a

Browse files
andrewleechdpgeorge
authored andcommitted
shared/tinyusb: Add common CDC TX/RX functions.
There are a few TinyUSB CDC functions used for stdio that are currently replicated across a number of ports. Not surprisingly in a couple of cases these have started to diverge slightly, with additional features added to one of them. This commit consolidates a couple of key shared functions used directly by TinyUSB based ports, and makes those functions available to all. Signed-off-by: Andrew Leech <andrew@alelec.net>
1 parent 3613ad9 commit c98789a

File tree

7 files changed

+168
-36
lines changed

7 files changed

+168
-36
lines changed

ports/esp32/boards/ARDUINO_NANO_ESP32/mpconfigboard.cmake

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ set(SDKCONFIG_DEFAULTS
1818
set(MICROPY_SOURCE_BOARD
1919
${MICROPY_BOARD_DIR}/board_init.c
2020
${MICROPY_BOARD_DIR}/double_tap.c
21-
${MICROPY_DIR}/shared/tinyusb/mp_cdc_common.c
21+
${MICROPY_DIR}/shared/tinyusb/mp_usbd_cdc.c
2222
)
2323

2424
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)

ports/nrf/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ SRC_SHARED_C += $(addprefix shared/,\
185185
runtime/pyexec.c \
186186
runtime/sys_stdio_mphal.c \
187187
runtime/interrupt_char.c \
188-
tinyusb/mp_cdc_common.c \
188+
tinyusb/mp_usbd_cdc.c \
189189
timeutils/timeutils.c \
190190
)
191191

ports/renesas-ra/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ SHARED_SRC_C += $(addprefix shared/,\
174174
runtime/stdout_helpers.c \
175175
runtime/sys_stdio_mphal.c \
176176
timeutils/timeutils.c \
177-
tinyusb/mp_cdc_common.c \
178177
tinyusb/mp_usbd.c \
178+
tinyusb/mp_usbd_cdc.c \
179179
tinyusb/mp_usbd_descriptor.c \
180180
)
181181

ports/rp2/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ set(MICROPY_SOURCE_LIB
105105
${MICROPY_DIR}/shared/runtime/softtimer.c
106106
${MICROPY_DIR}/shared/runtime/sys_stdio_mphal.c
107107
${MICROPY_DIR}/shared/timeutils/timeutils.c
108-
${MICROPY_DIR}/shared/tinyusb/mp_cdc_common.c
109108
${MICROPY_DIR}/shared/tinyusb/mp_usbd.c
109+
${MICROPY_DIR}/shared/tinyusb/mp_usbd_cdc.c
110110
${MICROPY_DIR}/shared/tinyusb/mp_usbd_descriptor.c
111111
${MICROPY_DIR}/shared/tinyusb/mp_usbd_runtime.c
112112
)

ports/samd/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ SHARED_SRC_C += \
133133
shared/runtime/stdout_helpers.c \
134134
shared/runtime/sys_stdio_mphal.c \
135135
shared/timeutils/timeutils.c \
136-
shared/tinyusb/mp_cdc_common.c \
137136
shared/tinyusb/mp_usbd.c \
137+
shared/tinyusb/mp_usbd_cdc.c \
138138
shared/tinyusb/mp_usbd_descriptor.c \
139139
shared/tinyusb/mp_usbd_runtime.c \
140140

shared/tinyusb/mp_usbd_cdc.c

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2022 Ibrahim Abdelkader <iabdalkader@openmv.io>
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "py/runtime.h"
28+
#include "py/mphal.h"
29+
#include "py/mpconfig.h"
30+
#include "py/stream.h"
31+
#include "extmod/modmachine.h"
32+
33+
#if MICROPY_HW_USB_CDC && MICROPY_HW_ENABLE_USBDEV
34+
#include "tusb.h"
35+
#include "device/usbd.h"
36+
37+
#include "mp_usbd_cdc.h"
38+
#include "mp_usbd.h"
39+
40+
static uint8_t cdc_itf_pending; // keep track of cdc interfaces which need attention to poll
41+
42+
uintptr_t mp_usbd_cdc_poll_interfaces(uintptr_t poll_flags) {
43+
uintptr_t ret = 0;
44+
if (!cdc_itf_pending) {
45+
// Explicitly run the USB stack as the scheduler may be locked (eg we are in
46+
// an interrupt handler) while there is data pending.
47+
mp_usbd_task();
48+
}
49+
50+
// any CDC interfaces left to poll?
51+
if (cdc_itf_pending && ringbuf_free(&stdin_ringbuf)) {
52+
for (uint8_t itf = 0; itf < 8; ++itf) {
53+
if (cdc_itf_pending & (1 << itf)) {
54+
tud_cdc_rx_cb(itf);
55+
if (!cdc_itf_pending) {
56+
break;
57+
}
58+
}
59+
}
60+
}
61+
if ((poll_flags & MP_STREAM_POLL_RD) && ringbuf_peek(&stdin_ringbuf) != -1) {
62+
ret |= MP_STREAM_POLL_RD;
63+
}
64+
if ((poll_flags & MP_STREAM_POLL_WR) && tud_cdc_connected() && tud_cdc_write_available() > 0) {
65+
// When connected operate as blocking, only allow if space is available.
66+
ret |= MP_STREAM_POLL_WR;
67+
}
68+
return ret;
69+
}
70+
71+
void tud_cdc_rx_cb(uint8_t itf) {
72+
// consume pending USB data immediately to free usb buffer and keep the endpoint from stalling.
73+
// in case the ringbuffer is full, mark the CDC interface that need attention later on for polling
74+
cdc_itf_pending &= ~(1 << itf);
75+
for (uint32_t bytes_avail = tud_cdc_n_available(itf); bytes_avail > 0; --bytes_avail) {
76+
if (ringbuf_free(&stdin_ringbuf)) {
77+
int data_char = tud_cdc_read_char();
78+
#if MICROPY_KBD_EXCEPTION
79+
if (data_char == mp_interrupt_char) {
80+
// Clear the ring buffer
81+
stdin_ringbuf.iget = stdin_ringbuf.iput = 0;
82+
// and stop
83+
mp_sched_keyboard_interrupt();
84+
} else {
85+
ringbuf_put(&stdin_ringbuf, data_char);
86+
}
87+
#else
88+
ringbuf_put(&stdin_ringbuf, data_char);
89+
#endif
90+
} else {
91+
cdc_itf_pending |= (1 << itf);
92+
return;
93+
}
94+
}
95+
}
96+
97+
mp_uint_t mp_usbd_cdc_tx_strn(const char *str, mp_uint_t len) {
98+
size_t i = 0;
99+
if (tud_cdc_connected()) {
100+
while (i < len) {
101+
uint32_t n = len - i;
102+
if (n > CFG_TUD_CDC_EP_BUFSIZE) {
103+
n = CFG_TUD_CDC_EP_BUFSIZE;
104+
}
105+
int timeout = 0;
106+
// Wait with a max of USC_CDC_TIMEOUT ms
107+
while (n > tud_cdc_write_available() && timeout++ < MICROPY_HW_USB_CDC_TX_TIMEOUT) {
108+
mp_event_wait_ms(1);
109+
110+
// Explicitly run the USB stack as the scheduler may be locked (eg we
111+
// are in an interrupt handler), while there is data pending.
112+
mp_usbd_task();
113+
}
114+
if (timeout >= MICROPY_HW_USB_CDC_TX_TIMEOUT) {
115+
break;
116+
}
117+
uint32_t n2 = tud_cdc_write(str + i, n);
118+
tud_cdc_write_flush();
119+
i += n2;
120+
}
121+
}
122+
return i;
123+
}
124+
125+
#if MICROPY_HW_USB_CDC_1200BPS_TOUCH && MICROPY_HW_ENABLE_USBDEV
126+
127+
static mp_sched_node_t mp_bootloader_sched_node;
128+
129+
static void usbd_cdc_run_bootloader_task(mp_sched_node_t *node) {
130+
mp_hal_delay_ms(250);
131+
machine_bootloader(0, NULL);
132+
}
133+
134+
void
135+
#if MICROPY_HW_USB_EXTERNAL_TINYUSB
136+
mp_usbd_line_state_cb
137+
#else
138+
tud_cdc_line_state_cb
139+
#endif
140+
(uint8_t itf, bool dtr, bool rts) {
141+
if (dtr == false && rts == false) {
142+
// Device is disconnected.
143+
cdc_line_coding_t line_coding;
144+
tud_cdc_n_get_line_coding(itf, &line_coding);
145+
if (line_coding.bit_rate == 1200) {
146+
// Delay bootloader jump to allow the USB stack to service endpoints.
147+
mp_sched_schedule_node(&mp_bootloader_sched_node, usbd_cdc_run_bootloader_task);
148+
}
149+
}
150+
}
151+
152+
#endif
153+
#endif

shared/tinyusb/mp_cdc_common.c renamed to shared/tinyusb/mp_usbd_cdc.h

+10-31
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* The MIT License (MIT)
55
*
6-
* Copyright (c) 2022 Ibrahim Abdelkader <iabdalkader@openmv.io>
6+
* Copyright (c) 2022 Blake W. Felt & Angus Gratton
77
*
88
* Permission is hereby granted, free of charge, to any person obtaining a copy
99
* of this software and associated documentation files (the "Software"), to deal
@@ -24,37 +24,16 @@
2424
* THE SOFTWARE.
2525
*/
2626

27-
#include "py/runtime.h"
28-
#include "py/mphal.h"
29-
#include "extmod/modmachine.h"
27+
#ifndef MICROPY_INCLUDED_SHARED_TINYUSB_MP_USBD_CDC_H
28+
#define MICROPY_INCLUDED_SHARED_TINYUSB_MP_USBD_CDC_H
3029

31-
#if MICROPY_HW_USB_CDC_1200BPS_TOUCH && MICROPY_HW_ENABLE_USBDEV
32-
33-
#include "tusb.h"
30+
#ifndef MICROPY_HW_USB_CDC_TX_TIMEOUT
31+
#define MICROPY_HW_USB_CDC_TX_TIMEOUT (500)
32+
#endif
3433

35-
static mp_sched_node_t mp_bootloader_sched_node;
34+
uintptr_t mp_usbd_cdc_poll_interfaces(uintptr_t poll_flags);
35+
void tud_cdc_rx_cb(uint8_t itf);
36+
mp_uint_t mp_usbd_cdc_tx_strn(const char *str, mp_uint_t len);
3637

37-
static void usbd_cdc_run_bootloader_task(mp_sched_node_t *node) {
38-
mp_hal_delay_ms(250);
39-
machine_bootloader(0, NULL);
40-
}
4138

42-
void
43-
#if MICROPY_HW_USB_EXTERNAL_TINYUSB
44-
mp_usbd_line_state_cb
45-
#else
46-
tud_cdc_line_state_cb
47-
#endif
48-
(uint8_t itf, bool dtr, bool rts) {
49-
if (dtr == false && rts == false) {
50-
// Device is disconnected.
51-
cdc_line_coding_t line_coding;
52-
tud_cdc_n_get_line_coding(itf, &line_coding);
53-
if (line_coding.bit_rate == 1200) {
54-
// Delay bootloader jump to allow the USB stack to service endpoints.
55-
mp_sched_schedule_node(&mp_bootloader_sched_node, usbd_cdc_run_bootloader_task);
56-
}
57-
}
58-
}
59-
60-
#endif
39+
#endif // MICROPY_INCLUDED_SHARED_TINYUSB_MP_USBD_CDC_H

0 commit comments

Comments
 (0)