tinygo icon indicating copy to clipboard operation
tinygo copied to clipboard

rp2040: failed enumeration

Open tuffrabit opened this issue 1 year ago • 2 comments

Hello!

I'm trying to make a simple 4 switch keypad with a Seeed Studio XIAO RP2040. I can successfully compile with no errors or warnings, and then also (seemingly) successfully flash the device with the resulting uf2. The issue is, more often than not, the device after flashing fails to enumerate in Windows 10. I get the most success when I start with the device unplugged, boot, and then flash. It tends to work under those circumstances. If I reset the device using the reset button, it tends to fail. I can reproduce this with both v0.29 and v0.30, I haven't tried other versions of tinygo.

I've also tried adding println statements to debug over serial. When the device is in the failure state, the tinygo monitor is unable to locate the COM port. I'm happy to try other troubleshooting or debug steps, but I'm not versed enough with tinygo to know what would be useful here. In my perusing of the issues list, it seems like this could be related to this: https://github.com/tinygo-org/tinygo/issues/3012

Here's what device manager looks like when the device is in the failure state: tinygo_device_fail

Here's the code being compiled:

package main

import (
	"machine"
	"machine/usb"
	"machine/usb/hid/keyboard"
	"time"
)

func main() {
	button1 := machine.D0
	button1.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
	button2 := machine.D1
	button2.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
	button3 := machine.D2
	button3.Configure(machine.PinConfig{Mode: machine.PinInputPullup})
	button4 := machine.D3
	button4.Configure(machine.PinConfig{Mode: machine.PinInputPullup})

	kb := keyboard.Port()

	for {
		if !button1.Get() {
			kb.Down(keyboard.KeyW)
		} else {
			kb.Up(keyboard.KeyW)
		}
		
		if !button2.Get() {
			kb.Down(keyboard.KeyD)
		} else {
			kb.Up(keyboard.KeyD)
		}
		
		if !button3.Get() {
			kb.Down(keyboard.KeyS)
		} else {
			kb.Up(keyboard.KeyS)
		}
		
		if !button4.Get() {
			kb.Down(keyboard.KeyA)
		} else {
			kb.Up(keyboard.KeyA)
		}
		
		time.Sleep(25 * time.Millisecond)
	}
}

Here's the command I'm using to compile: tinygo build -target=xiao-rp2040 -o firmware.uf2 main.go

tuffrabit avatar Feb 19 '24 15:02 tuffrabit

Update.

Tested again on 0.31.1. This is easily reproducible on 0.31.1 as well.

tuffrabit avatar Mar 01 '24 14:03 tuffrabit

Having the exact same issue on linux while running basic hello world example... Did you manage to fix it? here is my dmesg, the board with rp2040 is custom designed

[163761.929936] usb 1-4: new full-speed USB device number 55 using xhci_hcd [163762.071677] usb 1-4: New USB device found, idVendor=2e8a, idProduct=0003, bcdDevice= 1.00 [163762.071692] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [163762.071698] usb 1-4: Product: RP2 Boot [163762.071703] usb 1-4: Manufacturer: Raspberry Pi [163762.071707] usb 1-4: SerialNumber: E0C9125B0D9B [163762.074544] usb-storage 1-4:1.0: USB Mass Storage device detected [163762.075164] scsi host0: usb-storage 1-4:1.0 [163763.090724] scsi 0:0:0:0: Direct-Access RPI RP2 3 PQ: 0 ANSI: 2 [163763.092928] sd 0:0:0:0: [sda] 262144 512-byte logical blocks: (134 MB/128 MiB) [163763.093885] sd 0:0:0:0: [sda] Write Protect is off [163763.093895] sd 0:0:0:0: [sda] Mode Sense: 03 00 00 00 [163763.094648] sd 0:0:0:0: [sda] No Caching mode page found [163763.094656] sd 0:0:0:0: [sda] Assuming drive cache: write through [163763.103462] sda: sda1 [163763.103973] sd 0:0:0:0: [sda] Attached SCSI removable disk [163763.630648] usb 1-4: USB disconnect, device number 55 [163763.630826] sd 0:0:0:0: [sda] tag#0 FAILED Result: hostbyte=DID_ERROR driverbyte=DRIVER_OK cmd_age=0s [163763.630830] sd 0:0:0:0: [sda] tag#0 CDB: Read(10) 28 00 00 00 03 08 00 00 f0 00 [163763.630832] I/O error, dev sda, sector 776 op 0x0:(READ) flags 0x84700 phys_seg 17 prio class 2 [163763.630852] device offline error, dev sda, sector 1016 op 0x0:(READ) flags 0x80700 phys_seg 1 prio class 2 [163763.630922] device offline error, dev sda, sector 776 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 2 [163763.630927] buffer_io_error: 14 callbacks suppressed [163763.630929] Buffer I/O error on dev sda, logical block 97, async page read [163763.949866] usb 1-4: new full-speed USB device number 56 using xhci_hcd [163764.073248] usb 1-4: device descriptor read/64, error -71 [163764.303389] usb 1-4: device descriptor read/64, error -71 [163764.533517] usb 1-4: new full-speed USB device number 57 using xhci_hcd [163764.659992] usb 1-4: device descriptor read/64, error -71 [163764.890046] usb 1-4: device descriptor read/64, error -71 [163764.996845] usb usb1-port4: attempt power cycle [163765.406714] usb 1-4: new full-speed USB device number 58 using xhci_hcd [163765.406938] usb 1-4: Device not responding to setup address. [163765.617284] usb 1-4: Device not responding to setup address. [163765.823434] usb 1-4: device not accepting address 58, error -71 [163765.947200] usb 1-4: new full-speed USB device number 59 using xhci_hcd [163765.947460] usb 1-4: Device not responding to setup address. [163766.154732] usb 1-4: Device not responding to setup address. [163766.360468] usb 1-4: device not accepting address 59, error -71 [163766.360704] usb usb1-port4: unable to enumerate USB device

VitRuzicka avatar Sep 08 '24 10:09 VitRuzicka

The rp2040 usb can be a little finicky depending on the version of the processor you are using.

See https://github.com/tinygo-org/tinygo/blob/release/src/machine/machine_rp2040_usb_fix_usb_device_enumeration.go#L10

That is not specific to TinyGo it is for all versions of rp2040 below a certain revision of the chip.

deadprogram avatar Dec 14 '24 08:12 deadprogram

I found a potential workaround for the USB enumeration issue.

Adding the following code to the handleUSBSetAddress function in machine_rp2040_usb.go resolved the "Unknown USB device" error on my Windows 11 Pro:

func handleUSBSetAddress(setup usb.Setup) bool {
    start := rp.TIMER.TIMERAWL.Get()
    target := start + (2 * 1000)
    for rp.TIMER.TIMERAWL.Get() < target {}
    // existing code

Image

This modification adjusts the timing of USB address setting. According to the USB specification, after receiving a SetAddress request, a device must set its new address before the next status stage, but the response time was too fast.

While this fix works in my environment, I don't have the proper testing equipment to verify if this is the correct approach. I would appreciate if others could test whether this has the same effect in their environments and provide feedback on the approach itself. If the effectiveness is confirmed, I would like to create a pull request for this fix.

rdon-key avatar Feb 18 '25 15:02 rdon-key

Tagging this issue to be closed after next release.

deadprogram avatar Mar 16 '25 09:03 deadprogram

Now closing with 0.37.0 release. Thanks!

deadprogram avatar Mar 19 '25 18:03 deadprogram