Important update: Arm Announces End of Life Timeline for Mbed. This site will be archived in July 2026. Read the full announcement.
USB device stack
Dependents: mbed-mX-USB-TEST1 USBMSD_SD_HID_HelloWorld HidTest MIDI_usb_bridge ... more
Issue: STM32F207ZG (Nucleo F207ZG) - Second USB Port Problem
Hello,
to use the second usb interface as a device with the library I changed the file USBDevice/targets/TARGET_STM/USBHAL_STM_144_64pins.h. I used a preprocessor switch to switch between the first (Port A) and second (on Port B) interface. This is the code:
Added a new usb port configuration for USBHAL_STM_144_64pins.h
/* Copyright (c) 2016 mbed.org, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef USBHAL_STM32_144_64 #define USBHAL_STM32_144_64 //#define USBDOM_PORTB #ifndef USBDOM_PORTB #define USBHAL_IRQn OTG_FS_IRQn #else #define USBHAL_IRQn OTG_HS_IRQn #endif /* must be multiple of 4 bytes */ #ifndef USBDOM_PORTB #define NB_ENDPOINT 4 #define MAXTRANSFER_SIZE 0x200 #else #define NB_ENDPOINT 4 #define MAXTRANSFER_SIZE 0x200 #endif #define FIFO_USB_RAM_SIZE (MAXTRANSFER_SIZE+MAX_PACKET_SIZE_EP0+MAX_PACKET_SIZE_EP1+MAX_PACKET_SIZE_EP2+MAX_PACKET_SIZE_EP3) #if (FIFO_USB_RAM_SIZE > 0x500) #error "FIFO dimensioning incorrect" #endif typedef struct { USBHAL *inst; void (USBHAL::*bus_reset)(void); void (USBHAL::*sof)(int frame); void (USBHAL::*connect_change)(unsigned int connected); void (USBHAL::*suspend_change)(unsigned int suspended); void (USBHAL::*ep0_setup)(void); void (USBHAL::*ep0_in)(void); void (USBHAL::*ep0_out)(void); void (USBHAL::*ep0_read)(void); bool (USBHAL::*ep_realise)(uint8_t endpoint, uint32_t maxPacket, uint32_t flags); bool (USBHAL::*epCallback[2*NB_ENDPOINT-2])(void); /* memorize dummy buffer used for reception */ uint32_t pBufRx[MAXTRANSFER_SIZE>>2]; uint32_t pBufRx0[MAX_PACKET_SIZE_EP0>>2]; uint8_t epComplete[2*NB_ENDPOINT]; }USBHAL_Private_t; uint32_t HAL_PCDEx_GetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo) { uint32_t len; if (fifo == 0) len = hpcd->Instance->DIEPTXF0_HNPTXFSIZ>>16; else len = hpcd->Instance->DIEPTXF[fifo - 1] >> 16; return len*4; } void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { USBHAL_Private_t *priv=((USBHAL_Private_t *)(hpcd->pData)); USBHAL *obj= priv->inst; USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; uint32_t sofnum = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF) >> 8; void (USBHAL::*func)(int frame) = priv->sof; (obj->*func)(sofnum); } USBHAL * USBHAL::instance; USBHAL::USBHAL(void) { /* init parameter */ USBHAL_Private_t *HALPriv = new(USBHAL_Private_t); #ifndef USBDOM_PORTB hpcd.Instance = USB_OTG_FS; //Port A #else hpcd.Instance = USB_OTG_HS; //Port B #endif memset(&hpcd.Init, 0, sizeof(hpcd.Init)); hpcd.Init.dev_endpoints = NB_ENDPOINT; hpcd.Init.ep0_mps = MAX_PACKET_SIZE_EP0; hpcd.Init.phy_itface = PCD_PHY_EMBEDDED; hpcd.Init.Sof_enable = 0; hpcd.Init.speed = PCD_SPEED_FULL; hpcd.Init.vbus_sensing_enable = 0; //hpcd.Init.lpm_enable = 0; /* pass instance for usage inside call back */ HALPriv->inst = this; HALPriv->bus_reset = &USBHAL::busReset; HALPriv->suspend_change = &USBHAL::suspendStateChanged; HALPriv->connect_change = &USBHAL::connectStateChanged; HALPriv->sof = &USBHAL::SOF; HALPriv->ep0_setup = &USBHAL::EP0setupCallback; HALPriv->ep_realise = &USBHAL::realiseEndpoint; HALPriv->ep0_in = &USBHAL::EP0in; HALPriv->ep0_out = &USBHAL::EP0out; HALPriv->ep0_read = &USBHAL::EP0read; hpcd.pData = (void*)HALPriv; HALPriv->epCallback[0] = &USBHAL::EP1_OUT_callback; HALPriv->epCallback[1] = &USBHAL::EP1_IN_callback; HALPriv->epCallback[2] = &USBHAL::EP2_OUT_callback; HALPriv->epCallback[3] = &USBHAL::EP2_IN_callback; HALPriv->epCallback[4] = &USBHAL::EP3_OUT_callback; HALPriv->epCallback[5] = &USBHAL::EP3_IN_callback; instance = this; // Enable power and clocking /* board 144 pin all similar */ #ifndef USBDOM_PORTB __HAL_RCC_GPIOA_CLK_ENABLE(); //Port A #else __HAL_RCC_GPIOB_CLK_ENABLE(); //Port B #endif #ifndef USBDOM_PORTB //First Interface (Port A) pin_function(PA_8, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_SOF */ pin_function(PA_9, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_VBUS */ pin_function(PA_10, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF10_OTG_FS)); /* OTG_FS_ID */ pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DM */ pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF10_OTG_FS)); /* OTG_FS_DP */ #else //Second Interface (Port B) pin_function(PA_4, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); /* OTG_HS_SOF */ pin_function(PB_13, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); /* OTG_HS_VBUS */ pin_function(PB_12, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_PULLUP, GPIO_AF12_OTG_HS_FS)); /* OTG_HS_ID */ pin_function(PB_14, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); /* OTG_HS_DM */ pin_function(PB_15, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_OTG_HS_FS)); /* OTG_HS_DP */ #endif #ifndef USBDOM_PORTB __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); //Port A #else __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); //Port B #endif __HAL_RCC_SYSCFG_CLK_ENABLE(); hpcd.State = HAL_PCD_STATE_RESET; HAL_PCD_Init(&hpcd); /* 1.25kbytes */ /* min value 16 (= 16 x 4 bytes) */ /* max value 256 (= 1K bytes ) */ /* maximum sum is 0x140 */ HAL_PCDEx_SetRxFiFo(&hpcd, (MAXTRANSFER_SIZE/4)); /* bulk/int 64 bytes in FS */ HAL_PCDEx_SetTxFiFo(&hpcd, 0, (MAX_PACKET_SIZE_EP0/4)+1); /* bulk/int bytes in FS */ HAL_PCDEx_SetTxFiFo(&hpcd, 1, (MAX_PACKET_SIZE_EP1/4)+1); HAL_PCDEx_SetTxFiFo(&hpcd, 2, (MAX_PACKET_SIZE_EP2/4)); /* ISOchronous */ HAL_PCDEx_SetTxFiFo(&hpcd, 3, (MAX_PACKET_SIZE_EP3/4)); NVIC_SetVector(USBHAL_IRQn, (uint32_t)&_usbisr); NVIC_SetPriority(USBHAL_IRQn, 1); HAL_PCD_Start(&hpcd); } #endif
To test this code I took a USBSerial (CDC) and just fire an output every 250ms.
If i use the predefined (Port A) USB interface the code is working well.
With the Port B the USB descriptor is successfully sent and then the host disconnects the device. It seems that the interrupt routine is not working with my configuration and I have no clue, why this should be the case.
Here some outputs that shows the linux kernel complaining about the device:
dmesg shows successfully registering the device and then it disconnects the device
[ 5419.410077] usb 1-9: new full-speed USB device number 8 using xhci_hcd [ 5419.749329] usb 1-9: New USB device found, idVendor=1f00, idProduct=2012 [ 5419.749334] usb 1-9: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 5419.749338] usb 1-9: Product: CDC DEVICE [ 5419.749341] usb 1-9: Manufacturer: mbed.org [ 5419.749344] usb 1-9: SerialNumber: 0123456789 [ 5419.771362] cdc_acm 1-9:1.0: ttyACM1: USB ACM device [ 5421.330501] cdc_acm 1-9:1.0: failed to set dtr/rts [ 5421.654303] usb 1-9: USB disconnect, device number 8 [ 5421.654479] cdc_acm 1-9:1.0: failed to set dtr/rts [ 5421.966054] usb 1-9: new full-speed USB device number 9 using xhci_hcd [ 5422.094065] usb 1-9: device descriptor read/64, error -71 [ 5422.330030] usb 1-9: device descriptor read/64, error -71 [ 5422.566031] usb 1-9: new full-speed USB device number 10 using xhci_hcd [ 5422.694043] usb 1-9: device descriptor read/64, error -71 [ 5422.930046] usb 1-9: device descriptor read/64, error -71 [ 5423.038072] usb usb1-port9: attempt power cycle [ 5423.690002] usb 1-9: new full-speed USB device number 11 using xhci_hcd [ 5423.690150] usb 1-9: Device not responding to setup address. [ 5423.898146] usb 1-9: Device not responding to setup address. [ 5424.105995] usb 1-9: device not accepting address 11, error -71 [ 5424.234001] usb 1-9: new full-speed USB device number 12 using xhci_hcd [ 5424.234148] usb 1-9: Device not responding to setup address. [ 5424.442029] usb 1-9: Device not responding to setup address. [ 5424.653998] usb 1-9: device not accepting address 12, error -71 [ 5424.654077] usb usb1-port9: unable to enumerate USB device
To debug this, I placed printfs in the USBCallback_request method of USBCDC.cpp and print the request ID the nucleo gets (via stlinks cdc implementation).
Logged USBRequests comparison PortA (USB_FS) and PortB (USB_HS)
//Port A and B are identical. CALLBACK REQUEST 06 CALLBACK REQUEST 05 CALLBACK REQUEST 06 CALLBACK REQUEST 06 CALLBACK REQUEST 06 CALLBACK REQUEST 06 CALLBACK REQUEST 06 CALLBACK REQUEST 06 CALLBACK REQUEST 06 CALLBACK REQUEST 09 CALLBACK REQUEST 20 //Port B output ends here. //Port A continues: CALLBACK REQUEST 22 CALLBACK REQUEST 20 CALLBACK REQUEST 22 CALLBACK REQUEST 22
So the blocking connect procedure is working and after that the USBDevice lib stops communication with the host. I guess the interrupt is not working if I want to use the second instead of the first interface. A test to confirm this is: The usb connect with descriptor is only working if I reset the board. If I just pull and connect the usb line, the Nucleo isn't sending something and the pc doesn't recognize the usb device either.
Am I missing something ? Sadly I'm running out of ideas what to try next at the moment.