Repository navigation
Conversation
The PHY is off from SUSPEND, so RWAKEUP put no K state on the bus and the host never resumed. Turn it on first, as the vendor BSP does, and let the RESUME bus event end the suspended state instead of the macro.
Clearing a halt left DSQSYNC as it was, so the endpoint could answer with DATA1 and the host would drop the packet as a repeat. Clear it with SSTALL, as the vendor BSP does.
usb_lld_reset set up EP0 only, so the other hardware endpoints kept their configuration, data toggle, STALL and any transaction made ready before the reset, and the host could receive that data after it enumerated the device again. Clear the ready state, STALL and configuration of every endpoint first. The vendor BSP also resets the data toggle of all endpoints at a bus reset.
The interrupt handler served a SETUP before the endpoint events of the same INTSTS read, although those events belong to the transfers before the SETUP. A status stage completion handled against the new request stalled it or ended it early. Serve the endpoint events first, clear the control endpoint STALL at SETUP, and drop the endpoint events read together with a bus reset.
usb_lld_init_endpoint left CFGP unchanged, so a halt set by the host with SET_FEATURE stayed after SET_CONFIGURATION, which must reset the Halt feature (USB 2.0 9.4.5). Write CLRRDY to CFGP of both hardware endpoints first, which also clears SSTALL.
The hardware ACKs an OUT packet whose data toggle equals the last one accepted, and the driver passed it on as new data, so a packet resent after a lost ACK was received twice. Keep the toggle of the last accepted packet per endpoint, read EPSTS on each OUT event, and re-arm the endpoint without delivering a repeat (USB 2.0 8.6.4).
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.
This is a follow-on to @doombadroid's #454: six fixes to the NUC126 USB driver (
os/hal/ports/NUMICRO/LLD/USBv2). Each one has a practical effect. I run this driver in QMK on a Ducky One 3 RGB keyboard (NUC1261SG4AE; qmk/qmk_firmware#26499). Changes were directly tested where possible (2 & 3 come from spec reading) and adhere to the NUC126 Technical Reference Manual (Rev 1.04), Nuvoton's NUC126 BSP (OpenNuvoton/NUC126BSP) and the USB 2.0 specification.Commits and associated testing:
RWAKEUPput no K state on the bus.usb_lld_wakeup_hostalso called_usb_wakeup()itself, which marked the driver active while the bus was still suspended.SampleCode/StdDriver/USBD_HID_Mouse2/main.c, "Enable PHY before sending Resume('K') state".DSQSYNCwas left as it was, so after a halt was cleared the endpoint could answer with DATA1, and the host would drop the packet as a repeat (USB 2.0 9.4.5).usbd.c,USBD_StandardRequest, which clearsSSTALLandDSQSYNCtogether.usb_lld_resetset up EP0 only. The other hardware endpoints kept their configuration, data toggle, STALL and any transaction made ready before the reset, so the host could receive that data after it enumerated the device again (for example a key report from before a port reset).usbd.c,USBD_SwReset, which resets the data toggle of all eight endpoints. The STM32 LLDs also reset every endpoint inusb_lld_reset.INTSTSread, although those events belong to the transfer before the SETUP. A status stage completion handled against the new request stalled it or ended it early. The commit also drops the endpoint events read together with a bus reset, which were served after_usb_resethad cleared the endpoint configurations.device descriptor read/64, error -32,device not accepting address). With this commit and the same 1 ms wait, it enumerates.usbd.c,USBD_CtrlOut, andSampleCode/StdDriver/USBD_VCOM_and_HID_Keyboard/VCOM_and_HID_keyboard.c, which compareEPSTSwith the toggle of the last OUT packet.USBDEVFS_RESETEP): before, both packets were delivered, withEPSTSshowing OUT DATA0 ACK for each. After, the repeat isn't delivered, and the next DATA1 packet is.Apart from the endpoint mapping and register names, the NUC123 driver (
LLD/USBv1) has the same code, so these faults likely apply there too. I have no NUC123 hardware, so I haven't changed it.I made the review and these patches with Claude Code, an AI coding agent. The tests above ran on my keyboard.