espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.35k stars 7.21k forks source link

ESP32-S3 Mass Storage Class has no disk shown up if CDC count is 2 (IDFGH-11924) #13005

Closed huming2207 closed 7 months ago

huming2207 commented 8 months ago

UPDATE

Check latest comment.

I found the problem. Previously for some reason I set CONFIG_TINYUSB_CDC_COUNT to 2 and then enable the MSC. Now if I set CONFIG_TINYUSB_CDC_COUNT to 1 and MSC works... But I guess this is a bug or something undocumented. I guess Espressif guys may need to have a look.

Below here is the original issue post.

Answers checklist.

General issue report

Hi all,

I've written this code back in last November for adding MSC to my project: https://github.com/huming2207/soul-injector/blob/next/main/comm/comm_msc.cpp

This is to expose an FAT data partition to a host PC so that the user can transfer data (mainly a target microcontroller's firmware binary and flash algorithm ELF files) into this partition, and then later my device can use the data.

Basically for a quick test I just called comm_msc::init() and followed by comm_msc::unmount_and_start_msc() in app_main(). Nothing else was called.

Now I continue working on it. But I realise the MSC was recognised by the host PC but no disk shown up.

My host machines are a PC with Debian 12 and latest Linux kernel 6.1.17, and a MacBook Pro M1 with macOS 14.2.1. Both machines' USB are functional, works fine with outher portable SSDs, thumb drives and USB-UART/DAPLink dongles.

Here's the dmesg on the Debian PC:

[453625.778560] usb 3-1.3: new full-speed USB device number 67 using xhci_hcd
[453626.097571] usb 3-1.3: New USB device found, idVendor=303a, idProduct=80ce, bcdDevice= 1.00
[453626.097577] usb 3-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[453626.097579] usb 3-1.3: Product: Soul Injector
[453626.097580] usb 3-1.3: Manufacturer: Jackson Hu
[453626.097581] usb 3-1.3: SerialNumber: 123456
[453626.281766] cdc_acm 3-1.3:1.0: ttyACM1: USB ACM device
[453626.331608] cdc_acm 3-1.3:1.2: ttyACM2: USB ACM device
[453626.351849] usb-storage 3-1.3:1.4: USB Mass Storage device detected
[453626.351976] scsi host11: usb-storage 3-1.3:1.4

As you see there's a USB Mass Storage device detected, however if I do a lsblk, I can't see any block device (disk) shown. The sda and sdb are two SATA SSDs, and the sdc is a ESPLink JTAG debugger, not my device:

NAME                                          MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
sda                                             8:0    0 465.8G  0 disk
├─sda1                                          8:1    0    16M  0 part
└─sda2                                          8:2    0 465.7G  0 part
sdb                                             8:16   0 931.5G  0 disk
└─luks-xxxxxx-f33e-4e82-xxxx-xxxxxxxxxxx   253:1    0 931.5G  0 crypt /home
sdc                                             8:32   1    24M  0 disk  /media/hu/ESPLink
nvme0n1                                       259:0    0 238.5G  0 disk
├─nvme0n1p1                                   259:1    0 499.7M  0 part  /boot/efi
├─nvme0n1p2                                   259:2    0  39.1G  0 part  [SWAP]
└─nvme0n1p3                                   259:3    0 198.9G  0 part
  └─luks-xxxxxx-9bfa-4a52-xxxx-xxxxxxxxxxx 253:0    0 198.9G  0 crypt /

Anyway, my understanding is, to let a FAT partition on SPI flash act as an USB MSC device and to be exposed to host PC, I need these steps:

  1. call esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, PART_NAME); to grab the partition pointer
  2. call wl_mount(data_part, &wl_handle) where data_part is the esp_partition FAT partition's pointer
  3. init tinyusb_msc_storage_init_spiflash() with wl_handle
  4. optionally, mount the partition internally by tinyusb_msc_storage_mount()
  5. after that do tinyusb_driver_install()
  6. then later do a tinyusb_msc_storage_unmount() to expose this FAT partition to a host PC.

May I ask am I right? Or have a I missed anything here?

Meanwhile I will post more detailed logs on the ESP32 side later tonight.

Regards, Jackson

huming2207 commented 8 months ago

By the way, both host machine's ESP-IDF is v5.1.2; esp_tinyusb is v1.4.2

I also suspect I need to set CONFIG_WL_SECTOR_SIZE_512=y and CONFIG_WL_SECTOR_MODE_PERF=y...

huming2207 commented 8 months ago

Now I've enabled the CONFIG_WL_SECTOR_SIZE_512=y and CONFIG_WL_SECTOR_MODE_PERF=y but still no luck.

Here's the log (with TinyUSB log set to level 3):

I (749) main_task: Calling app_main()
I (749) main: Started
I (759) comm_msc: Mount data partition
I (759) comm_msc: Mount OK, now install USB
I (759) comm_msc: Initialised with SN: 4827e2eadf8c535c090e174e05b5
W (769) TinyUSB: The device's configuration descriptor is not provided by user, using default.
W (779) TinyUSB: The device's string descriptor is not provided by user, using default.
W (789) TinyUSB: The device's device descriptor is not provided by user, using default.
I (799) tusb_desc: 
┌─────────────────────────────────┐
│  USB Device Descriptor Summary  │
├───────────────────┬─────────────┤
│bDeviceClass       │ 239         │
├───────────────────┼─────────────┤
│bDeviceSubClass    │ 2           │
├───────────────────┼─────────────┤
│bDeviceProtocol    │ 1           │
├───────────────────┼─────────────┤
│bMaxPacketSize0    │ 64          │
├───────────────────┼─────────────┤
│idVendor           │ 0x303a      │
├───────────────────┼─────────────┤
│idProduct          │ 0x80ce      │
├───────────────────┼─────────────┤
│bcdDevice          │ 0x100       │
├───────────────────┼─────────────┤
│iManufacturer      │ 0x1         │
├───────────────────┼─────────────┤
│iProduct           │ 0x2         │
├───────────────────┼─────────────┤
│iSerialNumber      │ 0x3         │
├───────────────────┼─────────────┤
│bNumConfigurations │ 0x1         │
└───────────────────┴─────────────┘
USBD init on controller 0
sizeof(usbd_device_t) = 43
sizeof(tu_fifo_t) = 20
sizeof(tu_edpt_stream_t) = 116
CDC init
MSC init
dwc2->guid = 0
dwc2->gsnpsid = 4F54400A
dwc2->ghwcfg1 = 0

dwc2->ghwcfg2 = 224DD930
hw_cfg2->op_mode = 0
hw_cfg2->arch = 0
hw_cfg2->point2point = 0
hw_cfg2->hs_phy_type = 0
hw_cfg2->fs_phy_type = 0
hw_cfg2->num_dev_ep = 0
hw_cfg2->num_host_ch = 0
hw_cfg2->period_channel_support = 0
hw_cfg2->enable_dynamic_fifo = 0
hw_cfg2->mul_cpu_int = 0
hw_cfg2->nperiod_tx_q_depth = 0
hw_cfg2->host_period_tx_q_depth = 0
hw_cfg2->dev_token_q_depth = 0
hw_cfg2->otg_enable_ic_usb = 0

dwc2->ghwcfg3 = C804B5
hw_cfg3->xfer_size_width = 0
hw_cfg3->packet_size_width = 0
hw_cfg3->otg_enable = 0
hw_cfg3->i2c_enable = 0
hw_cfg3->vendor_ctrl_itf = 0
hw_cfg3->optional_feature_removed = 0
hw_cfg3->synch_reset = 0
hw_cfg3->otg_adp_support = 0
hw_cfg3->otg_enable_hsic = 0
hw_cfg3->battery_charger_support = 0
hw_cfg3->lpm_mode = 0
hw_cfg3->total_fifo_size = 0

dwc2->ghwcfg4 = D3F0A030
hw_cfg4->num_dev_period_in_ep = 0
hw_cfg4->power_optimized = 0
hw_cfg4->ahb_freq_min = 0
hw_cfg4->hibernation = 0
hw_cfg4->service_interval_mode = 0
hw_cfg4->ipg_isoc_en = 0
hw_cfg4->acg_enable = 0
hw_cfg4->utmi_phy_data_width = 0
hw_cfg4->dev_ctrl_ep_num = 0
hw_cfg4->iddg_filter_enabled = 0
hw_cfg4->vbus_valid_filter_enabled = 0
hw_cfg4->a_valid_filter_enabled = 0
hw_cfg4->b_valid_filter_enabled = 0
hw_cfg4->dedicated_fifos = 0
hw_cfg4->num_dev_in_eps = 0
hw_cfg4->dma_desc_enable = 0
hw_cfg4->dma_dynamic = 0
Fullspeed PHY init
I (1109) TinyUSB: TinyUSB Driver installed
I (1109) comm_msc: USB install OK
USBD Bus Reset : Full Speed

USBD Setup Received 80 06 00 01 00 00 40 00 
  Get Descriptor Device
  Queue EP 80 with 18 bytes ...
USBD Xfer Complete on EP 80 with 18 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes
USBD Bus Reset : Full Speed

USBD Setup Received 00 05 06 00 00 00 00 00 
  Set Address
USBD Xfer Complete on EP 80 with 0 bytes

USBD Setup Received 80 06 00 01 00 00 12 00 
  Get Descriptor Device
  Queue EP 80 with 18 bytes ...
USBD Xfer Complete on EP 80 with 18 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 00 06 00 00 0A 00 
  Get Descriptor Device Qualifier
  Stall EP0

USBD Setup Received 80 06 00 06 00 00 0A 00 
  Get Descriptor Device Qualifier
  Stall EP0

USBD Setup Received 80 06 00 06 00 00 0A 00 
  Get Descriptor Device Qualifier
  Stall EP0

USBD Setup Received 80 06 00 02 00 00 09 00 
  Get Descriptor Configuration[0]
  Queue EP 80 with 9 bytes ...
USBD Xfer Complete on EP 80 with 9 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 00 02 00 00 A4 00 
  Get Descriptor Configuration[0]
  Queue EP 80 with 64 bytes ...
USBD Xfer Complete on EP 80 with 64 bytes
  Queue EP 80 with 64 bytes ...
USBD Xfer Complete on EP 80 with 64 bytes
  Queue EP 80 with 36 bytes ...
USBD Xfer Complete on EP 80 with 36 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 00 03 00 00 FF 00 
  Get Descriptor String[0]
  Queue EP 80 with 4 bytes ...
USBD Xfer Complete on EP 80 with 4 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 02 03 09 04 FF 00 
  Get Descriptor String[2]
  Queue EP 80 with 28 bytes ...
USBD Xfer Complete on EP 80 with 28 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 01 03 09 04 FF 00 
  Get Descriptor String[1]
  Queue EP 80 with 22 bytes ...
USBD Xfer Complete on EP 80 with 22 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 03 03 09 04 FF 00 
  Get Descriptor String[3]
  Queue EP 80 with 14 bytes ...
USBD Xfer Complete on EP 80 with 14 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 00 09 01 00 00 00 00 00 
  Set Configuration
  Open EP 81 with Size = 8
    Allocated 8 bytes at offset 952  Open EP 02 with Size = 64
  Open EP 82 with Size = 64
    Allocated 64 bytes at offset 888  Queue EP 02 with 64 bytes ...
  CDC opened
  Bind EP 81 to driver id 0
  Bind EP 02 to driver id 0
  Bind EP 82 to driver id 0
  Open EP 83 with Size = 8
    Allocated 8 bytes at offset 880  Open EP 04 with Size = 64
  Open EP 84 with Size = 64
    Allocated 64 bytes at offset 816  Queue EP 04 with 64 bytes ...
  CDC opened
  Bind EP 83 to driver id 0
  Bind EP 04 to driver id 0
  Bind EP 84 to driver id 0
  Open EP 05 with Size = 64
  Open EP 85 with Size = 64
    Allocated 64 bytes at offset 752  Queue EP 05 with 31 bytes ...
  MSC opened
  Bind EP 05 to driver id 1
  Bind EP 85 to driver id 1
  Queue EP 80 with 0 bytes ...
USBD Xfer Complete on EP 80 with 0 bytes

USBD Setup Received 80 06 04 03 09 04 FF 00 
  Get Descriptor String[4]
  Queue EP 80 with 42 bytes ...
USBD Xfer Complete on EP 80 with 42 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 21 20 00 00 00 00 07 00 
  CDC control request
  Set Line Coding
  Queue EP 00 with 7 bytes ...
USBD Xfer Complete on EP 00 with 7 bytes
  0000:  80 25 00 00 00 00 08                             |.%.....|
  CDC control complete
  Queue EP 80 with 0 bytes ...
USBD Xfer Complete on EP 80 with 0 bytes

USBD Setup Received 80 06 04 03 09 04 FF 00 
  Get Descriptor String[4]
  Queue EP 80 with 42 bytes ...
USBD Xfer Complete on EP 80 with 42 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 21 20 00 00 02 00 07 00 
  CDC control request
  Set Line Coding
  Queue EP 00 with 7 bytes ...
USBD Xfer Complete on EP 00 with 7 bytes
  0000:  80 25 00 00 00 00 08                             |.%.....|
  CDC control complete
  Queue EP 80 with 0 bytes ...
USBD Xfer Complete on EP 80 with 0 bytes

USBD Setup Received 80 06 05 03 09 04 FF 00 
  Get Descriptor String[5]
  Queue EP 80 with 42 bytes ...
USBD Xfer Complete on EP 80 with 42 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received A1 FE 00 00 04 00 01 00 
  MSC control request
  MSC Get Max Lun
  Queue EP 80 with 1 bytes ...
USBD Xfer Complete on EP 80 with 1 bytes
  MSC control complete
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes
USBD Xfer Complete on EP 05 with 31 bytes
  MSC xfer callback
  SCSI Command [Lun0]: Inquiry
  Queue EP 85 with 36 bytes ...
USBD Bus Reset : Full Speed

USBD Setup Received 80 06 00 01 00 00 40 00 
  Get Descriptor Device
  Queue EP 80 with 18 bytes ...
USBD Xfer Complete on EP 80 with 18 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes
USBD Bus Reset : Full Speed

USBD Setup Received 00 05 06 00 00 00 00 00 
  Set Address
USBD Xfer Complete on EP 80 with 0 bytes

USBD Setup Received 80 06 00 01 00 00 12 00 
  Get Descriptor Device
  Queue EP 80 with 18 bytes ...
USBD Xfer Complete on EP 80 with 18 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 00 02 00 00 A4 00 
  Get Descriptor Configuration[0]
  Queue EP 80 with 64 bytes ...
USBD Xfer Complete on EP 80 with 64 bytes
  Queue EP 80 with 64 bytes ...
USBD Xfer Complete on EP 80 with 64 bytes
  Queue EP 80 with 36 bytes ...
USBD Xfer Complete on EP 80 with 36 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 80 06 03 03 09 04 FF 00 
  Get Descriptor String[3]
  Queue EP 80 with 14 bytes ...
USBD Xfer Complete on EP 80 with 14 bytes
  Queue EP 00 with 0 bytes ...
USBD Xfer Complete on EP 00 with 0 bytes

USBD Setup Received 00 09 01 00 00 00 00 00 
  Set Configuration
  Open EP 81 with Size = 8
    Allocated 8 bytes at offset 952  Open EP 02 with Size = 64
  Open EP 82 with Size = 64
    Allocated 64 bytes at offset 888  Queue EP 02 with 64 bytes ...
  CDC opened
  Bind EP 81 to driver id 0
  Bind EP 02 to driver id 0
  Bind EP 82 to driver id 0
  Open EP 83 with Size = 8
    Allocated 8 bytes at offset 880  Open EP 04 with Size = 64
  Open EP 84 with Size = 64
    Allocated 64 bytes at offset 816  Queue EP 04 with 64 bytes ...
  CDC opened
  Bind EP 83 to driver id 0
  Bind EP 04 to driver id 0
  Bind EP 84 to driver id 0
  Open EP 05 with Size = 64
  Open EP 85 with Size = 64
    Allocated 64 bytes at offset 752  Queue EP 05 with 31 bytes ...
  MSC opened
  Bind EP 05 to driver id 1
  Bind EP 85 to driver id 1
  Queue EP 80 with 0 bytes ...
USBD Xfer Complete on EP 80 with 0 bytes

USBD Setup Received 21 20 00 00 00 00 07 00 
  CDC control request
  Set Line Coding
  Queue EP 00 with 7 bytes ...
USBD Xfer Complete on EP 00 with 7 bytes
  0000:  80 25 00 00 00 00 08                             |.%.....|
  CDC control complete
  Queue EP 80 with 0 bytes ...
USBD Xfer Complete on EP 80 with 0 bytes

USBD Setup Received 21 20 00 00 02 00 07 00 
  CDC control request
  Set Line Coding
  Queue EP 00 with 7 bytes ...
USBD Xfer Complete on EP 00 with 7 bytes
  0000:  80 25 00 00 00 00 08                             |.%.....|
  CDC control complete
  Queue EP 80 with 0 bytes ...
USBD Xfer Complete on EP 80 with 0 bytes
huming2207 commented 8 months ago

I found the problem. Previously for some reason I set CONFIG_TINYUSB_CDC_COUNT to 2 and then enable the MSC. Now if I set CONFIG_TINYUSB_CDC_COUNT to 1 and MSC works... The storage device shown up on my machine:

NAME                                          MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
sda                                             8:0    0 465.8G  0 disk  
├─sda1                                          8:1    0    16M  0 part  
└─sda2                                          8:2    0 465.7G  0 part  
sdb                                             8:16   0 931.5G  0 disk  
└─luks-a50785ca-f33e-4e82-8c97-db7abbb21976   253:1    0 931.5G  0 crypt /home
sdc                                             8:32   1    24M  0 disk  /media/hu/ESPLink
sdd                                             8:48   1   4.9M  0 disk  
└─sdd1                                          8:49   1   4.9M  0 part  /media/hu/0021-2751
nvme0n1                                       259:0    0 238.5G  0 disk  
├─nvme0n1p1                                   259:1    0 499.7M  0 part  /boot/efi
├─nvme0n1p2                                   259:2    0  39.1G  0 part  [SWAP]
└─nvme0n1p3                                   259:3    0 198.9G  0 part  
  └─luks-da60ce8e-9bfa-4a52-842d-28dc5c92dec8 253:0    0 198.9G  0 crypt /

The sdd is the FAT partition on ESP32.

But why...?

huming2207 commented 7 months ago

May I ask is there any update on this issue?

peter-marcisovsky commented 7 months ago

Hi @huming2207, thank you for reporting the issue. The problem you are facing is a HW limitation of the number of endpoints on the USB peripheral.

According to the documentation:

Our USB-OTG implementation is limited to 6 USB endpoints

Firstly you configured your USB device to have 1 MSC interface and 2 CDC interfaces, which requires 8 endpoints in total, (2 for MSC, 3 for each CDC). Your host machine did not recognize the MSC device, because the TinyUSB implementation first creates CDC interface descriptor, then MSC interface descriptor. And since the CDC interface has already taken 6 endpoints, there were no left for the the MSC interface.

Then you configured your USB device to have 1 MSC interface and 1 CDC interface, which requires 5 endpoints in total, which is within the range and the code is running fine.

Since, this is a HW limitation, it is not possible to use 1 MSC together with 2 CDC interfaces. We will implement an assertion for this types of use cases.

huming2207 commented 7 months ago

Firstly you configured your USB device to have 1 MSC interface and 2 CDC interfaces, which requires 8 endpoints in total, (2 for MSC, 3 for each CDC). Your host machine did not recognize the MSC device, because the TinyUSB implementation first creates CDC interface descriptor, then MSC interface descriptor. And since the CDC interface has already taken 6 endpoints, there were no left for the the MSC interface.

Oh I see. I thought MSC and CDC uses two endpoints only... Thanks for the info!