cancel
Showing results for 
Search instead for 
Did you mean: 

STM32U5A5 OTG_HS USB Host with DMA not enumerating

Namr
Associate

Hello,

I have been utilizing the OTG_HS peripheral on an STM32U5A5 to act as a USB host. I am using the USBx stack in a non-secure application and initializing the peripheral as follows:

 

VOID USBX_APP_Host_Init(VOID) {

  MX_USB_HCD_Init();

  ux_host_stack_hcd_register(_ux_system_host_hcd_stm32_name,
                             _ux_hcd_stm32_initialize, (ULONG)USB_OTG_HS,
                             (ULONG)&hhcd_USB_OTG_HS);
  
  HAL_HCD_Start(&hhcd_USB_OTG_HS);
}


void MX_USB_HCD_Init(void)
{
  hhcd_USB_OTG_HS.Instance = USB_OTG_HS;
  hhcd_USB_OTG_HS.Init.Host_channels = 16;
  hhcd_USB_OTG_HS.Init.speed = HCD_SPEED_HIGH;
  hhcd_USB_OTG_HS.Init.dma_enable = ENABLE;
  hhcd_USB_OTG_HS.Init.phy_itface = USB_OTG_HS_EMBEDDED_PHY;
  hhcd_USB_OTG_HS.Init.Sof_enable = DISABLE;
  hhcd_USB_OTG_HS.Init.low_power_enable = DISABLE;
  hhcd_USB_OTG_HS.Init.use_external_vbus = DISABLE;
  if (HAL_HCD_Init(&hhcd_USB_OTG_HS) != HAL_OK)
  {
    Error_Handler();
  }
}

void HAL_HCD_MspInit(HCD_HandleTypeDef* hcdHandle)
{
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
  if(hcdHandle->Instance==USB_OTG_HS)
  {
  /* USER CODE BEGIN USB_OTG_HS_MspInit 0 */
    __HAL_RCC_USB_OTG_HS_FORCE_RESET();
      
    __HAL_RCC_USB_OTG_HS_RELEASE_RESET();
		
    __HAL_RCC_SYSCFG_CLK_ENABLE();

  /* USER CODE END USB_OTG_HS_MspInit 0 */

  /** Initializes the peripherals clock */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USBPHY;
    PeriphClkInit.UsbPhyClockSelection = RCC_USBPHYCLKSOURCE_HSE;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

    /** Set the OTG PHY reference clock selection */
    HAL_SYSCFG_SetOTGPHYReferenceClockSelection(SYSCFG_OTG_HS_PHY_CLK_SELECT_1);

    /* Peripheral clock enable */
    __HAL_RCC_USB_OTG_HS_CLK_ENABLE();
    __HAL_RCC_USBPHYC_CLK_ENABLE();

    /* Enable VDDUSB */
    if(__HAL_RCC_PWR_IS_CLK_DISABLED())
    {
      __HAL_RCC_PWR_CLK_ENABLE();
      HAL_PWREx_EnableVddUSB();

      /*configure VOSR register of USB*/
      HAL_PWREx_EnableUSBHSTranceiverSupply();
      __HAL_RCC_PWR_CLK_DISABLE();
    }
    else
    {
      HAL_PWREx_EnableVddUSB();

      /*configure VOSR register of USB*/
      HAL_PWREx_EnableUSBHSTranceiverSupply();
    }

    /*Configuring the SYSCFG registers OTG_HS PHY*/
    /*OTG_HS PHY enable*/
    HAL_SYSCFG_EnableOTGPHY(SYSCFG_OTG_HS_PHY_ENABLE);
    /* USB_OTG_HS interrupt Init */
    HAL_NVIC_SetPriority(OTG_HS_IRQn, 6, 0);
    HAL_NVIC_EnableIRQ(OTG_HS_IRQn);

  /* USER CODE BEGIN USB_OTG_HS_MspInit 1 */

  /* USER CODE END USB_OTG_HS_MspInit 1 */
  }

}

void HAL_HCD_MspDeInit(HCD_HandleTypeDef* hcdHandle)
{
  if(hcdHandle->Instance==USB_OTG_HS)
  {
  /* USER CODE BEGIN USB_OTG_HS_MspDeInit 0 */

  /* USER CODE END USB_OTG_HS_MspDeInit 0 */
  /* Peripheral clock disable */
//  __HAL_RCC_USB_OTG_HS_CLK_DISABLE();
//  __HAL_RCC_USBPHYC_CLK_DISABLE();

  /* USB_OTG_HS interrupt DeInit */
  HAL_NVIC_DisableIRQ(OTG_HS_IRQn);
  /* USER CODE BEGIN USB_OTG_HS_MspDeInit 1 */

  /* USER CODE END USB_OTG_HS_MspDeInit 1 */
  }
}
void OTG_HS_IRQHandler(void)
{
    HAL_HCD_IRQHandler(&hhcd_USB_OTG_HS);
}

 USBX_APP_Host_Init is called in an auto-start thread created in tx_application_define. With this configuration, I see a UX_DEVICE_ENUMERATION_FAILURE when any device is plugged in.

 

Interestingly, if in the configuration I make the following change:

hhcd_USB_OTG_HS.Init.dma_enable = DISABLE;

then the device works as expected. However, I am in need of DMA for my particular application and it is unclear from reading the datasheet what steps I have missed to allow the internal DMA to work.

 

I see similar issues on the forums for the STM32H7 series of chips, where the issue is related to the placement of program in DTCMRAM or DCache. However in my application I have DCache disabled and the STM32U5 series does not seem to have the same issue with DTCMRAM, all the peripherals seem to communicate over SRAM. My SRAM setup is the default generated from the STM32CubeIDE:

/* Memories definition */
MEMORY
{
  RAM (xrw)   : ORIGIN = 0x20000000, LENGTH = 2496K
  SRAM4 (xrw) : ORIGIN = 0x28000000, LENGTH = 16K
  FLASH (rx)  : ORIGIN = 0x08000000, LENGTH = 4096K
}

 

I have looked at the USB examples for this chipset and none of them enable internal DMA. Does anyone understand the issue going on here? What steps do I have to take to get internal DMA to function correctly?

1 ACCEPTED SOLUTION

Accepted Solutions

Hi @FBL,

I am happy to say I was actually able to resolve this issue just yesterday. My issue was actually related to the security features of the STM32U5. I had TrustZone enabled for the device, and all banks were marked as secure, which caused my code to be run as a secure application.

It seems that USB DMA does not play nice with the address aliasing that occurs in secure mode, though I am not 100% sure of the exact cause (it could also be related to the linker configuration I shared in the original post, since that linker configuration sets the RAM to the addresses expected in non-secure mode). Once I had a proper bootloader setup, and ran the USB code in a non-secure application, everything works as expected.

View solution in original post

2 REPLIES 2
FBL
ST Employee

Hi @Namr 

Would you share your project? Maybe buffers used for USB data transfers are not properly aligned. USB internal DMA requires specific alignment (only by multiple of 4 bytes). USB DMA does not allow sending data from non-word-aligned addresses. 

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.

Hi @FBL,

I am happy to say I was actually able to resolve this issue just yesterday. My issue was actually related to the security features of the STM32U5. I had TrustZone enabled for the device, and all banks were marked as secure, which caused my code to be run as a secure application.

It seems that USB DMA does not play nice with the address aliasing that occurs in secure mode, though I am not 100% sure of the exact cause (it could also be related to the linker configuration I shared in the original post, since that linker configuration sets the RAM to the addresses expected in non-secure mode). Once I had a proper bootloader setup, and ran the USB code in a non-secure application, everything works as expected.