2025-12-07 5:17 AM
Just wanted to see if anyone could point me in the right direction regarding a problem I'm having with implementing a USB device using MSC in standalone mode. The code initialises correctly as far as I can tell but as soon as it gets into the main loop, a HardFault is generated - this seems to be because ux_device_tasks_run() is trying to access ux_system_slave->ux_system_slave_dcd which is not initialised. I cannot see a function in the CubeMX (v1.5.1) code base that performs this.
I have a reference project for the U385 micro and have confirmed the ioc files for USBX are essentially identical. I can't see a DCD registration function in that project either but apparently it works (I have no way of confirming without the hardware). I think in previous Cube versions, a function called ux_device_stack_dcd_register() was exposed but that no longer seems to be the case. The intention must be for it to be carried out another way but I'm having a hard time working out what this should be.
Would appreciate some advice on how to debug this.
This is how I'm initialising the USBX device :
in main, before while (1) loop :
PCD_HandleTypeDef hpcd_USB_DRD_FS;
...
MX_SDMMC1_SD_Init();
MX_FileX_Init();
MX_USBX_Device_Init();
Within app_usbx_device.c
extern PCD_HandleTypeDef hpcd_USB_DRD_FS;
....
UINT MX_USBX_Device_Init(VOID)
{
UINT ret = UX_SUCCESS;
UCHAR *device_framework_high_speed;
UCHAR *device_framework_full_speed;
ULONG device_framework_hs_length;
ULONG device_framework_fs_length;
ULONG string_framework_length;
ULONG language_id_framework_length;
UCHAR *string_framework;
UCHAR *language_id_framework;
UCHAR *pointer;
/* USER CODE BEGIN MX_USBX_Device_Init0 */
/* USER CODE END MX_USBX_Device_Init0 */
pointer = ux_device_byte_pool_buffer;
/* Initialize USBX Memory */
if (ux_system_initialize(pointer, USBX_DEVICE_MEMORY_STACK_SIZE, UX_NULL, 0) != UX_SUCCESS)
{
/* USER CODE BEGIN USBX_SYSTEM_INITIALIZE_ERROR */
return UX_ERROR;
/* USER CODE END USBX_SYSTEM_INITIALIZE_ERROR */
}
/* Get Device Framework High Speed and get the length */
device_framework_high_speed = USBD_Get_Device_Framework_Speed(USBD_HIGH_SPEED,
&device_framework_hs_length);
/* Get Device Framework Full Speed and get the length */
device_framework_full_speed = USBD_Get_Device_Framework_Speed(USBD_FULL_SPEED,
&device_framework_fs_length);
/* Get String Framework and get the length */
string_framework = USBD_Get_String_Framework(&string_framework_length);
/* Get Language Id Framework and get the length */
language_id_framework = USBD_Get_Language_Id_Framework(&language_id_framework_length);
/* Install the device portion of USBX */
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,
UX_NULL) != UX_SUCCESS)
{
/* USER CODE BEGIN USBX_DEVICE_INITIALIZE_ERROR */
return UX_ERROR;
/* USER CODE END USBX_DEVICE_INITIALIZE_ERROR */
}
/* Initialize the storage class parameters for the device */
storage_parameter.ux_slave_class_storage_instance_activate = USBD_STORAGE_Activate;
storage_parameter.ux_slave_class_storage_instance_deactivate = USBD_STORAGE_Deactivate;
/* Store the number of LUN in this device storage instance */
storage_parameter.ux_slave_class_storage_parameter_number_lun = STORAGE_NUMBER_LUN;
/* Initialize the storage class parameters for reading/writing to the Flash Disk */
storage_parameter.ux_slave_class_storage_parameter_lun[0].
ux_slave_class_storage_media_last_lba = USBD_STORAGE_GetMediaLastLba();
storage_parameter.ux_slave_class_storage_parameter_lun[0].
ux_slave_class_storage_media_block_length = USBD_STORAGE_GetMediaBlocklength();
storage_parameter.ux_slave_class_storage_parameter_lun[0].
ux_slave_class_storage_media_type = 0;
storage_parameter.ux_slave_class_storage_parameter_lun[0].
ux_slave_class_storage_media_removable_flag = STORAGE_REMOVABLE_FLAG;
storage_parameter.ux_slave_class_storage_parameter_lun[0].
ux_slave_class_storage_media_read_only_flag = STORAGE_READ_ONLY;
storage_parameter.ux_slave_class_storage_parameter_lun[0].
ux_slave_class_storage_media_read = USBD_STORAGE_Read;
storage_parameter.ux_slave_class_storage_parameter_lun[0].
ux_slave_class_storage_media_write = USBD_STORAGE_Write;
storage_parameter.ux_slave_class_storage_parameter_lun[0].
ux_slave_class_storage_media_flush = USBD_STORAGE_Flush;
storage_parameter.ux_slave_class_storage_parameter_lun[0].
ux_slave_class_storage_media_status = USBD_STORAGE_Status;
storage_parameter.ux_slave_class_storage_parameter_lun[0].
ux_slave_class_storage_media_notification = USBD_STORAGE_Notification;
/* USER CODE BEGIN STORAGE_PARAMETER */
/* USER CODE END STORAGE_PARAMETER */
/* Get storage configuration number */
storage_configuration_number = USBD_Get_Configuration_Number(CLASS_TYPE_MSC, 0);
/* Find storage interface number */
storage_interface_number = USBD_Get_Interface_Number(CLASS_TYPE_MSC, 0);
/* Initialize the device storage class */
if (ux_device_stack_class_register(_ux_system_slave_class_storage_name,
ux_device_class_storage_entry,
storage_configuration_number,
storage_interface_number,
&storage_parameter) != UX_SUCCESS)
{
/* USER CODE BEGIN USBX_DEVICE_STORAGE_REGISTER_ERROR */
return UX_ERROR;
/* USER CODE END USBX_DEVICE_STORAGE_REGISTER_ERROR */
}
/* USER CODE BEGIN MX_USBX_Device_Init1 */
USBX_APP_Device_Init();
/* USER CODE END MX_USBX_Device_Init1 */
return ret;
}
and
/* USER CODE BEGIN 1 */
VOID USBX_APP_Device_Init(VOID)
{
/* USER CODE BEGIN USB_Device_Init_PreTreatment_0 */
/* USER CODE END USB_Device_Init_PreTreatment_0 */
/* initialize the device controller HAL driver */
MX_USB_PCD_Init();
/* USER CODE BEGIN USB_Device_Init_PreTreatment_1 */
HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, 0x00, PCD_SNG_BUF, 0x14);
HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, 0x80, PCD_SNG_BUF, 0x54);
HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, USBD_MSC_EPOUT_ADDR, PCD_SNG_BUF, 0x94);
HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, USBD_MSC_EPIN_ADDR, PCD_SNG_BUF, 0xD4);
/* USER CODE END USB_Device_Init_PreTreatment_1 */
/* Initialize and link controller HAL driver */
ux_dcd_stm32_initialize((ULONG)USB_DRD_FS, (ULONG)&hpcd_USB_DRD_FS);
/* Start the USB device */
HAL_PCD_Start(&hpcd_USB_DRD_FS);
/* USER CODE BEGIN USB_Device_Init_PostTreatment */
/* USER CODE END USB_Device_Init_PostTreatment */
}
from main.c :
void MX_USB_PCD_Init(void)
{
/* USER CODE BEGIN USB_Init 0 */
/* USER CODE END USB_Init 0 */
/* USER CODE BEGIN USB_Init 1 */
/* USER CODE END USB_Init 1 */
hpcd_USB_DRD_FS.Instance = USB_DRD_FS;
hpcd_USB_DRD_FS.Init.dev_endpoints = 8;
hpcd_USB_DRD_FS.Init.speed = USBD_FS_SPEED;
hpcd_USB_DRD_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd_USB_DRD_FS.Init.Sof_enable = DISABLE;
hpcd_USB_DRD_FS.Init.low_power_enable = DISABLE;
hpcd_USB_DRD_FS.Init.lpm_enable = DISABLE;
hpcd_USB_DRD_FS.Init.battery_charging_enable = DISABLE;
hpcd_USB_DRD_FS.Init.vbus_sensing_enable = DISABLE;
hpcd_USB_DRD_FS.Init.bulk_doublebuffer_enable = DISABLE;
hpcd_USB_DRD_FS.Init.iso_singlebuffer_enable = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_DRD_FS) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USB_Init 2 */
ux_dcd_stm32_initialize((ULONG)USB_DRD_FS, (ULONG)&hpcd_USB_DRD_FS);
/* USER CODE END USB_Init 2 */
}
and within stm32h5xx_hal_pcd.c :
HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
{
#if defined (USB_OTG_FS)
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
#endif /* defined (USB_OTG_FS) */
__HAL_LOCK(hpcd);
#if defined (USB_OTG_FS)
if (hpcd->Init.battery_charging_enable == 1U)
{
/* Enable USB Transceiver */
USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
}
#endif /* defined (USB_OTG_FS) */
__HAL_PCD_ENABLE(hpcd);
(void)USB_DevConnect(hpcd->Instance);
__HAL_UNLOCK(hpcd);
return HAL_OK;
}
The point at which it crashes :
UINT _ux_device_stack_tasks_run(VOID)
{
UX_SLAVE_DCD *dcd;
UX_SLAVE_CLASS *class_instance;
ULONG class_index;
UINT status;
status = UX_STATE_RESET;
/* Run all DCD tasks (pending ISR handle). */
dcd = &_ux_system_slave -> ux_system_slave_dcd; /* <<<<<< THIS IS WHERE IT FALLS OVER! */
dcd -> ux_slave_dcd_function(dcd, UX_DCD_TASKS_RUN, UX_NULL);
2025-12-07 10:44 AM
Hi,
did you read :
https://community.st.com/t5/stm32-mcus/how-to-implement-usbx-in-standalone-mode/ta-p/614435
and
https://community.st.com/t5/stm32-mcus-embedded-software/usbx-msc-standalone/m-p/801896#M63353
+
+
Should show, how to do.