stm32-rs / synopsys-usb-otg

usb-device implementation for Synopsys USB OTG IP cores
MIT License
41 stars 29 forks source link

Unable to enumerate on a STM32F446RE using the FS peripheral #2

Closed thousandeyes-fwieland closed 4 years ago

thousandeyes-fwieland commented 4 years ago

I'm using code very similar to that from the F446ZE plus a homemade breakout board, from a Nucleo F446RE. The USB functionality works and I can prove it by flashing an mbed program instead.

Here I try to make a simple serial echo program. What actually happens is that the onboard LED flashes momentarily after connecting the board to my laptop, but nothing else happens and the board remains powered.

Actual code:

        // Set up the clocks - which is kinda sensitive
        let rcc = dp.RCC.constrain();
        let clocks = rcc.cfgr
            .use_hse(8.mhz())
            .sysclk(48.mhz())
            .pclk1(24.mhz())
            .require_pll48clk()
            .freeze();

        // Enable the appropriate GPIOs

        let gpioa = dp.GPIOA.split();
        let mut led = gpioa.pa5.into_push_pull_output();
        led.set_high().unwrap();

        // USB time
        let peripheral = Peripheral {
            usb_global: dp.OTG_FS_GLOBAL,
            usb_device: dp.OTG_FS_DEVICE,
            usb_pwrclk: dp.OTG_FS_PWRCLK,
            pin_dm: gpioa.pa11.into_alternate_af10(),
            pin_dp: gpioa.pa12.into_alternate_af10(),
        };

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

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

        let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0xcafe, 0xf00d))
            .manufacturer("TEST")
            .product("Serial port")
            .serial_number("TEST")
            .device_class(USB_CLASS_CDC)
            .build();

        loop {
            led.set_low().unwrap();
            if !usb_dev.poll(&mut [&mut serial_port]) {
                continue;
            }

            let mut buf = [0u8; 64];
            match serial_port.read(&mut buf[..]) {
                Ok(_) => led.set_high().unwrap(),
                _ => continue,
            };

            serial_port.write(&buf[..]).unwrap_or(0);
        }
Disasm commented 4 years ago

This is expected, F446 is not supported at the moment. This chip has another version of USB IP core, so as a lot of other F4xx chips. From what I can see with a logic analyzer, first USB communication with a host works great, but then the device fails to receive one of the OUT packets from host effectively stopping enumeration process. This may happen due to the RX FIFO overflow, but I'm not sure.

thousandeyes-fwieland commented 4 years ago

I will experiment with porting code from the C/C++ library (I found a copy here https://github.com/kauailabs/navxmxp/blob/732ff85c1535ed61e572c0d7e1035320b3a1dc02/stm32/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c), I noticed it does things a bit differently

FLamparski commented 4 years ago

I've looked at the stm32ral crate and it does have the right registers for f446xx, although some changes will have to be made. I'll have more of a poke tomorrow.

FLamparski commented 4 years ago

The SVD for F446 appears to be quite messy when it comes to the USB peripherals, see https://github.com/stm32-rs/stm32-rs/issues/327

FLamparski commented 4 years ago

Thank you to everyone who has helped me with this issue, I have resolved it for now - at least on the ZE version of the dev board. Once I get some RE hardware made I'm going to test this again but for now everything appears to be working in order (the additional endpoints currently not available through this crate will be enabled in #3). This ticket can now be closed.