stm32/tinyusb: Add High-Speed USB support and fix CDC/VBUS issues.#26
Draft
andrewleech wants to merge 57 commits intomasterfrom
Draft
stm32/tinyusb: Add High-Speed USB support and fix CDC/VBUS issues.#26andrewleech wants to merge 57 commits intomasterfrom
andrewleech wants to merge 57 commits intomasterfrom
Conversation
|
Code size report: |
bb25aee to
4c3e95f
Compare
This commit updates the documentation for the `re` library, officially documenting non-capturing grouping rules (ie. "(?:...)"). The documentation mistakenly marked that feature as not supported, but is is indeed supported in the current iteration of the regex library. This closes micropython#18900. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
This reverts commit 046013a. Looks like since the latest round of GitHub Actions updates, the Cache LRU algorithm is working as designed again. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Both the overall IRQ line and the per-channel IRQ, for good measure. Otherwise, soft reset will remove the handler before the finaliser for the DMA object(s) run and trigger IRQs if the channel is still active. Closes micropython#18765 This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Small tweak to avoid changes in other targets' lockfiles from printing warnings when building esp32 port. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Not currently building, and too many versions to concurrently support. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Also rename the prefix from can to pyb_can, in anticipation of machine.CAN tests. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Closes micropython#18922 Signed-off-by: Angus Gratton <angus@redyak.com.au>
The function arguments mean totally different things for Classic vs FDCAN hardware, but the argument name wasn't particularly clear for either. This commit shouldn't really change the binary firmware at all. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Simplifies the pattern of an optional arg which can be a list of at least a certain length, otherwise one is lazily initialised. Modify pyb.CAN and ESP-NOW APIs to use the helper. Note this changes the return type of pyb.CAN.recv() from tuple to list. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
API is different to the original machine.CAN proposal, as numerous shortcomings were found during initial implementation. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
These are oddly missing from the STM32G4 HAL, but the reference manual describes being able to use them and the implementations seem to work as expected. Note that unlike STM32H7 it doesn't seem like we must use this approach, because HAL_FDCAN_AddMessageToTxFifoQ() does seem to not have the issues with priority inversion seen on the H7. However it's simpler to use the same API for both... Signed-off-by: Angus Gratton <angus@redyak.com.au> Signed-off-by: Angus Gratton <angus@redyak.com.au>
Implemented according to API docs in a parent comment. Adds new multi_extmod/machine_can_* tests which pass when testing between NUCLEO_G474RE, NUCLEO_H723ZG and PYBDV11. This work was mostly funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
The DAR register field is for auto-retransmit, FDCAN doesn't support automatic restart to clear Bus Off. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Some MCUs (eg N6) have more timers which are 32-bit, and it's best to use this macro to work that out. Signed-off-by: Damien George <damien@micropython.org>
This functionality already exists in the TIM code, and can be reused by the upcoming PWM implementation. Signed-off-by: Damien George <damien@micropython.org>
This commit implements the standard `machine.PWM` class on stm32, using the common bindings in `extmod/machine_pwm.c`. Features implemented are: - construct a PWM object from a pin, with automatic selection of TIM instance and channel; - get and set freq, duty_u16 and duty_ns; - optionally invert the output. The PWM objects are static objects (partly in ROM, partly in RAM) so creating a PWM instance on the same pin will return exactly the same object. That's consistent with other peripherals in the stm32 port, and consistent with other PWM implementations (eg rp2). When creating a PWM object on a pin, if that pin has multiple TIM instances then only the first will be selected. A future extension could allow selecting the TIM/channel (eg similar to how ADCBlock allows selecting an ADC). Signed-off-by: Damien George <damien@micropython.org>
When assigning a TIMx_CHy to a pin, the second available alternate function is chosen (or the first if there is only one). This gives better overall static allocation of TIM's to pins. On most MCUs (eg F4, F7, H5, H7) picking the second gives TIM5_CH[1-4] for PA0-PA3, and TIM5 is a 32-bit timer. That leaves TIM2 (also usually on PA0-PA3) for other pins that only have TIM2. For STM32G0, STM32L432 and STM32L452 the heuristic is to simply use the first available alternate function because that gives TIM2 (a 32-bit timer) on PA0-PA3. The above heuristic guarantees that PA0-PA3 always get a 32-bit timer on all supported MCUs. Signed-off-by: Damien George <damien@micropython.org>
To be slightly more accurate computing the expected low/high times for the PWM output. Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: Damien George <damien@micropython.org>
Intended to catch problems where new features don't build in old ESP-IDF. Includes major refactor to the GitHub Actions Workflow for esp32 port, including making a reusable workflow for both Code Size and ESP32 build jobs. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Signed-off-by: Damien George <damien@micropython.org>
This commit updates the listed limitations of the native emitter in the documentation related to how to increase speed of python code. Context managers are supported, as in functions marked as native can use the `with` statement in regular code. Generators can be used in native functions both on the emitting (ie. `yield <whatever>`) and on the receiving end. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
This commit fixes an issue related to the NimBLE initialisation procedure in low memory environments on ESP32 boards. MicroPython uses at least two different NimBLE stacks across the supported ports, mynewt (imported as an external library), and the one provided by Espressif in their own SDKs. The problem is that these two ports differ in the signature for `nimble_port_init(void)`, with mynewt returning `void`, and Espressif's returning a status code on failure. On ESP32 boards, allocating almost all the available heap and then turning on the Bluetooth stack would trigger a failure in the NimBLE initialisation function that is not handled by the NimBLE integration code, as there's no expectation of a recoverable condition. Since the stack initialisation would progress, then uninitialised memory accesses crash the board. Since we cannot really modify neither mynewt nor Espressif SDKs, the next best thing is to provide two conditional initialisation paths depending on a configuration setting. This would make Espressif ports recover from a failed initialisation whilst retaining the existing behaviour on other ports. This fixes micropython#14293. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
Because socket objects have a finaliser they must be created carefully, in case an exception is raised during the population of their members, eg invalid input argument or out-of-memory when allocating additional arrays. Prior to the fix in this commit, the finaliser would crash due to `incoming.udp_raw.array` being an invalid pointer in the following cases: - if a SOCK_RAW was created with a proto argument that was not an integer - if a SOCK_DGRAM or SOCK_RAW was created where the allocation of `lwip_incoming_packet_t` failed - if an integer was passed in for the socket type but it was not one of SOCK_STREAM, SOCK_DGRAM or SOCK_RAW Furthermore, if the allocation of `lwip_incoming_packet_t` failed then it may have led to corruption within lwIP when freeing `socket->pcb.raw` because that PCB was not fully set up with its callbacks. This commit fixes all of these issues by ensuring: - `pcb.tcp` and `incoming.udp_raw.array` are initialised to NULL early on - the proto argument is parsed before allocating the PCB - the allocation of `lwip_incoming_packet_t` occurs befor allocating the PCB - `incoming.udp_raw.array` is checked for NULL in the finaliser code The corresponding test (which already checked most of these causes of failure) has been updated to include a previously-uncovered scenario. Signed-off-by: Damien George <damien@micropython.org>
User callbacks allow code to respond to incoming messages without blocking or polling. User callbacks are optional, and if no callback is registered the code has no effect. The mechanism is the same as for TCP: when a connection is accepted or a TCP packet is received, a user callback is executed. Fixes issue micropython#3594. Signed-off-by: Jack Whitham <jack.d.whitham@gmail.com>
Add DMA, NPU and PDM IRQ priorities to irq.h. Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2.25k Seems necessary so it doesn't crash `thread/thread_stacksize1.py`. But 2.5k gives a little extra headroom to make that test actually pass. Signed-off-by: Damien George <damien@micropython.org>
With the recent addition of `machine.PWM` and `machine.CAN`, the internal flash of PYBD_SF3 overflows by about 300 bytes. This commit moves the inline assembler compiler functions from internal to external QSPI flash. That frees up about 3k internal flash, and shouldn't affect performance. Signed-off-by: Damien George <damien@micropython.org>
qstr literals are of type qstr_short_t (aka uint16_t) for efficiency, but when the type is passed to `mp_printf` it must be cast explicitly to type `qstr`. These locations were found using an experimental gcc plugin for `mp_printf` error checking. Signed-off-by: Jeff Epler <jepler@unpythonic.net>
This adds support for the standard `weakref` module, to make weak references to Python objects and have callbacks for when an object is reclaimed by the GC. This feature was requested by PyScript, to allow control over the lifetime of external proxy objects (distinct from JS<->Python proxies). Addresses issue micropython#646 (that's nearly a 12 year old issue!). Functionality added here: - `weakref.ref(object [, callback])` create a simple weak reference with optional callback to be called when the object is reclaimed by the GC - `weakref.finalize(object, callback, /, *args, **kwargs)` create a finalize object that holds a weak reference to an object and allows more convenient callback usage and state change The new module is enabled at the "everything" level. The implementation aims to be as efficient as possible, by adding another bit-per-block to the garbage collector, the WTB (weak table). Similar to the finalizer bit (FTB), if a GC block has its corresponding WTB bit set then a weak reference to that block is held. The details of that weak reference are stored in a global map, `mp_weakref_map`, which maps weak reference to ref/finalize objects, allowing the callbacks to be efficiently found when the object is reclaimed. With this feature enabled the overhead is: - 1/128th of the available memory is used for the new WTB table (eg a 128k heap now needs an extra 1k for the WTB). - Code size is increased. - At garbage collection time, there is a small overhead to check if the collected objects had weak references. This check is the same as the existing FTB finaliser scan, so shouldn't add much overhead. If there are weak reference objects alive (ref/finalize objects) then additional time is taken to call the callbacks and do some accounting to clean up the used weak reference. Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: Damien George <damien@micropython.org>
Needs a native exp file because native code doesn't print line numbers in the traceback. Signed-off-by: Damien George <damien@micropython.org>
Following a69425b, this is a convenient way to run a subset of tests. Signed-off-by: Damien George <damien@micropython.org>
The webassembly port needs some additional weakref tests due to the fact that garbage collection only happens when Python execution finishes and JavaScript resumes. The `tests/ports/webassembly/heap_expand.py` expected output also needs to be updated because the amount of GC heap got smaller (weakref WTB takes some of the available RAM). Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: Damien George <damien@micropython.org>
It takes longer now that weakref is enabled in the coverage build. Signed-off-by: Damien George <damien@micropython.org>
This brings in: - sdcard: Send stop bit after multi-block read/write - sdcard: Compute CRC7 for all SPI commands - sdcard: Add read/write speed test to sdtest - lsm6dsox: Add pedometer support - lsm6dsox: Add pedometer example code - unix-ffi/re: Handle PCRE2_UNSET in group and groups methods - unix-ffi/re: Add tests for empty string match in ffi regex - unix-ffi/machine: Retrieve a unique identifier if one is known - senml/docs: Correct capitalization of 'MicroPython' - unix-ffi/_libc: Extend FreeBSD libc versions range - string: Convert string module to package and import templatelib Signed-off-by: Damien George <damien@micropython.org>
If a port enables t-strings then it is required to have the `string.templatelib` package (at least to run the tests). That's automatically the case if `MICROPY_PY_TSTRINGS` is enabled. If a port freezes in the micropython-lib `string` extension package then the latest version of this package will include the built-in `string.templatelib` classes. So the feature check for t-strings no longer needs to check if they are available. Signed-off-by: Damien George <damien@micropython.org>
Includes a fix to STA teardown to deinit tcpip and clear itf_state. Signed-off-by: Damien George <damien@micropython.org>
Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
Signed-off-by: Dryw Wade <dryw.wade@sparkfun.com>
Signed-off-by: Matt Trentini <matthew.trentini@planetinnovation.com.au> Signed-off-by: Matt Trentini <matt.trentini@gmail.com>
Implements mapping from MICROPY_HW_USB_MAIN_DEV to TinyUSB RHPORT configuration, enabling board-specific USB PHY selection. Adds HS-in-FS mode support (High Speed controller running at Full Speed) which is the default for STM32 boards without external ULPI PHY. The RHPORT mode configuration is replicated directly in tusb_config.h using board configuration macros available at TinyUSB compilation stage, since the MICROPY_HW_TINYUSB_RHPORTx_MODE macros from mpconfigboard_common.h are not available when tusb_config.h is compiled. Supports all STM32 USB configurations: - Full-Speed only: RHPORT0 enabled, RHPORT1 disabled - High-Speed with ULPI: RHPORT0 disabled, RHPORT1 HS mode - High-Speed internal PHY: RHPORT0 disabled, RHPORT1 FS 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>
When a host closes and reopens the CDC serial port, the IN endpoint may remain stalled from a prior runtime USB disconnect (e.g. mpremote connect/disconnect cycles). Clear the stall on DTR high so the connection recovers without requiring a device reset. On DTR low (host close), flush the TX FIFO so stale data does not accumulate and block writes on the next connection. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
The TinyUSB serial descriptor used a raw hex dump of all 12 UID bytes in sequential order (24-char lowercase), while the legacy USB stack and ST's onboard DFU bootloader use a condensed algorithm that selects 6 bytes with two additions (12-char uppercase). This mismatch caused the device to report a different serial number depending on which USB stack was active, breaking tools that identify devices by serial (e.g. udev rules, mpremote, dfu-util). Use the ST DFU bootloader algorithm for consistency. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
4c3e95f to
1e59002
Compare
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #26 +/- ##
==========================================
+ Coverage 98.45% 98.46% +0.01%
==========================================
Files 175 176 +1
Lines 22635 22784 +149
==========================================
+ Hits 22286 22435 +149
Misses 349 349 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
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
The STM32 port's TinyUSB integration only supports the FS controller. Boards with a HS controller (PYBD_SF6, STM32F429DISC, OLIMEX_H407, or ULPI-based designs) cannot use TinyUSB — the RHPORT configuration is hardcoded to RHPORT 0 / full-speed only.
This PR adds proper RHPORT mode selection in
tusb_config.hbased onMICROPY_HW_USB_HSandMICROPY_HW_USB_HS_IN_FSboard config, routes HS IRQ handlers to the correct RHPORT (including STM32N6 which maps HS to RHPORT 0), and adds VBUS sensing configuration for the HS-in-FS path on STM32F4/F7 (mirroring the existing FS path, with support for both VBDEN and legacy NOVBUSSENS register variants).Additional issues found and fixed during testing (each is a separate commit and can be split into its own PR if preferred):
CDC reconnect stall: When a host closes and reopens the CDC serial port (e.g. repeated mpremote connect/disconnect cycles), the IN endpoint can remain stalled from a prior runtime USB disconnect. The device becomes unresponsive until reset. Fixed by clearing endpoint stall on DTR high. Additionally, on DTR low (host close) the TX FIFO is now flushed so stale data from a previous session does not accumulate and block writes on the next connection.
DFU bootloader serial number mismatch: The TinyUSB serial descriptor uses a raw hex dump of all 12 UID bytes (24-char lowercase), while the legacy USB stack and ST's onboard DFU bootloader use a condensed algorithm that selects 6 bytes with two additions (12-char uppercase). This causes the device to report a different serial number depending on which USB stack is active, breaking tools that identify devices by serial (udev rules, mpremote, dfu-util). Fixed by using the ST DFU bootloader algorithm.
TinyUSB-specific boot.py template: The factory reset boot.py template references
pyb.usb_mode()which does not exist on the TinyUSB stack. A TinyUSB-specific template is added that usesmachine.USBDevicewithBUILTIN_DEFAULT.Testing
Built with
CFLAGS_EXTRA=-DMICROPY_HW_TINYUSB_STACK=1for:machine.USBDeviceAPI, filesystem accessmachine.USBDeviceAPI, filesystem accessULPI boards (STM32H747I_DISCO) are tested on hardware as part of the original development in micropython#18303 — this branch is split out from that work.
CDC serial throughput (OPENMV_N6, HS link at 480 Mbit/s)
Compared TinyUSB vs legacy USB stack using
tests/serial_test.pymethodology.Read (device → host):
Write (host → device):
TinyUSB read is 6-12x faster. Write is 2.5-4.5x slower due to a pre-existing limitation in the TinyUSB CDC stdin path —
mp_hal_stdin_rx_chr()reads byte-by-byte through a 512-byte ringbuffer, causing backpressure on the USB OUT endpoint. This affects all TinyUSB ports, not just HS, and is being tracked separately.Trade-offs and Alternatives
The RHPORT configuration uses
#ifndefguards so boards like STM32N6 that pre-defineCFG_TUSB_RHPORT0_MODEinmpconfigboard_common.hpass through unchanged. This avoids needing per-family#ifchains but means any future HS-capable family (e.g. STM32U5) needs its own board-level override.