on 2025-05-28 7:02 AM
USB_CoreReset() the USB_OTG_GESTCTL_CSRST bit is never reset and hence a timeout occurs.
Here is the call stack:
The CSRST bit in the GRSTCTL register is not cleared, resulting in a timeout.
do
{
count++;
if (count > HAL_USB_TIMEOUT)
{
return HAL_TIMEOUT;
}
} while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);
This suggests that the issue might be related to the initialization of the USB PHY.
/** Enable USB Voltage detector */
HAL_PWREx_EnableUSBVoltageDetector();
/** Enable USB HS Regulator */
HAL_PWREx_EnableUSBHSregulator();
6. Check in usbd_conf.c
/* Peripheral clock enable */
__HAL_RCC_USB_OTG_HS_CLK_ENABLE();
/* PHY clock enable */
__HAL_RCC_USBPHYC_CLK_ENABLE();
For STM32F72x lines, the RCC OTGHSULPIEN is still required even for the internal HS PHY.
/* Enable HS PHY Clock */
__HAL_RCC_OTGPHYC_CLK_ENABLE();
/* Enable USB HS Clocks */
__HAL_RCC_USB_OTG_HS_CLK_ENABLE();
/* OTGHSULPIEN is still required even for the internal HS PHY */
__HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE();
Here is an overview of USB HS controller and USB FS controller extracted from RM0477.
OTG_HS PHY (also called USBPHYC) does not intervene when using FS controller unless selecting its clock source. The following diagram gives an overview of the clock distribution of USB controllers in STM32H7RS.
When using clk48mohci (from USBPHYC). As this clock is coming from the USB PHY (which appears to be unpowered).
The USBPHYC is intended for OTG_HS controller for HS operations.
Enabling USB HS regulator is needed. Otherwise, change the clock source.
The OTG_FS receives a 48 MHz clock. The application can select:
The USBPHYC provides a 60 MHz clock to the OTG_HS block, and a 48 MHz clock to the OTG_FS block.
Consider a scenario when you are using clk48mohci (from USBPHYC). As this clock is coming from the USB PHY (which appears to be unpowered) then the Core soft reset CSRST bit will not function correctly.
The USBPHYC is intended for OTG_HS controller for HS operations. For that reason, enabling USB HS regulator is needed. Otherwise, change the clock source.
Set the USB OTG_HS PHY1 reference clock source.
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USBPHY1;
PeriphClkInitStruct.UsbPhy1ClockSelection = RCC_USBPHY1REFCLKSOURCE_HSE_DIRECT;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
Error_Handler();
}
__HAL_RCC_GPIOA_CLK_ENABLE();
LL_AHB5_GRP1_ForceReset(0x00800000);
__HAL_RCC_USB1_OTG_HS_FORCE_RESET();
__HAL_RCC_USB1_OTG_HS_PHY_FORCE_RESET();
LL_RCC_HSE_SelectHSEDiv2AsDiv2Clock();
LL_AHB5_GRP1_ReleaseReset(0x00800000);
Enable the peripheral clock.
__HAL_RCC_USB1_OTG_HS_CLK_ENABLE();
HAL_Delay(1);
USB1_HS_PHYC->USBPHYC_CR &= ~(0x7 << 0x4);
USB1_HS_PHYC->USBPHYC_CR |= (0x1 << 16) | (0x2 << 4) | (0x1 << 2) | 0x1U;
__HAL_RCC_USB1_OTG_HS_PHY_RELEASE_RESET();
HAL_Delay(1);
__HAL_RCC_USB1_OTG_HS_RELEASE_RESET();
__HAL_RCC_USB1_OTG_HS_PHY_CLK_ENABLE();
HAL_Delay(1) introduced here is dependent on CPU frequency and may not be reliable. You can insert __NOP() to ensure that the delay is consistent. The volatile keyword ensures that the loop is not optimized away by the compiler.
/* Required few clock cycles before accessing USB PHY Controller Registers */
for (volatile uint32_t i = 0; i < 10; i++) {
__NOP(); // No Operation instruction to create a delay
}
A delay of 10 cycles of the PHY clock must be inserted between PHY operations, specifically when setting the USB_OTG_GUSBCFG_PHYSE in CoreInit() and setting USB_OTG_GRSTCTL_CSRST in USB_CoreReset().
This delay is necessary to avoid the situation where the CSRT bit in OTG_GRSTCTL gets stuck, which can result in a timeout error. The need for this delay is related to the dependency on compiler optimization, PHY frequency, and CPU frequency.
To conclude, these points indicate that the CSRST bit issue is related to timing and initialization problems across different STM32 platforms. Adjusting the delay between certain operations or manually resetting the module might help mitigate the issue.