Electrical – STM32F072C8 – USB communication issue

cortex-mstm32stm32f0usbusb device

I am trying to use the built-it USB to implement a simple HID device in STM32F072. Of course, it is not working. This is my first experience with USB, so I needed some help in figuring out what could be going wrong.

I am using the STM32F0x2xx USB FS device library and am right now testing with their HID example.

When I plug the USB cable to my device and computer, nothing happens. Not even "Unknown Device" or "Yellow exclamation" which leads me to believe it is getting screwed up in the enumeration stage itself.

Doing a USB dump with Wireshark shows some data transfer, which includes lots of "malformed packets".

Enter image description here

So I am not sure what could be wrong. Some things which I think may be going wrong…

  1. Do I need termination resistors on the DM and DP lines? No as per the STM32F072 reference manual; we don't need them
    Enter image description here

  2. Do I need an external pull-up resistor on the DP line? Nope, as per reference manual, F072 has built-in pull-up resistors for that.
    Enter image description here

  3. As per F072 datasheet, there is a USB_NOE line on pin PA13 which I have left unconnected. I am not sure, but I don't think this pin needs to be connected.

  4. In the STM32 USB library, in the file usb_bsp.c (where all the pins, etc. are dealt with), I don't see the DP and DM pins being initialized or set to their alternate USB functions. Only thing they do is enable the USB clock.

    void USB_BSP_Init(USB_CORE_HANDLE * pdev) {
    GPIO_InitTypeDef GPIO_InitStructure;

      #
      if defined USB_DEVICE_LOW_PWR_MGMT_SUPPORT
      EXTI_InitTypeDef EXTI_InitStructure;#
      endif
    
      /* Enable all GPIO clock */
      RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOE | RCC_AHBPeriph_GPIOF, ENABLE);
    
      /* Configure all GPIOs in AN mode to disable current to flow into or out of GPIOs when in suspend mode  */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
      GPIO_Init(GPIOB, & GPIO_InitStructure);
      GPIO_Init(GPIOC, & GPIO_InitStructure);
      GPIO_Init(GPIOD, & GPIO_InitStructure);
      GPIO_Init(GPIOE, & GPIO_InitStructure);
      GPIO_Init(GPIOF, & GPIO_InitStructure);
    
      /* Disable all GPIO clock */
      RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOE | RCC_AHBPeriph_GPIOF, DISABLE);
    
      /* Enable USB clock */
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
    
      #
      if defined USB_CLOCK_SOURCE_CRS
      /*For using CRS, you need to do the following:
      - Enable HSI48 (managed by the SystemInit() function at the application startup)
        - Select HSI48 as USB clock
        - Enable CRS clock
        - Set AUTOTRIMEN
        - Set CEN
        */
    
      /* Select HSI48 as USB clock */
      RCC_USBCLKConfig(RCC_USBCLK_HSI48);
    
      /* Configure the Clock Recovery System */
      CRS_Config();#
      else
      /* Configure PLL to be used as USB clock:
         - Enable HSE external clock (for this example the system is clocked by HSI48
             managed by the SystemInit() function at the application startup)
           - Enable PLL
           - Select PLL as USB clock */
      /* Enable HSE */
        RCC_HSEConfig(RCC_HSE_ON);
    
      /* Wait till HSE is ready */
      while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET) {}
    
      /* Enable PLL */
      RCC_PLLCmd(ENABLE);
    
      /* Wait till PLL is ready */
      while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {}
    
      /* Configure USBCLK from PLL clock */
      RCC_USBCLKConfig(RCC_USBCLK_PLLCLK);
    
      #
      endif /*USB_CLOCK_SOURCE_CRS */
    
      /*JoyStick IOs Configuration*/
      //  STM_EVAL_PBInit(BUTTON_RIGHT, BUTTON_MODE_GPIO);
      //  STM_EVAL_PBInit(BUTTON_LEFT, BUTTON_MODE_GPIO);
      //  STM_EVAL_PBInit(BUTTON_UP, BUTTON_MODE_GPIO);
      //  STM_EVAL_PBInit(BUTTON_DOWN, BUTTON_MODE_GPIO);
    
      /* Configure the Tamper button in EXTI mode */
      //  STM_EVAL_PBInit(BUTTON_TAMPER, Mode_EXTI);
    
      /* Clear the Tamper EXTI line pending bit */
      //  EXTI_ClearITPendingBit(TAMPER_BUTTON_EXTI_LINE);
    
      # ifdef USB_DEVICE_LOW_PWR_MGMT_SUPPORT
    
      /* Enable the PWR clock */
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
    
      /* EXTI line 18 is connected to the USB Wakeup from suspend event   */
      EXTI_ClearITPendingBit(EXTI_Line18);
      EXTI_InitStructure.EXTI_Line = EXTI_Line18;
      /*Must Configure the EXTI Line 18 to be sensitive to rising edge*/
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      EXTI_Init( & EXTI_InitStructure);#
      endif /*USB_DEVICE_LOW_PWR_MGMT_SUPPORT */
    }
    

I would appreciate if someone can suggest what the issue here could be.

Best Answer

You need to set the pins to its alternative functions. See examples below (this is for stm32f7 series, so you probably cannot use it directly):

Full Speed Device

void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
{
    GPIO_InitTypeDef GPIO_Init;

    /* Configure USB FS GPIOs */
    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_Init.Mode = GPIO_MODE_AF_PP;
    GPIO_Init.Pull = GPIO_NOPULL;
    GPIO_Init.Speed = GPIO_SPEED_HIGH;
    GPIO_Init.Alternate = GPIO_AF10_OTG_FS;

    /* Configure DM DP Pins */
    GPIO_Init.Pin = GPIO_PIN_11 | /* OTG_FS_DM */
                    GPIO_PIN_12;  /* OTG_FS_DP */
    HAL_GPIO_Init(GPIOA, &GPIO_Init); 

    /* Enable USB FS Clock */
    __HAL_RCC_USB_OTG_FS_CLK_ENABLE();

    /* Set USBFS Interrupt priority */
    HAL_NVIC_SetPriority(OTG_FS_IRQn, 6, 0);

    /* Enable USBFS Interrupt */
    HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
}

High Speed Host

void  HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
{
    GPIO_InitTypeDef GPIO_Init;

    /* Enable GPIOs clock */
    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_Init.Mode = GPIO_MODE_AF_PP;
    GPIO_Init.Pull = GPIO_PULLUP;
    GPIO_Init.Speed = GPIO_SPEED_HIGH;
    GPIO_Init.Alternate = GPIO_AF12_OTG_HS_FS;

    GPIO_Init.Pin = GPIO_PIN_14 |    /* OTG_HS_DM */
                    GPIO_PIN_15;     /* OTG_HS_DP */
    HAL_GPIO_Init(GPIOB, &GPIO_Init);

    /* Enable USB HS Clocks */
    __HAL_RCC_USB_OTG_HS_CLK_ENABLE();

    /* Set USBHS Interrupt to the lowest priority */
    HAL_NVIC_SetPriority(OTG_HS_IRQn, 5, 0);

    /* Enable USBHS Interrupt */
    HAL_NVIC_EnableIRQ(OTG_HS_IRQn);
}

The functions above will typically be called when initializing the usb function with:

HAL_PCD_Init(&hpcd); // USBH_HandleTypeDef
HAL_HCD_Init(&hhcd); // USBD_HandleTypeDef