Skip to main content
ST Technical Moderator
May 28, 2025

FAQ: Troubleshooting a USB core soft reset stuck on an STM32

  • May 28, 2025
  • 1 reply
  • 1845 views

Introduction

This article addresses an issue where the USB_OTG_GRSTCTL_CSRST bit in the GRSTCTL register fails to reset, resulting in a timeout during USB initialization. The problem is related to timing and initialization, particularly with the USB PHY and clock configuration. Below, we provide an in-depth explanation, troubleshooting steps, and specific solutions.

1. Issue description

During the USB initialization process, the USB_CoreReset() function is responsible for resetting the USB core by masking the CSRST bit in the GRSTCTL register. However, the bit remains unmasked, causing the function to timeout. The relevant code snippet highlights the problematic loop:

 do
 {
 count++;

 if (count > HAL_USB_TIMEOUT)
 {
 return HAL_TIMEOUT;
 }
 } while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);

The sequence of function calls leading to the issue is as follows:

USB_CoreReset
 └ USB_CoreInit
 └ HAL_PCD_Init
 └ USBD_LL_Init
 └ MX_USB_DEVICE_Init
 └ main

This suggests that the issue might be related to the initialization of the USB controller or the PHY.

2. Troubleshooting steps

  1. Ensure that the clock settings provided match the specifications.
  2. If using CubeMX, check the configuration: set CRS SYNC under RCC to CRS SYNC source USB.
  3. Ensure the global interrupt for USB in NVIC is enabled
  4. Check the USB_HS_REGEN in CubeMX if present. ..... (check in which file)
    /** Enable USB Voltage detector */
     HAL_PWREx_EnableUSBVoltageDetector();
    /** Enable USB HS Regulator */
     HAL_PWREx_EnableUSBHSregulator();
  5. Check the __HAL_RCC_SYSCFG_CLK_ENABLE(); should be generated by CubeMX in the stm32xxx_hal_msp.c 
  6. Verify the usbd_conf.c to make sure the peripheral and PHY clock are correctly configured.
/* Peripheral clock enable */
__HAL_RCC_USB_OTG_HS_CLK_ENABLE();
/* PHY clock enable */
__HAL_RCC_USBPHYC_CLK_ENABLE();

2.1 STM32F72x use case

For STM32F72x lines, the RCC OTGHSULPIEN is still required even for the internal HS PHY in usbh_conf.c or usbd_conf.c.

 /* 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();

2.2 STM32H7RS use case

Here is an overview of USB HS controller and USB FS controller extracted from RM0477.

2-fixed.png

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.

FBL_0-1748439955183.png

The STM32H7RS series has a more complex clock distribution for USB controllers. The USBPHYC block is intended for the OTG_HS controller.

If using clk48mohci (from USBPHYC), ensure the USB HS regulator is enabled:

HAL_PWREx_EnableUSBHSRegulator();
Alternatively, change the clock source for OTG_FS to one of the following:
  • The hsi48_ker_ck for crystal-less applications
  • hse_ker_ck
  • pll3_q_ck

2.3 STM32N6 use case

Step 1. Set the USB OTG_HS PHY1 reference clock source including setting the clock divider in stm32n6xx_hal_msp.c

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();
/*Resets the USB PHY and OTG HS to their default states*/
LL_AHB5_GRP1_ForceReset(0x00800000);
__HAL_RCC_USB1_OTG_HS_FORCE_RESET();
__HAL_RCC_USB1_OTG_HS_PHY_FORCE_RESET();
/*Select HSE clock divided by 2*/
LL_RCC_HSE_SelectHSEDiv2AsDiv2Clock();
/*Release Reset on USB PHY*/
LL_AHB5_GRP1_ReleaseReset(0x00800000);

Step 2. 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();

Step 3. Ensure consistent delays

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
}

3. Delay needed between selecting PHY and soft reset

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.

Conclusion

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.

Related links

1 reply

Robmar
Senior II
July 14, 2026

This issue affects our H743 design only during debug, and the code below solved the issue for us:

 

On the H743 using V1.12.1 library, CubeIDE,  the USB_CoreReset() procedure occasionally fails to reset the Host USB core in debug mode.  I have added a reset call which seems to fix the issue in debug, reproduced below.
I would like to know if this is a known issue in CubeIDE debug mode?

See fix below in USB_CoreReset()
 

// mod - added extra reset as in debug the USB host core fails to reset correctly at times

static void USB_Hard_Reset(USB_OTG_GlobalTypeDef *USBx)

{

/* Example from USBH_LL_Init() in usbh_conf.c USB_HOST/Target/

__HAL_RCC_USB_OTG_HS_FORCE_RESET();

HAL_Delay(50);

__HAL_RCC_USB_OTG_HS_RELEASE_RESET();

HAL_Delay(50);

/* --- FS BACK-POWER FIX START ---

HAL_PWREx_EnableUSBVoltageDetector();

uint32_t to = 100000;

while (__HAL_PWR_GET_FLAG(PWR_FLAG_USB33RDY) == 0U && to--) ;

assert(to > 0);*/

uint32_t timeout;

/* 1. Mask all interrupts and stop AHB transactions */

USBx->GINTMSK = 0U;

USBx->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT; // disable global int

/* 2. Wait for AHB idle */

timeout = 0xFFFFU;

while (((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U) && (timeout-- > 0U))

{

/* wait */

}

/* 3. Core soft reset */

USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;

timeout = 0xFFFFU;

while (((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) != 0U) && (timeout-- > 0U))

{

/* wait */

}

/* 4. Flush TX FIFOs */

USBx->GRSTCTL = USB_OTG_GRSTCTL_TXFFLSH | (0x10U << 6); // all TX FIFOs

timeout = 0xFFFFU;

while (((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) != 0U) && (timeout-- > 0U))

{

/* wait */

}

/* 5. Flush RX FIFO */

USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH;

timeout = 0xFFFFU;

while (((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) != 0U) && (timeout-- > 0U))

{

/* wait */

}

/* 6. Clear pending core interrupts */

USBx->GINTSTS = 0xFFFFFFFFU;

 

/* 7. Leave core in clean, disabled state.

Higher-level init (host/device, FIFOs, GCCFG, etc.) must be redone after this. */

}

 

Affected stock HAL routine:-

/**

* @brief Reset the USB Core (needed after USB clock settings change)

* @param USBx Selected device

* @retval HAL status

*/

static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx)

{

#ifdef DEBUG // mod - added to overcome debug mode HOST HS core hang

USB_Hard_Reset(USBx);

#endif

__IO uint32_t count = 0U;

/* Wait for AHB master IDLE state. */

do

{

count++;

if (count > HAL_USB_TIMEOUT)

{

return HAL_TIMEOUT;

}

} while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);

/* Core Soft Reset */

count = 0U;

USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;

do

{

count++;

// BUG IN DEBUG MODE?? SOMETIMES TIMES-OUT IN DEBUG MODE THEM USB HOST FAILS TO WORK

if (count > HAL_USB_TIMEOUT)

{

return HAL_TIMEOUT;

}

} while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);

return HAL_OK;

}