zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.85k stars 6.61k forks source link

stm32f4 usb - bulk in endpoint does not work #30031

Closed xhpohanka closed 3 years ago

xhpohanka commented 3 years ago

Hello,

I'm testing USB subsystem on stm32f4 discovery board. I have created a simple device with 2 bulk endpoints, one in, one out. In fact it is almost a copy of the loopback example. My issue is that bulk in endopoint does not work. I'm not very far in debugging, but I noticed that a read request from my host does not even fire the HAL_PCD_IRQHandler(). On the host I use a pyusb library, writes into bulk out endpint work as expected.

Does anyone tested similar setup? I'm aware of #28333 but have not studied how that test works and if it can be related.

thanks Jan

jfischer-no commented 3 years ago

Does loopback sample works for you on stm32f4 discovery board? You can try it with pyusb as well.

xhpohanka commented 3 years ago

Does loopback sample works for you on stm32f4 discovery board? You can try it with pyusb as well.

I'm not able to read from bulk in endpoint from pyusb using the loopback sample :(

xhpohanka commented 3 years ago

I have checked also a native_posix platform. Here the read works fine, however the write ends with <err> native_posix_adapt: recv wrong length: 12.

jfischer-no commented 3 years ago

I have checked also a native_posix platform. Here the read works fine, however the write ends with <err> native_posix_adapt: recv wrong length: 12.

native_posix device driver is special and has own issues #29038 As I understand, the issue is to get data from the device (IN transfer)? Can you share pyocd sample?

xhpohanka commented 3 years ago

I started with the loopback sample and edited the in callback to just return same data every time.

...
static uint8_t loopback_buf[1024] = { "ahoj" };
...
static void loopback_in_cb(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status)
{
    if (usb_write(ep, loopback_buf, 64, NULL)) {
        LOG_DBG("ep 0x%x", ep);
    }
}

and this is my pyusb code

import usb.core
import usb.util

dev = usb.core.find(idVendor=0x1005, idProduct=0x0023)
if dev is None:
    raise ValueError('Device not found')

dev.set_configuration()

dev.read(0x81, 8)  # timeouts 

On stm32f4 I get read timeouts, native_posix returns my "ahoj" data.

jfischer-no commented 3 years ago

I tested loopback sample on nucleo_f413zh with the script below. I see few errors from the shim driver after subsequent set_interface_altsetting, but it works. I do not have an other STM32 board.

_Important: loopback_in_cb is called when the host has successfully fetched the IN endpoint buffer. usbwrite fills the buffer, it does not transfer anything to the host, that is not possible in USB. The IN transfer is started at the USB_DC_INTERFACE event, and is filled anew at each loopback_in_cb.

#!/usr/bin/python3

import usb.core

def main():
    dev = usb.core.find(idVendor=0x2fe3, idProduct=0x0009)

    for cfg in dev:
        for intf in cfg:
            if dev.is_kernel_driver_active(intf.bInterfaceNumber):
                try:
                    dev.detach_kernel_driver(intf.bInterfaceNumber)
                except usb.core.USBError as e:
                    raise RuntimeError("Failed to detach kernel driver")

    dev.set_interface_altsetting(interface = 0, alternate_setting = 0)
    ret = dev.read(0x81, 64, 100)
    print(ret)

if __name__ == "__main__":
    main()
xhpohanka commented 3 years ago

Thanks for your explanation. I have done a quick test with a nucleo-f429zi (I'll check the f407 board later). It seems that the call dev.set_interface_altsetting(interface = 0, alternate_setting = 0) is neccessary, my reads are working when after it is issued.

carlescufi commented 3 years ago

@erwango could you take a look please?

xhpohanka commented 3 years ago

I think, this is solved. It was causd by my misunderstanding of the subsystem