cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H573I - USB MSC device standalone

loz01
Associate II

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);
3 REPLIES 3
Gyessine
ST Employee

Hello @loz01

I reviewed your code and honestly, I did not identify any major mistakes at this time. However, I could not understand why you are calling the "ux_dcd_stm32_initialize" function in two places: in "USBX_APP_Device_Init" and in "main.c".

Upon reviewing the last two versions of the H5 firmware examples, I noticed that this function is only called in "USBX_APP_Device_Init".
However, we have an article that explains how to configure the USBX MS class in standalone mode. Could you please refer to this article as a basis for your configuration? It may provide helpful insights.

I am waiting for your feedback.

Gyessine

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, thanks for your response. I hadn't realised that function was called twice! I have removed the call in main() but the same issue remains. I will certainly read through that article and let you know if this provides a solution.