cancel
Showing results for 
Search instead for 
Did you mean: 

USBX Device MSC in Standalone mode

PRuss
Associate II

I'm trying to get USBX Device MSC to work in Standalone mode (without RTOS).  I loosely followed @B.Montanari 's example in https://community.st.com/t5/stm32-mcus/how-to-implement-usbx-in-standalone-mode/ta-p/614435, and also referred to a CubeMX example for Device MSC which does use an RTOS (STM32Cube_FW_U5_V1.6.0\Projects\STM32U575I-EV\Applications\USBX\Ux_Device_MSC).  I'm running this on an STM32U5 dev kit.

There are no errors, Windows recognizes the USB MSC device, and a drive shows up.  But something isn't working quite right, since Windows tells me to insert a disk, won't format the volume, and doesn't seem to recognize its size.

I'm not quite sure yet where things are going wrong, but I thought I'd see if this configuration is expected to work or if I'm overlooking any other examples before digging further...

1 ACCEPTED SOLUTION

Accepted Solutions

This was apparently caused by a bug in the USBX source.  Once I fixed it, things seem to be working.

It looks like _ux_device_class_storage_disk_wait just passes the return value of ux_slave_class_storage_media_read (and other similar functions) directly to _ux_device_class_storage_task_disk.  Here this return value is compared against UX_STATE_NEXT to check for success.  

However, comparing some additional samples and other places in the code, ux_slave_class_storage_media_read is expected to return UX_SUCCESS if successful.

BTW, while debugging through the code I also found a couple of bugs in _ux_utility_debug_log (as-is it won't even compile with the UX_ENABLE_DEBUG_LOG switch).

 

This makes me wonder whether Standalone mode and other non-mainstream features are getting much use or test time.

View solution in original post

4 REPLIES 4
Imen.D
ST Employee

Hello @PRuss ,

Try to increase the heap size or configure the USB library to use static allocation as recommended in this FAQ: USB device not recognized.

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen

Thanks for the reply.  I did increase both the heap and stack significantly, but I'm still having the same issue.

This was apparently caused by a bug in the USBX source.  Once I fixed it, things seem to be working.

It looks like _ux_device_class_storage_disk_wait just passes the return value of ux_slave_class_storage_media_read (and other similar functions) directly to _ux_device_class_storage_task_disk.  Here this return value is compared against UX_STATE_NEXT to check for success.  

However, comparing some additional samples and other places in the code, ux_slave_class_storage_media_read is expected to return UX_SUCCESS if successful.

BTW, while debugging through the code I also found a couple of bugs in _ux_utility_debug_log (as-is it won't even compile with the UX_ENABLE_DEBUG_LOG switch).

 

This makes me wonder whether Standalone mode and other non-mainstream features are getting much use or test time.

Azerocks
Associate

Hello @PRuss 

I'm also trying to get USBX MSC to work in standalone mode for one of my projects. However, I can't get it to work. In my main loop, I call the ux_device_stack_tasks_run function, which allows me to detect my device when I plug it into Windows. 

  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    ux_device_stack_tasks_run();
    //_ux_device_class_storage_tasks_run(storage);
  }
  /* USER CODE END 3 */
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 */

  /* Initialize the USB Peripheral */
  MX_USB_OTG_FS_PCD_Init();

  HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x80);
  HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, USBD_MAX_EP0_SIZE / 4);
  HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, USBD_MSC_EPIN_FS_MPS / 2);
  /* Link the USB drivers with the USBX DCD and check if it return error */
  if(ux_dcd_stm32_initialize((ULONG)USB_OTG_FS, (ULONG)&hpcd_USB_OTG_FS) != UX_SUCCESS)

  {
    Error_Handler();
  }
  if(ux_dcd_stm32_initialize((ULONG)USB_OTG_FS, (ULONG)&hpcd_USB_OTG_FS) != UX_SUCCESS)
  {
    Error_Handler();
  }
  /* Start the PCD Peripheral */
  HAL_PCD_Start(&hpcd_USB_OTG_FS);
  /* USER CODE END MX_USBX_Device_Init1 */

  return ret;
}

However, I never get as far as the USBD_STORAGE_Read or USBD_STORAGE_Write functions. As far as I can see, this is because I don't call the _ux_device_class_storage_tasks_run function.
If this is the problem, how can I retrieve the storage class instance?

Thanks for your help