2025-07-31 4:01 AM
I am trying to perform USB enumeration on an STM32H503. I am using HAL_PCD_SetupStageCallback inside of the USB interrupt, which is working perfectly: when I plug in the USB cable to the Nucleo board, the interrupt triggers and I can see that the callback is executing. One thing that doesn't make sense is that the wLength field is always 0x8408 = 33800. One would expect the field to be 0x12 = 18 for a GET_DESCRIPTOR command, but it's always 33800. I don't think the host is the problem - it's a typical Ubuntu PC that has worked with plenty of other USB devices in the past - but I'm having a hard time seeing where there might be a problem in the code. (The cast from hpcd->Setup to USB_SetupTypeDef isn't the problem, in the debugger window I can see that all fields except wLength are exactly as expected, and that 0x8408 is in the hpcd->Setup array as well.)
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) {
USB_SetupTypeDef *setup = (USB_SetupTypeDef *)hpcd->Setup;
if (setup->bRequest == USB_REQ_GET_DESCRIPTOR) {
if (setup->wValue >> 8 == USB_DESC_TYPE_DEVICE) {
// this happens twice, always with setup->wLength == 33800
send_control_data(device_descriptor, 18);
}
else if (setup->wValue >> 8 == USB_DESC_TYPE_CONFIGURATION) {
// never gets here
}
else if (setup->wValue >> 8 == USB_DESC_TYPE_STRING) {
// never gets here
}
else {
stall_ep0();
}
}
else if (setup->bRequest == USB_REQ_SET_CONFIGURATION) {
// Accept configuration, no special action needed here
send_control_data(NULL, 0);
}
else {
stall_ep0();
}
}
static void send_control_data(uint8_t *buf, uint16_t len) {
if (len == 0) {
// I have tried with both 0x80 and 0x00 endpoints
HAL_PCD_EP_Transmit(&hpcd_USB_DRD_FS, 0x00, NULL, 0); // Status stage
} else {
HAL_PCD_EP_Transmit(&hpcd_USB_DRD_FS, 0x00, buf, len);
}
}