cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U5 USB Interrupt Based Approach

Rajendra_2002
Associate II

I am using the STM32U585RIT6 microcontroller with the B-U585I-IOT02A development kit. I need to implement USB functionality using an interrupt-based approach.

In my project, I have configured USB_OTG_FS in Device-only mode, enabled the NVIC global interrupt, and enabled USBX CDC-ACM. I am using bare-metal code (no RTOS or ThreadX).

After completing all the USB configurations, inside the MX_USBX_Device_Init() function I added the following initialization:

RX FIFO and TX FIFO configurations

USBX DCD initialization using _ux_dcd_stm32_initialize()

Started the PCD using HAL_PCD_Start()

In the main while loop, I am calling ux_device_stack_tasks_run(). With this setup, the USB device starts correctly and is detected as a Virtual COM Port.

Now, I want to handle USB connect and disconnect events using interrupts. For this, VBUS sensing may need to be enabled. While referring to the B-U585I-IOT02A schematic, the USB_VBUS_SENSE pin is shown as PF14. However, in the MCU datasheet and in STM32CubeIDE, PA9 is assigned as the VBUS sense pin.

Please clarify what the correct solution is in this case, and how to properly implement interrupt-based USB connect/disconnect handling? If there are any reference examples related to this scenario, it would be helpful, as I could only find CDC-ACM–related examples.

5 REPLIES 5
Gyessine
ST Employee

Hello @Rajendra_2002 
Since you are using the B-U585I-IOT02A board, use the PF14 pin because it already includes the hardware required for VBUS sensing.
And to handle connect and disconnect events, you basically just need to manipulate these two functions.

HAL_HCD_Connect_Callback(hhcd);
HAL_HCD_Disconnect_Callback(hhcd);

Here is an example of an HID host example where these functions are used:

static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
{
  const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
  uint32_t USBx_BASE = (uint32_t)USBx;
  __IO uint32_t hprt0;
  __IO uint32_t hprt0_dup;

  /* Handle Host Port Interrupts */
  hprt0 = USBx_HPRT0;
  hprt0_dup = USBx_HPRT0;

  hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
                 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);

  /* Check whether Port Connect detected */
  if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
  {
    if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
    {
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
      hhcd->ConnectCallback(hhcd);
#else
      HAL_HCD_Connect_Callback(hhcd);
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
    }
    hprt0_dup |= USB_OTG_HPRT_PCDET;
  }

  /* Check whether Port Enable Changed */
  if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
  {
    hprt0_dup |= USB_OTG_HPRT_PENCHNG;

    if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
    {
      if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
      {
        if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
        {
          (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
        }
        else
        {
          (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
        }
      }
      else
      {
        if (hhcd->Init.speed == HCD_SPEED_FULL)
        {
          USBx_HOST->HFIR = HFIR_60_MHZ;
        }
      }
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
      hhcd->PortEnabledCallback(hhcd);
#else
      HAL_HCD_PortEnabled_Callback(hhcd);
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */

    }
    else
    {
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
      hhcd->PortDisabledCallback(hhcd);
#else
      HAL_HCD_PortDisabled_Callback(hhcd);
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
    }
  }

  /* Check for an overcurrent */
  if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
  {
    hprt0_dup |= USB_OTG_HPRT_POCCHNG;
  }

  /* Clear Port Interrupts */
  USBx_HPRT0 = hprt0_dup;
}

You can also read STM32Cube USB host library It may also help you.
Hope that helps.
BR
Gyessine

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Thanks for the information. I tested multiple scenarios to handle USB connect and disconnect events. First, I enabled VBUS sensing for USB_OTG_FS using PA9 and tried to capture interrupts, but the code did not enter HAL_PCD_ConnectCallback() or HAL_PCD_DisconnectCallback().
Next, I disabled VBUS sensing and configured PF14 as a GPIO EXTI with NVIC global interrupts enabled, but the interrupt was not triggered.
I then tried enabling both VBUS sensing on PA9 and configuring PF14 as GPIO EXTI, but unfortunately none of the interrupts were triggered. Additionally, in all scenarios the USB virtual COM port failed to start, and the code still did not enter either HAL_PCD_ConnectCallback() or HAL_PCD_DisconnectCallback()

gbm
Principal

You don't need to use VBUS_SENSE to detect connection. Things are little tricky with disconnection - the old USB stack could not detect it at all, I don't know about USBX but I don't have high hopes here.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
Rajendra_2002
Associate II

@Gyessine  -  what is the solution for this?

Gyessine
ST Employee

Hello @Rajendra_2002 
Can you clarify how did you configure the VBUS pin from PA9 to PF14

your MSP file should include something like this 

void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  if(hpcd->Instance==USB_OTG_FS)
  {
    /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */

    /* USER CODE END USB_OTG_FS_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_CLK48;
    PeriphClkInit.IclkClockSelection = RCC_CLK48CLKSOURCE_HSI48;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USB_OTG_FS GPIO Configuration
    PA12     ------> USB_OTG_FS_DP
    PA9     ------> USB_OTG_FS_VBUS
    PA11     ------> USB_OTG_FS_DM
    */
    GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF10_USB;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_14;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

    /* Peripheral clock enable */
    __HAL_RCC_USB_CLK_ENABLE();

    /* Enable VDDUSB */
    if(__HAL_RCC_PWR_IS_CLK_DISABLED())
    {
      __HAL_RCC_PWR_CLK_ENABLE();
      HAL_PWREx_EnableVddUSB();
      __HAL_RCC_PWR_CLK_DISABLE();
    }
    else
    {
      HAL_PWREx_EnableVddUSB();
    }
    /* USB_OTG_FS interrupt Init */
    HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
    /* USER CODE BEGIN USB_OTG_FS_MspInit 1 */

    /* USER CODE END USB_OTG_FS_MspInit 1 */

  }

}
void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd)
{
  if(hpcd->Instance==USB_OTG_FS)
  {
    /* USER CODE BEGIN USB_OTG_FS_MspDeInit 0 */

    /* USER CODE END USB_OTG_FS_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USB_CLK_DISABLE();

    /**USB_OTG_FS GPIO Configuration
    PA12     ------> USB_OTG_FS_DP
    PA9     ------> USB_OTG_FS_VBUS
    PA11     ------> USB_OTG_FS_DM
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_12|GPIO_PIN_11);
    HAL_GPIO_DeInit(GPIOF, GPIO_PIN_14);

    /* USB_OTG_FS interrupt DeInit */
    HAL_NVIC_DisableIRQ(OTG_FS_IRQn);
    /* USER CODE BEGIN USB_OTG_FS_MspDeInit 1 */

    /* USER CODE END USB_OTG_FS_MspDeInit 1 */
  }

}

Also, I recommend start debugging VBUS bits like VBDEN bit in GCCFG register and see if its value change or not.

Gyessine_0-1770042987238.png

Also, I recommend putting a breakpoint in HAL_PCD_IRQHandler to see if OTG_FS_IRQHnadler is called or not when you plug/unplug the USB cable .
all of this assuming that you don't have any issues in your implementation.
BR
Gyessine

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.