rust-embedded-community / usb-device

Experimental device-side USB framework for microcontrollers in Rust.
MIT License
414 stars 77 forks source link

The USB set address request failed in debug build #80

Closed vklachkov closed 2 years ago

vklachkov commented 2 years ago

Hi!

I used your library in my project for STM32F411CEU and noticed that sometimes Windows shows error 43 in Device Manager. If reconnect device, then everything works as it should

To reproduce the issue, I plugged and popped the device several times. Sometimes it also occurred if leave the stm32 connected via USB and flash using st-link

image

vklachkov commented 2 years ago

My code is based on example...

static mut EP_MEMORY: [u32; 1024] = [0; 1024];

#[entry]
fn main() -> ! {
    rtt_init_print!();
    rprintln!("Hello!");

    let dp = pac::Peripherals::take().unwrap();

    let rcc = dp.RCC.constrain();

    let clocks = rcc
        .cfgr
        .use_hse(25.mhz())
        .sysclk(48.mhz())
        .require_pll48clk()
        .freeze();

    let gpioa = dp.GPIOA.split();
    let usb = USB {
        usb_global: dp.OTG_FS_GLOBAL,
        usb_device: dp.OTG_FS_DEVICE,
        usb_pwrclk: dp.OTG_FS_PWRCLK,
        pin_dm: gpioa.pa11.into_alternate(),
        pin_dp: gpioa.pa12.into_alternate(),
        hclk: clocks.hclk(),
    };

    let mut usb_bus = UsbBus::new(usb, unsafe { &mut EP_MEMORY });

    let mut serial = SerialPort::new(&usb_bus);

    let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd))
        .product("Serial port")
        .device_class(USB_CLASS_CDC)
        .build();

    loop {
        if !usb_dev.poll(&mut [&mut serial]) {
            continue;
        }

        let mut buf = [0u8; 64];

        match serial.read(&mut buf[..]) {
            Ok(count) => {}
            Err(UsbError::WouldBlock) => {}
            Err(err) => {}
        };

        match serial.write(&[0x3a, 0x29]) {
            Ok(count) => {}
            Err(UsbError::WouldBlock) => {}
            Err(err) => {}
        };
    }
}
vklachkov commented 2 years ago

Experimenting, I noticed that with an increase in frequency to 100mhz, the problem is no longer reproduced. And if you lower it to 25, then there is almost always an error when connecting.

vklachkov commented 2 years ago

I get dump from the usb using Wireshark. This dump contains errors and successful connection. STM32 freq is 25mhz rust-usb-cdc-bug.zip

mvirkkunen commented 2 years ago

By increasing the frequency, did you mean the sysclk frequency? Which hardware are you using? Have you tried running it in release mode just in case (although in this case it really shouldn't matter)?

The dump didn't seem to contain anything enumeration related, just a bunch of interrupt requests from another USB devide. At any rate this is very unlikely to be related to usbd-serial if the device doesn't even manage to enumerate, it's either got something to do with usb-device or synopsys-usb-otg.

vklachkov commented 2 years ago

@mvirkkunen

Yes, I mean sysclk. My chip is STM32F411CEU6. And yes, I always run in release No, in debug, I was wrong

Sorry, initially I took the dump incorrectly using wireshark. Recently updated the archive, there is a more correct dump. Although, nothing concrete and useful... I will try to write to the usb repository. If you don't have the error, then I'm sorry for the trouble

mvirkkunen commented 2 years ago

I was wondering about the entire hardware, is it custom or pre-existing board? Could it possibly have a power-on delay that causes an intermittent fault?

I can see the update dump now and it doesn't contain errors, it's possible that your recording setup doesn't see that type of low-level error.

usb-device is my repository as well so I'll just move this issue.

vklachkov commented 2 years ago

I am using a Chinese black pill. And everything works fine on firmware, written using C and CubeMX

image

vklachkov commented 2 years ago

Hypothetically, i can try to get the dump using a cheap logic analyzer, but I'm not sure that it will be able to work correctly with usb 2.0

vklachkov commented 2 years ago

I can't figure out what is what and whether my logical analyzer managed to capture data from usb

RUST USB CDC BUG.zip

mvirkkunen commented 2 years ago

This logic analyzer dump is nice, looks like your logic analyzer works just fine. It looks like the device is responding with a STALL to the SET_ADDRESS request after some time for some reason.

Can you paste your list of dependencies from Cargo.toml with the versions numbers?

vklachkov commented 2 years ago

Can you paste your list of dependencies from Cargo.toml with the versions numbers?

My Cargo.toml:

[package]
name = "motor"
version = "3.0.0"
edition = "2021"

[dependencies]
nb = "1"
cortex-m = "*"
cortex-m-rt = "*"
embedded-hal = "0.2"
usb-device = "0.2.8"
usbd-serial = "0.1.1"
rtt-target = { version = "0.3.1", features = ["cortex-m"] }
arraydeque = { version = "0.4", default-features = false }

[dependencies.stm32f4xx-hal]
version = "0.10"
features = ["stm32f411", "rt", "usb_fs"]
vklachkov commented 2 years ago

@mvirkkunen

I'm sorry, I made a mistake. Before that, I started the project in debug mode using the cargo-embed --chip stm32f411ceu command. After I started launching the project via cargo-embed --chip stm32f411ceu --release, the problem went away even at low frequencies. But this is still wrong behavior, I think

mvirkkunen commented 2 years ago

Yes, it's odd. Even though debug mode Rust is slow, you're not doing anything else, and it shouldn't be that slow. Also, the dump shows a STALL condition, not a timeout from what I could tell from a quick look. I'll have to take a look at this more when I have time, I have some of the exact same board too.

vklachkov commented 2 years ago

If this problem is solved one day, I will be glad. Thank you for communicating! For now, I will work in the release and use your rtt library for debugging

My friend sent me such a link when I described my problem to him: https://community.st.com/s/question/0D50X0000B8jzZL/why-does-the-stm32f407-send-a-stall-on-usbfs

mvirkkunen commented 2 years ago

Yeah there are some weird race conditions in debug mode still it seems. What comes to debugging, stopping the device or even using semihosting is just a plain non-starter because USB has somewhat strict timeouts. I pretty much made the first version of the RTT library specifically for debugging USB, because semihosting was too slow and I didn't want to use an extra serial port.

I can't see what's behind the link, because I don't know what Discord server it is and I don't think it allows you to see messages unless I join the server.

vklachkov commented 2 years ago

Yeah there are some weird race conditions in debug mode still it seems. What comes to debugging, stopping the device or even using semihosting is just a plain non-starter because USB has somewhat strict timeouts. I pretty much made the first version of the RTT library specifically for debugging USB, because semihosting was too slow and I didn't want to use an extra serial port.

I can't see what's behind the link, because I don't know what Discord server it is and I don't think it allows you to see messages unless I join the server.

Excuse me. Corrected the link. It's time for me to sleep)

mvirkkunen commented 2 years ago

The Synopsys OTG IP is very fragile and easily breaks down in surprising ways when it's not handled exactly as the IP authors intended, even if you'd think your actions are reasonable.

mmm, sounds very nice indeed

vklachkov commented 2 years ago

mmm, sounds very nice indeed

Another surprise from stm32) It's amazing why nobody didn't encounter this problem besides me

Disasm commented 2 years ago

It's quite an old problem, there is even a warning which (unfortunately) doesn't work unless you build the firmware from a workspace which includes synopsys-usb-otg: https://github.com/stm32-rs/synopsys-usb-otg/blob/master/build.rs#L5-L7

mvirkkunen commented 2 years ago

It's possible people have just assumed it was because debug mode is slow and can break in weird ways, and never looked at it with a logic analyzer to see the surprise STALL status. This report might be a better fit for the Synopsys driver repo, unfortunately you can't move an issue to another org.

vklachkov commented 2 years ago

It's possible people have just assumed it was because debug mode is slow and can break in weird ways, and never looked at it with a logic analyzer to see the surprise STALL status. This report might be a better fit for the Synopsys driver repo, unfortunately you can't move an issue to another org.

I can write anywhere, summarizing everything written, if it helps a little in solving the problem.

vklachkov commented 2 years ago

Should I drop it here? https://github.com/stm32-rs/synopsys-usb-otg Or where it will be more convenient

Disasm commented 2 years ago

Yes, this is the right place.

vklachkov commented 2 years ago

Close issue here...

vklachkov commented 2 years ago

And open here https://github.com/stm32-rs/synopsys-usb-otg/issues/21