10000 ports/esp32: Use shared/tinyusb integration. · micropython/micropython@7bd0870 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7bd0870

Browse files
committed
ports/esp32: Use shared/tinyusb integration.
Uses newer libusb synopsys/dwc2 driver rather than the IDF tinyusb component. Signed-off-by: Andrew Leech <andrew@alelec.net>
1 parent aff686c commit 7bd0870

File tree

10 files changed

+171
-66
lines changed

10 files changed

+171
-66
lines changed

ports/esp32/esp32_common.cmake

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,32 @@ list(APPEND MICROPY_SOURCE_DRIVERS
5252
${MICROPY_DIR}/drivers/dht/dht.c
5353
)
5454

55+
if(MICROPY_PY_TINYUSB)
56+
set(TINYUSB_SRC "${MICROPY_DIR}/lib/tinyusb/src")
57+
string(TOUPPER OPT_MCU_${IDF_TARGET} tusb_mcu)
58+
59+
list(APPEND MICROPY_DEF_CORE
60+
CFG_TUSB_MCU=${tusb_mcu}
61+
)
62+
63+
list(APPEND MICROPY_SOURCE_LIB
64+
${TINYUSB_SRC}/tusb.c
65+
${TINYUSB_SRC}/common/tusb_fifo.c
66+
${TINYUSB_SRC}/device/usbd.c
67+
${TINYUSB_SRC}/device/usbd_control.c
68+
${TINYUSB_SRC}/class/cdc/cdc_device.c
69+
${TINYUSB_SRC}/portable/synopsys/dwc2/dcd_dwc2.c
70+
${MICROPY_DIR}/shared/tinyusb/mp_usbd.c
71+
${MICROPY_DIR}/shared/tinyusb/mp_usbd_cdc.c
72+
${MICROPY_DIR}/shared/tinyusb/mp_usbd_descriptor.c
73+
)
74+
75+
list(APPEND MICROPY_INC_CORE
76+
${TINYUSB_SRC}
77+
${MICROPY_DIR}/shared/tinyusb/
78+
)
79+
endif()
80+
5581
list(APPEND MICROPY_SOURCE_PORT
5682
adc.c
5783
main.c
@@ -100,6 +126,7 @@ list(APPEND MICROPY_SOURCE_QSTR
100126
${MICROPY_SOURCE_BOARD}
101127
)
102128

129+
103130
list(APPEND IDF_COMPONENTS
104131
app_update
105132
bootloader_support
@@ -132,6 +159,7 @@ list(APPEND IDF_COMPONENTS
132159
soc
133160
spi_flash
134161
ulp
162+
usb
135163
vfs
136164
)
137165

ports/esp32/main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include "shared/readline/readline.h"
5353
#include "shared/runtime/pyexec.h"
5454
#include "shared/timeutils/timeutils.h"
55+
#include "shared/tinyusb/mp_usbd.h"
5556
#include "mbedtls/platform_time.h"
5657

5758
#include "uart.h"
@@ -99,7 +100,7 @@ void mp_task(void *pvParameter) {
99100
#endif
100101
#if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
101102
usb_serial_jtag_init();
102-
#elif CONFIG_USB_OTG_SUPPORTED
103+
#elif MICROPY_HW_ENABLE_USBDEV
103104
usb_init();
104105
#endif
105106
#if MICROPY_HW_ENABLE_UART_REPL

ports/esp32/main_esp32s2/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ if(NOT MICROPY_PORT_DIR)
88
get_filename_component(MICROPY_PORT_DIR ${MICROPY_DIR}/ports/esp32 ABSOLUTE)
99
endif()
1010

11+
set(MICROPY_PY_TINYUSB ON)
12+
1113
include(${MICROPY_PORT_DIR}/esp32_common.cmake)

ports/esp32/main_esp32s3/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ if(NOT MICROPY_PORT_DIR)
88
get_filename_component(MICROPY_PORT_DIR ${MICROPY_DIR}/ports/esp32 ABSOLUTE)
99
endif()
1010

11+
set(MICROPY_PY_TINYUSB ON)
12+
1113
include(${MICROPY_PORT_DIR}/esp32_common.cmake)

ports/esp32/mpconfigport.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,70 @@
197197

198198
#define MP_STATE_PORT MP_STATE_VM
199199

200+
#if CONFIG_USB_OTG_SUPPORTED
201+
#ifndef MICROPY_HW_ENABLE_USBDEV
202+
#define MICROPY_HW_ENABLE_USBDEV (1)
203+
#endif
204+
#endif
205+
206+
#if MICROPY_HW_ENABLE_USBDEV
207+
#define MICROPY_SCHEDULER_STATIC_NODES (1)
208+
209+
// Enable USB-CDC serial port
210+
#ifndef MICROPY_HW_USB_CDC
211+
#define MICROPY_HW_USB_CDC (1)
212+
#endif
213+
214+
#ifndef MICROPY_HW_USB_DESC_STR_MAX
215+
#define MICROPY_HW_USB_DESC_STR_MAX (16)
216+
#endif
217+
218+
#ifndef MICROPY_HW_USB_VID
219+
#define USB_ESPRESSIF_VID 0x303A
220+
#if CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID
221+
#define MICROPY_HW_USB_VID (USB_ESPRESSIF_VID)
222+
#else
223+
#define MICROPY_HW_USB_VID (CONFIG_TINYUSB_DESC_CUSTOM_VID)
224+
#endif
225+
#endif
226+
227+
#ifndef MICROPY_HW_USB_PID
228+
#if CONFIG_TINYUSB_DESC_USE_DEFAULT_PID
229+
#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
230+
// A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
231+
// Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
232+
// Auto ProductID layout's Bitmap:
233+
// [MSB] HID | MSC | CDC [LSB]
234+
#define USB_TUSB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
235+
_PID_MAP(MIDI, 3)) // | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) )
236+
#define MICROPY_HW_USB_PID (USB_TUSB_PID)
237+
#else
238+
#define MICROPY_HW_USB_PID (CONFIG_TINYUSB_DESC_CUSTOM_PID)
239+
#endif
240+
#endif
241+
242+
#ifndef MICROPY_HW_USB_MANUFACTURER_STRING
243+
#ifdef CONFIG_TINYUSB_DESC_MANUFACTURER_STRING
244+
#define MICROPY_HW_USB_MANUFACTURER_STRING CONFIG_TINYUSB_DESC_MANUFACTURER_STRING
245+
#else
246+
#define MICROPY_HW_USB_MANUFACTURER_STRING "MicroPython"
247+
#endif
248+
#endif
249+
250+
#ifndef MICROPY_HW_USB_PRODUCT_FS_STRING
251+
#ifdef CONFIG_TINYUSB_DESC_PRODUCT_STRING
252+
#define MICROPY_HW_USB_PRODUCT_FS_STRING CONFIG_TINYUSB_DESC_PRODUCT_STRING
253+
#else
254+
#define MICROPY_HW_USB_PRODUCT_FS_STRING "Board in FS mode"
255+
#endif
256+
#endif
257+
258+
#define MICROPY_HW_USBDEV_TASK_HOOK extern void mp_usbd_task(void); mp_usbd_task();
259+
#else
260+
#define MICROPY_HW_USBDEV_TASK_HOOK
261+
#endif
262+
263+
200264
// type definitions for the specific machine
201265

202266
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p)))
@@ -216,6 +280,7 @@ void *esp_native_code_commit(void *, size_t, void *);
216280
extern void mp_handle_pending(bool); \
217281
mp_handle_pending(true); \
218282
MICROPY_PY_SOCKET_EVENTS_HANDLER \
283+
MICROPY_HW_USBDEV_TASK_HOOK \
219284
MP_THREAD_GIL_EXIT(); \
220285
ulTaskNotifyTake(pdFALSE, 1); \
221286
MP_THREAD_GIL_ENTER(); \
@@ -226,6 +291,7 @@ void *esp_native_code_commit(void *, size_t, void *);
226291
extern void mp_handle_pending(bool); \
227292
mp_handle_pending(true); \
228293
MICROPY_PY_SOCKET_EVENTS_HANDLER \
294+
MICROPY_HW_USBDEV_TASK_HOOK \
229295
asm ("waiti 0"); \
230296
} while (0);
231297
#endif

ports/esp32/mphalport.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
#include "extmod/misc.h"
4343
#include "shared/timeutils/timeutils.h"
4444
#include "shared/runtime/pyexec.h"
45+
#include "shared/tinyusb/mp_usbd.h"
46+
#include "shared/tinyusb/mp_usbd_cdc.h"
4547
#include "mphalport.h"
4648
#include "usb.h"
4749
#include "usb_serial_jtag.h"
@@ -103,11 +105,20 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
103105
#if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
104106
usb_serial_jtag_poll_rx();
105107
#endif
106-
if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) {
108+
#if MICROPY_HW_USB_CDC
109+
mp_usbd_cdc_poll_interfaces();
110+
#endif
111+
if ((poll_flags & MP_STREAM_POLL_RD) && ringbuf_peek(&stdin_ringbuf) != -1) {
107112
ret |= MP_STREAM_POLL_RD;
108113
}
109114
if (poll_flags & MP_STREAM_POLL_WR) {
115+
#if MICROPY_HW_USB_CDC && !MICROPY_HW_ENABLE_UART_REPL
116+
if (tud_cdc_connected() && tud_cdc_write_available() > 0) {
117+
ret |= MP_STREAM_POLL_WR;
118+
}
119+
#else
110120
ret |= MP_STREAM_POLL_WR;
121+
#endif
111122
}
112123
return ret;
113124
}
@@ -117,6 +128,9 @@ int mp_hal_stdin_rx_chr(void) {
117128
#if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
118129
usb_serial_jtag_poll_rx();
119130
#endif
131+
#if MICROPY_HW_USB_CDC
132+
mp_usbd_cdc_poll_interfaces();
133+
#endif
120134
int c = ringbuf_get(&stdin_ringbuf);
121135
if (c != -1) {
122136
return c;
@@ -136,9 +150,12 @@ mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) {
136150
#if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
137151
usb_serial_jtag_tx_strn(str, len);
138152
did_write = true;
139-
#elif CONFIG_USB_OTG_SUPPORTED
140-
usb_tx_strn(str, len);
141-
did_write = true;
153+
#elif MICROPY_HW_USB_CDC
154+
mp_uint_t cdc_res = mp_usbd_cdc_tx_strn(str, len);
155+
if (cdc_res > 0) {
156+
did_write = true;
157+
ret = MIN(cdc_res, ret);
158+
}
142159
#endif
143160
#if MICROPY_HW_ENABLE_UART_REPL
144161
uart_stdout_tx_strn(str, len);

ports/esp32/mphalport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252

5353
extern TaskHandle_t mp_main_task_handle;
5454

55+
extern int mp_interrupt_char;
5556
extern ringbuf_t stdin_ringbuf;
5657

5758
// Check the ESP-IDF error code and raise an OSError if it's not ESP_OK.

ports/esp32/usb.c

Lines changed: 48 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -28,76 +28,65 @@
2828
#include "py/mphal.h"
2929
#include "usb.h"
3030

31-
#if CONFIG_USB_OTG_SUPPORTED && !CONFIG_ESP_CONSOLE_USB_CDC && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
31+
#if CONFIG_USB_OTG_SUPPORTED && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
32+
#include "esp_rom_gpio.h"
33+
#include "esp_mac.h"
34+
#include "esp_private/usb_phy.h"
3235

33-
#include "esp_timer.h"
34-
#ifndef NO_QSTR
35-
#include "tinyusb.h"
36-
#include "tusb_cdc_acm.h"
37-
#endif
36+
#include "shared/tinyusb/mp_usbd.h"
3837

39-
#define CDC_ITF TINYUSB_CDC_ACM_0
38+
#define EXTERNAL_PHY 0
39+
#define SELF_POWERED 0
4040

41-
static uint8_t usb_rx_buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE];
41+
static usb_phy_handle_t phy_hdl;
4242

43-
// This is called from FreeRTOS task "tusb_tsk" in espressif__esp_tinyusb (not an ISR).
44-
static void usb_callback_rx(int itf, cdcacm_event_t *event) {
45-
// espressif__esp_tinyusb places tinyusb rx data onto freertos ringbuffer which
46-
// this function forwards onto our stdin_ringbuf.
47-
for (;;) {
48-
size_t len = 0;
49-
esp_err_t ret = tinyusb_cdcacm_read(itf, usb_rx_buf, sizeof(usb_rx_buf), &len);
50-
if (ret != ESP_OK) {
51-
break;
52-
}
53-
if (len == 0) {
54-
break;
55-
}
56-
for (size_t i = 0; i < len; ++i) {
57-
if (usb_rx_buf[i] == mp_interrupt_char) {
58-
mp_sched_keyboard_interrupt();
59-
} else {
60-
ringbuf_put(&stdin_ringbuf, usb_rx_buf[i]);
61-
}
62-
}
63-
mp_hal_wake_main_task();
64-
}
65-
}
6643

6744
void usb_init(void) {
68-
// Initialise the USB with defaults.
69-
tinyusb_config_t tusb_cfg = {0};
70-
ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
45+
// ref: https://github.com/espressif/esp-usb/blob/4b6a798d0bed444fff48147c8dcdbbd038e92892/device/esp_tinyusb/tinyusb.c
7146

72-
// Initialise the USB serial interface.
73-
tinyusb_config_cdcacm_t acm_cfg = {
74-
.usb_dev = TINYUSB_USBDEV_0,
75-
.cdc_port = CDC_ITF,
76-
.rx_unread_buf_sz = 256,
77-
.callback_rx = &usb_callback_rx,
78-
#ifdef MICROPY_HW_USB_CUSTOM_RX_WANTED_CHAR_CB
79-
.callback_rx_wanted_char = &MICROPY_HW_USB_CUSTOM_RX_WANTED_CHAR_CB,
80-
#endif
81-
#ifdef MICROPY_HW_USB_CUSTOM_LINE_STATE_CB
82-
.callback_line_state_changed = &MICROPY_HW_USB_CUSTOM_LINE_STATE_CB,
83-
#endif
84-
#ifdef MICROPY_HW_USB_CUSTOM_LINE_CODING_CB
85-
.callback_line_coding_changed = &MICROPY_HW_USB_CUSTOM_LINE_CODING_CB,
86-
#endif
47+
// Configure USB PHY
48+
usb_phy_config_t phy_conf = {
49+
.controller = USB_PHY_CTRL_OTG,
50+
.otg_mode = USB_OTG_MODE_DEVICE,
8751
};
88-
ESP_ERROR_CHECK(tusb_cdc_acm_init(&acm_cfg));
8952

90-
}
53+
#if EXTERNAL_PHY
54+
// External PHY IOs config
55+
usb_phy_ext_io_conf_t ext_io_conf = {
56+
.vp_io_num = USBPHY_VP_NUM,
57+
.vm_io_num = USBPHY_VM_NUM,
58+
.rcv_io_num = USBPHY_RCV_NUM,
59+
.oen_io_num = USBPHY_OEN_NUM,
60+
.vpo_io_num = USBPHY_VPO_NUM,
61+
.vmo_io_num = USBPHY_VMO_NUM,
62+
};
63+
phy_conf.target = USB_PHY_TARGET_EXT;
64+
phy_conf.ext_io_conf = &ext_io_conf;
65+
#else
66+
phy_conf.target = USB_PHY_TARGET_INT;
67+
#endif
9168

92-
void usb_tx_strn(const char *str, size_t len) {
93-
// Write out the data to the CDC interface, but only while the USB host is connected.
94-
uint64_t timeout = esp_timer_get_time() + (uint64_t)(MICROPY_HW_USB_CDC_TX_TIMEOUT_MS * 1000);
95-
while (tud_cdc_n_connected(CDC_ITF) && len && esp_timer_get_time() < timeout) {
96-
size_t l = tinyusb_cdcacm_write_queue(CDC_ITF, (uint8_t *)str, len);
97-
str += l;
98-
len -= l;
99-
tud_cdc_n_write_flush(CDC_ITF);
69+
#if SELF_POWERED
70+
// OTG IOs config
71+
const usb_phy_otg_io_conf_t otg_io_conf = USB_PHY_SELF_POWERED_DEVICE(config->vbus_monitor_io);
72+
if (config->self_powered) {
73+
phy_conf.otg_io_conf = &otg_io_conf;
10074
}
75+
#endif
76+
// Init ESP USB Phy
77+
usb_new_phy(&phy_conf, &phy_hdl);
78+
79+
// Init MicroPython / TinyUSB
80+
mp_usbd_init();
81+
82+
}
83+
84+
void mp_usbd_port_get_serial_number(char *serial_buf) {
85+
// use factory default MAC as serial ID
86+
uint8_t mac[8];
87+
esp_efuse_mac_get_default(mac);
88+
MP_STATIC_ASSERT(sizeof(mac) * 2 <= MICROPY_HW_USB_DESC_STR_MAX);
89+
mp_usbd_hex_str(serial_buf, mac, sizeof(mac));
10190
}
10291

10392
#endif // CONFIG_USB_OTG_SUPPORTED && !CONFIG_ESP_CONSOLE_USB_CDC && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG

ports/esp32/usb.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,5 @@
2929
#define MICROPY_HW_USB_CDC_TX_TIMEOUT_MS (500)
3030

3131
void usb_init(void);
32-
void usb_tx_strn(const char *str, size_t len);
3332

3433
#endif // MICROPY_INCLUDED_ESP32_USB_H

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[tool.codespell]
22
count = ""
33
ignore-regex = '\b[A-Z]{3}\b'
4-
ignore-words-list = "ans,asend,deques,dout,extint,hsi,iput,mis,numer,shft,technic,ure"
4+
ignore-words-list = "ans,asend,deques,dout,extint,hsi,iput,mis,numer,shft,synopsys,technic,ure"
55
quiet-level = 3
66
skip = """
77
*/build*,\

0 commit comments

Comments
 (0)
0