Skip to main content
Mikk Leini
Senior
September 8, 2026
Question

Lack of USBX error codes handling and reporting

  • September 8, 2026
  • 1 reply
  • 23 views

I would like to report mishandling of USBX stack function return values and error codes in ST generated code.

Here is a simplified CubeMX (v6.18.1) generated code call path for N6 MCU:

void main()
{
/* Call and ignore result */
MX_USBX_Init();
}

UINT MX_USBX_Init(VOID)
{
UINT ret = UX_SUCCESS;

if (MX_USBX_Device_Init() != UX_SUCCESS)
{
/* USER CODE BEGIN */
return UX_ERROR;
/* USER CODE END */
}

return ret;
}

UINT MX_USBX_Device_Init(VOID)
{
UINT ret = UX_SUCCESS;

/* More code here */

if (MX_USBX_Device_Stack_Init() != UX_SUCCESS)
{
/* USER CODE BEGIN */
return UX_ERROR;
/* USER CODE END */
}

return ret;
}

UINT MX_USBX_Device_Stack_Init(void)
{
UINT ret = UX_SUCCESS;

/* More code here */

if (ux_device_stack_initialize(device_framework_high_speed,
device_framework_hs_length,
device_framework_full_speed,
device_framework_fs_length,
string_framework,
string_framework_length,
language_id_framework,
language_id_framework_length,
USBD_ChangeFunction) != UX_SUCCESS)
{
/* USER CODE BEGIN */
return UX_ERROR;
/* USER CODE END */
}

/* More code here */

/* No failure check at all: */
ux_dcd_stm32_initialize((ULONG)USB1_OTG_HS, (ULONG)&hpcd_USB_OTG_HS1);
/* USER CODE BEGIN */
/* USER CODE END */

return ret;
}

If something fails deep inside USBX then the original error reason is lost and finally whole error is ignored. DCD call does not care about result at all. It is a silently failing system. Next, if application calls USBX functions, it gets hard fault because structures inside it are full of null pointers that weren’t initialized because some init function returned with error.

Now assume you want to debug the issue and implement logging. There are user code sections inside generated code where one can print/log that particular function failed, but since the function return value is not available, the error code cannot be printed. Yet, for some reason there is a ret variable declared. Debugger doesn’t help either because it doesn’t tell the return value (unless going into registers) and you have to step through all the subfunction code to see where it returns.

The solution would be that generated code assigns return value to ret and then checks that. Then user can use the error code for seeing with debugger (complier optimization must be turned down) or printing. An example:


UINT MX_USBX_Device_Init(VOID)
{
UINT ret = UX_SUCCESS;

ret = MX_USBX_Device_Stack_Init();
if (ret != UX_SUCCESS)
{
/* USER CODE BEGIN */
LOG_ERROR("USB device stack init error %u", ret);
return UX_ERROR; /* or return ret */
/* USER CODE END */
}

return ret;
}

Unfortunately same kind of error code discarding is everywhere in HAL code, but that’s another story.

I know the whole ThreadX stack needs improvement in fault handling and reporting, but the issue I point to is part of ST generated glue code so at least this can be improved by ST. I did not check other middleware and the problem could be systematic.

1 reply

ST Technical Moderator
September 9, 2026

Hi ​@Mikk Leini 

Thank you for reporting this. It has been escalated, and an internal ticket CDM0065646 has been submitted to the dedicated team.

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL