cancel
Showing results for 
Search instead for 
Did you mean: 

HS USB MSC as Device --> formatting error on Host

CObri.1
Associate III

Hi,
I am trying to set up a basic HS USB MSC project on a custom board with an STM32F723.
The project is based on these tutorials from ST, the only difference is, that I'm using USB HS and not USB FS.

https://www.st.com/content/st_com/en/support/learning/stm32-education/stm32-moocs/STM32-USB-training.html
https://www.youtube.com/watch?v=GjQqZd1keBo&ab_channel=STMicroelectronics

https://www.youtube.com/watch?v=Us_sTdGGcOQ&t=363s&ab_channel=ControllersTech

I'll shortly show the CubeMX setup and the code changes I made (all like in the tutorials) and then I will show what the error Message is on the Host.

Project Setup:
      Linker Settings:
         Minimum Heap Size 0x2000
         Minimum Stack Size 0x2000

  • Clock Config
    CObri1_0-1707986829194.png

     

  • USB_HS config
    CObri1_1-1707986910415.png

     

  • USB_Device config
    CObri1_2-1707986995601.png

    This is are all configuration I made. The rest is set to default when you start a new project with the project wizard. The IOC File is also attached to this post.

    In the code I made these addons in the usbd_storage_if.c file:

 

 

#define STORAGE_LUN_NBR                  1
#define STORAGE_BLK_NBR                  0x10000
#define STORAGE_BLK_SIZ                  0x200

/* USER CODE BEGIN PRIVATE_DEFINES */
#define STORAGE_BLK_NBR                  128
uint8_t usb_buffer[STORAGE_BLK_NBR*STORAGE_BLK_SIZ];
int8_t STORAGE_Read_HS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 13 */
	memcpy(&usb_buffer[blk_addr*STORAGE_BLK_SIZ], buf, blk_len*STORAGE_BLK_SIZ);


  return (USBD_OK);
  /* USER CODE END 13 */
}

int8_t STORAGE_Write_HS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 14 */
	memcpy(buf, &usb_buffer[blk_addr*STORAGE_BLK_SIZ], blk_len*STORAGE_BLK_SIZ);

  return (USBD_OK);
  /* USER CODE END 14 */
}

 


After building and running the FW the host computer (Windows 10) detects a new storage device and shows this message (german):

CObri1_3-1707987560888.png

It say's you have to format the device before using it.
If I do so:

CObri1_4-1707987677941.png

I'll get this error message which says: Windows could not complete the formatting

CObri1_5-1707987718903.png

I have also tried to format the device on an Linux host which also failed. 
In the link I shared on the top, the youtube Video from ST, there people in the comments facing the same problems.

Further it is to say, that the USB CDC example works. So the USB connection works.

Is there anyone faced the same problems and have a solution?


1 ACCEPTED SOLUTION

Accepted Solutions
tjaekel
Lead

Sure, your USB enumeration seems to work: you can see your device a "USB Memory dongle" (MSC).

No idea about the details of your code. But based on my experience/understanding with USB MSC:

  • USB MSC (a "USB Memory dongle") does not use any filesystem
  • instead: the host (PC) will take it like an SCSI device: the host PC will just assume it is a sector based memory device (512bytes per sector)
  • the host (PC) will write/read via sectors and provides the file system: so, even the FAT handling is done by the host (PC).
    When you intend to use a FatFS on MCU: it would be bypassed (the host (PC) will do). You just have to provide the SCSI primitives, e.g. writing/reading a sector

It looks to me as:

  • yes, you provide the functions, e.g. int8_t STORAGE_Write(uint8_t lun, uint8_t * buf, uint32_t blk_addr, uint16_t blk_len) and int8_t STORAGE_Read(uint8_t lun, uint8_t * buf, uint32_t blk_addr, uint16_t blk_len)
  • I guess, instead of using an SD Card - you use internal memory (as "simulation" for the file system storage (your usb_buffer variable/array) - OK
  • but I am completely lost with this code line:

 

memcpy(&usb_buffer[blk_addr*STORAGE_BLK_SIZ], buf, blk_len*STORAGE_BLK_SIZ);

 

  • Why do you multiply blk_len with STORAGE_BLK_SIZE?
    blk_len - I think, is already 512 (everything based on a sector, therefore here the sector size as 512 comes already

OK, assuming you want to "emulate" a file storage (internal SRAM instead, via usb_buffer, and not an SD card used (as often intended to do) - thinking about (besides this "bug" with *STORAGE_BLK_SIZE):

  • how much memory have you allocated for usb_buffer??
  • do you know that there is a MBR (Master Boot Record)?
    This is not part of the real file system storage, but it written once (via format) which contains important information about: what is the file system, what is the cluster size, how many sectors for FAT (and FAT2) etc.
  • I would imagine this:
    if you try to format a filesystem (also in memory) for 64KB size - you need a bit more of memory, at least also for the MBR (on sector), maybe this 64KB excludes the need for the FAT and FAT2.
    I guess: your buffer is too small and with this "bug" you overwrite the memory already written (check if all comes as 512byte sectors)

Do you have really 64KB (or even more) for usb_buffer? (as done via format parameter)

There is also a function as:

 

int8_t STORAGE_GetCapacity(uint8_t lun, uint32_t * block_num, uint16_t * block_size)

 

What do you return from here?
This matters a lot, because it tells the host (PC) how large your storage is.
If you do not have reserved the same amount of memory for your usb_buffer - it will corrupt your memory.

See the examples where the SD Card is used as file system storage:
they assume a block_num as linear, 0...X, in sector size 512bytes: you are right with 

 

&usb_buffer[blk_addr*STORAGE_BLK_SIZ]

 

but not with:

 

blk_len*STORAGE_BLK_SIZ

 

View solution in original post

6 REPLIES 6
tjaekel
Lead

Sure, your USB enumeration seems to work: you can see your device a "USB Memory dongle" (MSC).

No idea about the details of your code. But based on my experience/understanding with USB MSC:

  • USB MSC (a "USB Memory dongle") does not use any filesystem
  • instead: the host (PC) will take it like an SCSI device: the host PC will just assume it is a sector based memory device (512bytes per sector)
  • the host (PC) will write/read via sectors and provides the file system: so, even the FAT handling is done by the host (PC).
    When you intend to use a FatFS on MCU: it would be bypassed (the host (PC) will do). You just have to provide the SCSI primitives, e.g. writing/reading a sector

It looks to me as:

  • yes, you provide the functions, e.g. int8_t STORAGE_Write(uint8_t lun, uint8_t * buf, uint32_t blk_addr, uint16_t blk_len) and int8_t STORAGE_Read(uint8_t lun, uint8_t * buf, uint32_t blk_addr, uint16_t blk_len)
  • I guess, instead of using an SD Card - you use internal memory (as "simulation" for the file system storage (your usb_buffer variable/array) - OK
  • but I am completely lost with this code line:

 

memcpy(&usb_buffer[blk_addr*STORAGE_BLK_SIZ], buf, blk_len*STORAGE_BLK_SIZ);

 

  • Why do you multiply blk_len with STORAGE_BLK_SIZE?
    blk_len - I think, is already 512 (everything based on a sector, therefore here the sector size as 512 comes already

OK, assuming you want to "emulate" a file storage (internal SRAM instead, via usb_buffer, and not an SD card used (as often intended to do) - thinking about (besides this "bug" with *STORAGE_BLK_SIZE):

  • how much memory have you allocated for usb_buffer??
  • do you know that there is a MBR (Master Boot Record)?
    This is not part of the real file system storage, but it written once (via format) which contains important information about: what is the file system, what is the cluster size, how many sectors for FAT (and FAT2) etc.
  • I would imagine this:
    if you try to format a filesystem (also in memory) for 64KB size - you need a bit more of memory, at least also for the MBR (on sector), maybe this 64KB excludes the need for the FAT and FAT2.
    I guess: your buffer is too small and with this "bug" you overwrite the memory already written (check if all comes as 512byte sectors)

Do you have really 64KB (or even more) for usb_buffer? (as done via format parameter)

There is also a function as:

 

int8_t STORAGE_GetCapacity(uint8_t lun, uint32_t * block_num, uint16_t * block_size)

 

What do you return from here?
This matters a lot, because it tells the host (PC) how large your storage is.
If you do not have reserved the same amount of memory for your usb_buffer - it will corrupt your memory.

See the examples where the SD Card is used as file system storage:
they assume a block_num as linear, 0...X, in sector size 512bytes: you are right with 

 

&usb_buffer[blk_addr*STORAGE_BLK_SIZ]

 

but not with:

 

blk_len*STORAGE_BLK_SIZ

 

gbm
Lead III

You have swapped the arguments of memcpy. Just swap the first with the second in both calls.

Dear @tjaekel,
Thank you for taking time to check my question an provide such a detailed answer.

Yes, I would like to write, for testing, to the internal RAM. Next I would like to write to external RAM via FMC. But first I have to get the basic example, provided in these two tutorials running:
https://www.youtube.com/watch?v=Us_sTdGGcOQ&t=363s&ab_channel=ControllersTech
https://www.youtube.com/watch?v=GjQqZd1keBo&ab_channel=STMicroelectronics

Both tutorials using USB FS and not USB HS.

I have checkt your succestions. And Yes I made an error in the wite and read function with the use of memcpy.

I fixed it like this: 

int8_t STORAGE_Read_HS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 13 */
	memcpy(buf, &usb_buffer[blk_addr*STORAGE_BLK_SIZ], blk_len*STORAGE_BLK_SIZ);
  return (USBD_OK);
  /* USER CODE END 13 */
}

int8_t STORAGE_Write_HS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 14 */
	memcpy(&usb_buffer[blk_addr*STORAGE_BLK_SIZ], buf,  blk_len*STORAGE_BLK_SIZ);
  return (USBD_OK);
  /* USER CODE END 14 */
}

When debuging, I can see the blk_len is always 1. So it tries to read always 512Byte block, which should be ok. What is strange is, that it always tries to read. The STORAGE_Read_HS function is always called, nonstop...

For the Capacity, I'm using the same function as in the example:

int8_t STORAGE_GetCapacity_HS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
  /* USER CODE BEGIN 10 */
  //UNUSED(lun);

  *block_num  = STORAGE_BLK_NBR;
  *block_size = STORAGE_BLK_SIZ;
  return (USBD_OK);
  /* USER CODE END 10 */
}

 
So I am still facing the same problem.. formating on the host fails.

In the attachment, I'll provide the usbd_storage_if.c file and the main.c file.

Best regards,
Corsin

CObri.1
Associate III

Dear @gbm ,

Yes I have seen I made a *** error there. It happend because I tried everything possible and then when cleaning the whole project and restart it, I used the wrong memcpy functions for write and read.

As I answered to @tjaekel, you can see, that I'm still facing the formatting error on the host.

Do you may have an idea where it comes from?

Best regards,

Corsin 

The size of data being copied by memcpy should be simply STORAGE_BLK_SIZ - no multliplication here.

 

FBL
ST Employee

Hello @CObri.1 

Have you faced similar issues using different classes acm cdc for example? Ensure that your USB device descriptor correctly identifies the device as an MSC device. 

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.