Skip to main content
Graduate
October 13, 2025
Question

USBX MSC + LVLX, USBD_STORAGE_Write and USBD_STORAGE_Read

  • October 13, 2025
  • 3 replies
  • 495 views

Hello, 

I am trying to set up an external flash memory (MX25V1635F) on a Nucleo-U575ZI-Q using SPI.

- I managed to simulate a disk using RAM memory, Windows formats it perfectly, which leads me to believe that my USBX configuration is correct.

- I also tested my LevelX functions for reading and writing to my NOR flash, and they seem to be working correctly, which leads me to believe that the LevelX configuration is correct.

- I disabled all my FileX functions (format, open, read, and write) because it seems that Windows (USB Host) takes over the formatting. (Btw, if FileX can't be used, how can I write a formatted file to my flash memory?).

 

My problem: when I leave the USBD_STORAGE_Write and USBD_STORAGE_Read functions empty, Windows can see the size of my disk and offers to format it (without success):

RemiNao_0-1760366801083.png

And when I implement these two functions (based on the only example I found online using the Levelx functions lx_nor_flash_sector_write and lx_nor_flash_sector_read: LINK), Windows can no longer read my disk volume or offer to format it. I think my functions are not defined correctly : 

/**
 * @brief USBD_STORAGE_Read
 * This function is invoked to read from media.
 * @PAram storage_instance : Pointer to the storage class instance.
 * @PAram lun: Logical unit number is the command is directed to.
 * @PAram data_pointer: Address of the buffer to be used for reading or writing.
 * @PAram number_blocks: number of sectors to read/write.
 * @PAram lba: Logical block address is the sector address to read.
 * @PAram media_status: should be filled out exactly like the media status
 * callback return value.
 * @retval status
 */
UINT USBD_STORAGE_Read(VOID *storage_instance, ULONG lun, UCHAR *data_pointer,
 ULONG number_blocks, ULONG lba, ULONG *media_status)
{
 UINT status = UX_SUCCESS;

 /* USER CODE BEGIN USBD_STORAGE_Read */
 UX_PARAMETER_NOT_USED(storage_instance);
 UX_PARAMETER_NOT_USED(media_status);
 while(number_blocks--)
 {
 // status = fx_media_read(&nor_flash_disk,lba,data_pointer);
 status = lx_nor_flash_sector_read(&nor_flash,lba,data_pointer);
 data_pointer+=SECTOR_SIZE_LOGICAL;//512
 lba++;
 if (status != FX_SUCCESS) {
 	 Error_Handler();
 }
 }
//
// for (UINT block = 0; block < number_blocks; block++)
// {
// //status = fx_media_read(&nor_flash_disk,lba,data_pointer);
// status = lx_nor_flash_sector_read(&nor_flash, lba + block, data_pointer);
// data_pointer += SECTOR_SIZE_LOGICAL;//512
// if(status != UX_SUCCESS)
// {
// break;
// }
// }

 /* USER CODE END USBD_STORAGE_Read */

 return status;
}

/**
 * @brief USBD_STORAGE_Write
 * This function is invoked to write in media.
 * @PAram storage_instance : Pointer to the storage class instance.
 * @PAram lun: Logical unit number is the command is directed to.
 * @PAram data_pointer: Address of the buffer to be used for reading or writing.
 * @PAram number_blocks: number of sectors to read/write.
 * @PAram lba: Logical block address is the sector address to read.
 * @PAram media_status: should be filled out exactly like the media status
 * callback return value.
 * @retval status
 */
UINT USBD_STORAGE_Write(VOID *storage_instance, ULONG lun, UCHAR *data_pointer,
 ULONG number_blocks, ULONG lba, ULONG *media_status)
{
 UINT status = UX_SUCCESS;

 /* USER CODE BEGIN USBD_STORAGE_Write */
 UX_PARAMETER_NOT_USED(storage_instance);
 UX_PARAMETER_NOT_USED(media_status);
 while(number_blocks--)
 {
// status = fx_media_write(&nor_flash_disk,lba,data_pointer);
 status = lx_nor_flash_sector_write(&nor_flash,lba,data_pointer);
 data_pointer+=SECTOR_SIZE_LOGICAL;//512
 lba++;
 if(status != FX_SUCCESS)
 {
 	 Error_Handler();
 }
 }
// for (UINT block = 0; block < number_blocks; block++)
// {
// //status = fx_media_write(&nor_flash_disk, lba + block, data_pointer);
//	 status = lx_nor_flash_sector_write(&nor_flash, lba + block, data_pointer);
// data_pointer += SECTOR_SIZE_LOGICAL;//512
// if(status != UX_SUCCESS)
// {
// break;
// }
// }
 /* USER CODE END USBD_STORAGE_Write */

 return status;
}

 

Also, should I use lx_nor_flash_open, and if so, where should I call it?

lx_nor_flash_open(&nor_flash, "NOR_FLASH_DISK", lx_stm32_nor_custom_driver_initialize);


Thank you for your help,

 

    This topic has been closed for replies.

    3 replies

    RemiNaoAuthor
    Graduate
    October 15, 2025

    I still haven't managed to resolve this issue.
    For your information, here is the information from my storage instance when I do:

    lx_nor_flash_open(&nor_flash, "NOR_FLASH_DISK", lx_stm32_nor_custom_driver_initialize);

    RemiNao_0-1760540469454.png

    Does LX_NOR_SECTOR_SIZE correspond to the size of a physical sector?
    Mine are 4096 bytes (or 1024 words). And will this value define the size of the logical sectors?
    I have the impression that the logical sectors need to be 512 bytes.

    RemiNao_1-1760540539835.png

     

    Can you help me?
    thanks

     

    Visitor II
    October 15, 2025

    Hello RemiNao,

     

    block size does not need to be 512 but you should return a corresponding number in USBD_STORAGE_GetMediaBlocklength(). But it makes just little sense to use large block size for NOR so I would consider setting it to 512. Also, consider returning UX_STATE_NEXT instead of UX_SUCCESS in these two functions. You may call lx_nor_flash_open() in USBD_STORAGE_Activate().

     

    Regards,

    Dmitry

    RemiNaoAuthor
    Graduate
    October 16, 2025

    Hello @DmitryR 

    Thank you for your help.
    I forgot to mention that I’m already returning UX_STATE_NEXT and calling lx_nor_flash_open() inside USBD_STORAGE_Activate().

    If you notice anything else, please let me know.

    Visitor II
    October 16, 2025

    Hello RemiNao,

     

    I have checked that your flash has 4K sector so you should leave this too. The one more thing I may suppose is that you use LevelX functions but you check for FileX return codes (FX_SUCCESS). That may lead to a situation when your code always ends up in the error handler.

     

    With best regards,

    Dmitry

    ST Employee
    October 19, 2025

    Hi @RemiNao 

    I've shared a draft application under this thread.
    It combines USBX Device MSC class and NOR Flash memory.

    Have a look at it.

    regards

    Haithem.