shared/tinyusb, extmod: Add USB Network (NCM) with runtime class selection.#31
Draft
andrewleech wants to merge 12 commits intoreview/stm32_tinyusb_ncmfrom
Draft
shared/tinyusb, extmod: Add USB Network (NCM) with runtime class selection.#31andrewleech wants to merge 12 commits intoreview/stm32_tinyusb_ncmfrom
andrewleech wants to merge 12 commits intoreview/stm32_tinyusb_ncmfrom
Conversation
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## review/stm32_tinyusb_ncm #31 +/- ##
=========================================================
Coverage 98.46% 98.46%
=========================================================
Files 176 176
Lines 22784 22784
=========================================================
Hits 22435 22435
Misses 349 349 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
85a5948 to
739c2f6
Compare
|
Code size report: |
f04861e to
7d1a1ed
Compare
7d1a1ed to
0e91c61
Compare
Provides atoi() function implementation required by lwIP's netif_find() function when using string-based network interface lookup. Based on (MIT) implementation from https://github.com/littlekernel/lk Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
When false, the DHCP server omits the Router option from DHCP responses. This prevents point-to-point links (like USB NCM) from advertising a default gateway that hijacks the host's internet route. Defaults to true for backward compatibility with CYW43 AP mode. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Consolidates TinyUSB source includes across multiple ports (alif, mimxrt, renesas-ra, samd) to use a common approach for TinyUSB integration. This cleanup ensures consistent TinyUSB usage patterns across ports and simplifies maintenance. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Adds TinyUSB configuration and descriptor support for USB Network Control Model (NCM) interface. This provides the low-level USB infrastructure needed for USB networking. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
0e91c61 to
aa04ebe
Compare
Implements a complete USB Network Control Model (NCM) driver that provides ethernet-over-USB functionality integrated with lwIP stack. Features: - Link-local IP address generation from MAC using CRC32 - DHCP server integration with connect callbacks - Full lwIP network interface with IPv6 support - USB NCM protocol handling via TinyUSB - Python network.USB_NET class interface Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Automatically enable MICROPY_HW_NETWORK_USBNET when MICROPY_PY_LWIP is enabled, following the same pattern as WEBSOCKET and WEBREPL. This makes USB networking available by default on boards that support both USB device mode and LWIP networking, while still allowing boards to explicitly disable it by setting MICROPY_HW_NETWORK_USBNET=0. Also fixes USB NCM build issues when LWIP is enabled for ethernet by making MICROPY_HW_NETWORK_USBNET conditional on both LWIP and TinyUSB. Signed-off-by: Andrew Leech <andrew@alelec.net>
Add builtin_driver flag constants (BUILTIN_FLAG_CDC, BUILTIN_FLAG_MSC, BUILTIN_FLAG_NCM) that can be OR'd together to select USB classes at runtime from boot.py. A dynamic configuration descriptor is built containing only the selected classes with compact interface/endpoint numbering. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
usbd_conf.c unconditionally includes shared/tinyusb/mp_usbd.h which pulls in tusb.h when MICROPY_HW_ENABLE_USBDEV is set. The BUILDING_MBOOT guard that disables TinyUSB comes after the include, so mboot builds fail with missing tusb.h. Guard the include with !BUILDING_MBOOT. Also add forward declaration of mp_usbd_ll_init() next to the MICROPY_HW_TINYUSB_LL_INIT macro in mpconfigboard_common.h, since the function is used in an inline function in mp_usbd.h but only declared in the port-specific usbd_conf.h. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
aa04ebe to
04ef70d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This adds USB networking via NCM (Network Control Model) and a runtime USB class selection API. The work is in four phases that could be split into separate PRs, though phases 1-3 are dependent on prior work so would need to stay stacked.
Background network support - a couple of small prerequisites: a weak
atoi()implementation for lwIP'snetif_find(), consolidating TinyUSB source includes across port Makefiles to use upstreamtinyusb.mk, asend_routerflag on the DHCP server so point-to-point links don't advertise a default gateway (which hijacks the host's internet route), makingLWIP_IPV6configurable on stm32, and movingmod_network_init()earlier in stm32's boot sequence so the netif is ready before USB enumeration.NCM implementation - the actual
network.USB_NETdriver. It provides a USB Ethernet adapter via NCM that the host sees immediately on plug-in. The device runs a DHCP server and optionally mDNS so the host gets an IP and can reach the device without any manual config. The netif is auto-initialised at boot (beforetusb_init()) because TinyUSB's NCM driver starts receiving as soon as the host sends SET_INTERFACE, which happens during enumeration before any Python code runs. NCM is auto-enabled on any port with lwIP and TinyUSB.Runtime USB class selection - integer flag constants (
BUILTIN_FLAG_CDC,BUILTIN_FLAG_MSC,BUILTIN_FLAG_NCM) that can be OR'd together and assigned tomachine.USBDevice.builtin_driverin boot.py. This builds a dynamic configuration descriptor containing only the selected classes with compact interface/endpoint numbering. The PID is varied per combination so the host re-enumerates correctly.BUILTIN_DEFAULTis now CDC-only, MSC and NCM are opt-in. WithoutRUNTIME_DEVICE(ie. nomachine.USBDevice) all compiled-in classes are exposed by default.TinyUSB fixes - VBUS sensing fix for newer STM32F4/F7 HAL versions that have the
VBDENregister bit, and a mboot build fix for TinyUSB-enabled boards.Testing
Tested on NUCLEO_WB55 (stm32 with TinyUSB + lwIP) with both
RUNTIME_DEVICE=1andRUNTIME_DEVICE=0. NCM interface enumerates on Linux host, DHCP assigns an address, ping works at ~1.8ms RTT. Flag-mask class selection tested with CDC-only and CDC+NCM combinations.Not tested on mimxrt, renesas-ra, samd, rp2 (build-tested only via the auto-enable logic). The descriptor patch offset tables for the dynamic builder haven't been verified against TinyUSB versions other than the current submodule.
Trade-offs and Alternatives
The descriptor builder uses hardcoded byte-offset patch tables derived from TinyUSB's
TUD_*_DESCRIPTORmacro output. This is fragile across TinyUSB updates but pretty much unavoidable without TinyUSB exposing a programmatic descriptor API. The offset tables include a comment noting this dependency.The previous
usbd_netbranch used an opaque C type with an internal flags byte for class selection, requiring casting in the descriptor callback. The integer flag approach here is simpler at both the Python and C level.Generative AI
I used generative AI tools when creating this PR, but a human has checked the
code and is responsible for the code and the description above.