Strange behavior of USB driver on STM32F407.
Posted: Tue Jul 22, 2014 3:36 am
I'm trying to communicate with my device using libusb and control requests.
Here is code:
First of all, if I remove sleep after usbStart, host can't even enumerate device. (Malformed descriptor response packets according to Wireshark)
Another problem is that USB driver not even handle control transfers. libusb_control_transfer on host blocks forever. Wireshark shows that packet was sended to ep0, but no response received.
On device side, seems usb irq for endpoint0 not generated on transfer.
serial_usb driver works perfectly with similiar code (descriptors and callbacks are changed according to demo project). Host application can send CDC control request and recieved response using libusb_control_transfer.
Am I missing something in driver usage?
P.S. ChibiOS 2.6.5
Here is code:
Code: Select all
#include "ch.h"
#include "hal.h"
#define USB_DATA_EP 1
static const USBDescriptor *get_descriptor(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t lang);
static void usb_event(USBDriver *usbp, usbevent_t event);
static bool_t requestsHook(USBDriver *usbp);
static void dataReceived(USBDriver *usbp, usbep_t ep);
static const uint8_t device_descriptor_data[18] =
{
USB_DESC_DEVICE(0x0110, /* bcdUSB (1.1). */
0xFF, /* bDeviceClass (Custom). */
0x00, /* bDeviceSubClass. */
0x00, /* bDeviceProtocol. */
0x40, /* bMaxPacketSize. */
0x0483, /* idVendor (ST). */
0x5740, /* idProduct. */
0x0000, /* bcdDevice. */
1, /* iManufacturer. */
2, /* iProduct. */
3, /* iSerialNumber. */
1) /* bNumConfigurations. */
};
static const USBDescriptor device_descriptor =
{
sizeof device_descriptor_data,
device_descriptor_data
};
/* Configuration Descriptor tree. */
static const uint8_t configuration_descriptor_data[25] =
{
/* Configuration Descriptor.*/
USB_DESC_CONFIGURATION(25, /* wTotalLength. */
0x01, /* bNumInterfaces. */
0x01, /* bConfigurationValue. */
0, /* iConfiguration. */
0xC0, /* bmAttributes (self powered). */
50), /* bMaxPower (100mA). */
/* Interface Descriptor.*/
USB_DESC_INTERFACE(0x00, /* bInterfaceNumber. */
0x00, /* bAlternateSetting. */
0x01, /* bNumEndpoints. */
0xFF, /* bInterfaceClass (Custom). */
0x00, /* bInterfaceSubClass (Custom). */
0x00, /* bInterfaceProtocol (Custom). */
0), /* iInterface. */
/* Endpoint 2 Descriptor.*/
USB_DESC_ENDPOINT(USB_DATA_EP,
0x02, /* bmAttributes (Bulk). */
0x0040, /* wMaxPacketSize. */
0x00) /* bInterval. */
};
static const USBDescriptor configuration_descriptor =
{
sizeof configuration_descriptor_data,
configuration_descriptor_data
};
static const uint8_t string0[] =
{
USB_DESC_BYTE(4), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */
};
static const uint8_t string1[] =
{
USB_DESC_BYTE(38), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'e', 0,
'l', 0, 'e', 0, 'c', 0, 't', 0, 'r', 0, 'o', 0, 'n', 0, 'i', 0,
'c', 0, 's', 0
};
static const uint8_t string2[] =
{
USB_DESC_BYTE(56), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'C', 0, 'h', 0, 'i', 0, 'b', 0, 'i', 0, 'O', 0, 'S', 0, '/', 0,
'R', 0, 'T', 0, ' ', 0, 'V', 0, 'i', 0, 'r', 0, 't', 0, 'u', 0,
'a', 0, 'l', 0, ' ', 0, 'C', 0, 'O', 0, 'M', 0, ' ', 0, 'P', 0,
'o', 0, 'r', 0, 't', 0
};
static const uint8_t string3[] =
{
USB_DESC_BYTE(8), /* bLength. */
USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */
'0' + CH_KERNEL_MAJOR, 0,
'0' + CH_KERNEL_MINOR, 0,
'0' + CH_KERNEL_PATCH, 0
};
static const USBDescriptor strings[] =
{
{sizeof string0, string0},
{sizeof string1, string1},
{sizeof string2, string2},
{sizeof string3, string3}
};
static USBOutEndpointState ep1outstate;
static const USBEndpointConfig ep1config =
{
USB_EP_MODE_TYPE_BULK,
NULL,
NULL,
dataReceived,
0x0,
0x0040,
NULL,
&ep1outstate,
2,
NULL
};
static const USBConfig usbcfg =
{
usb_event,
get_descriptor,
requestsHook,
NULL
};
static const USBDescriptor *get_descriptor(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t lang)
{
switch (dtype)
{
case USB_DESCRIPTOR_DEVICE:
return &device_descriptor;
case USB_DESCRIPTOR_CONFIGURATION:
return &configuration_descriptor;
case USB_DESCRIPTOR_STRING:
if (dindex < 4)
return &strings[dindex];
}
return NULL;
}
static void usb_event(USBDriver *usbp, usbevent_t event)
{
switch (event)
{
case USB_EVENT_RESET:
return;
case USB_EVENT_ADDRESS:
return;
case USB_EVENT_CONFIGURED:
chSysLockFromIsr();
usbInitEndpointI(usbp, USB_DATA_EP, &ep1config);
chSysUnlockFromIsr();
return;
case USB_EVENT_SUSPEND:
return;
case USB_EVENT_WAKEUP:
return;
case USB_EVENT_STALLED:
return;
}
return;
}
static bool_t requestsHook(USBDriver *usbp)
{
if ((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_VENDOR)
{
switch(usbp->setup[1])
{
case REQUEST_SET_LED:
palWritePad(GPIOH, GPIOH_LED1, usbp->setup[2] & (1));
palWritePad(GPIOH, GPIOH_LED2, usbp->setup[2] & (1 << 1));
palWritePad(GPIOI, GPIOI_LED3, usbp->setup[2] & (1 << 2));
palWritePad(GPIOI, GPIOI_LED4, usbp->setup[2] & (1 << 3));
usbSetupTransfer(usbp, NULL, 0, NULL);
return TRUE;
}
}
return FALSE;
}
static void dataReceived(USBDriver *usbp, usbep_t ep)
{
}
void initUSB(USBDriver *usbp)
{
usbDisconnectBus(usbp);
chThdSleepMilliseconds(1500);
usbStart(usbp, &usbcfg);
chThdSleepMilliseconds(1500);
usbConnectBus(usbp);
}
First of all, if I remove sleep after usbStart, host can't even enumerate device. (Malformed descriptor response packets according to Wireshark)
Another problem is that USB driver not even handle control transfers. libusb_control_transfer on host blocks forever. Wireshark shows that packet was sended to ep0, but no response received.
On device side, seems usb irq for endpoint0 not generated on transfer.
serial_usb driver works perfectly with similiar code (descriptors and callbacks are changed according to demo project). Host application can send CDC control request and recieved response using libusb_control_transfer.
Am I missing something in driver usage?
P.S. ChibiOS 2.6.5