From 55914d0c12181cdff2116c5c3553dc6c6ef350fa Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Bansal Date: Mon, 13 Mar 2023 12:58:58 +0530 Subject: [PATCH] usb: modify example according to newly implemented usbd msc driver --- .../api-reference/peripherals/usb_device.rst | 93 +++-- .../peripherals/usb/device/tusb_msc/README.md | 74 ++-- .../usb/device/tusb_msc/main/CMakeLists.txt | 7 +- .../device/tusb_msc/main/Kconfig.projbuild | 2 +- .../device/tusb_msc/main/idf_component.yml | 2 +- .../usb/device/tusb_msc/main/tusb_msc_main.c | 354 ++++++------------ .../device/tusb_msc/main/tusb_msc_storage.h | 166 -------- .../tusb_msc/main/tusb_msc_storage_sdmmc.c | 276 -------------- .../tusb_msc/main/tusb_msc_storage_spiffs.c | 196 ---------- .../device/tusb_msc/pytest_usb_device_msc.py | 2 +- 10 files changed, 195 insertions(+), 977 deletions(-) delete mode 100644 examples/peripherals/usb/device/tusb_msc/main/tusb_msc_storage.h delete mode 100644 examples/peripherals/usb/device/tusb_msc/main/tusb_msc_storage_sdmmc.c delete mode 100644 examples/peripherals/usb/device/tusb_msc/main/tusb_msc_storage_spiffs.c diff --git a/docs/en/api-reference/peripherals/usb_device.rst b/docs/en/api-reference/peripherals/usb_device.rst index 297f224757..72cab41248 100644 --- a/docs/en/api-reference/peripherals/usb_device.rst +++ b/docs/en/api-reference/peripherals/usb_device.rst @@ -139,67 +139,66 @@ To specify callbacks you can either set the pointer to your :cpp:type:`tusb_cdca USB Serial Console ^^^^^^^^^^^^^^^^^^ -The driver allows to redirect all standard application streams (stdinm stdout, stderr) to the USB Serial Device and return them to UART using :cpp:func:`esp_tusb_init_console`/:cpp:func:`esp_tusb_deinit_console` functions. +The driver allows to redirect all standard application streams (stdin, stdout, stderr) to the USB Serial Device and return them to UART using :cpp:func:`esp_tusb_init_console`/:cpp:func:`esp_tusb_deinit_console` functions. USB Mass Storage Device (MSC) ----------------------------- -If the MSC CONFIG_TINYUSB_MSC_ENABLED option is enabled, the USB MSC Device can be initialized as shown below (see example below). +If the MSC CONFIG_TINYUSB_MSC_ENABLED option is enabled in Menuconfig, the ESP Chip can be used as USB MSC Device. The storage media (spi-flash or sd-card) can be initialized as shown below (see example below). + +- SPI-Flash .. code-block:: c - static uint8_t const desc_configuration[] = { - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + static esp_err_t storage_init_spiflash(wl_handle_t *wl_handle) + { + *** + esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, NULL); + *** + wl_mount(data_partition, wl_handle); + *** + } + storage_init_spiflash(&wl_handle); - // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 0, EDPT_MSC_OUT, EDPT_MSC_IN, TUD_OPT_HIGH_SPEED ? 512 : 64), + const tinyusb_msc_spiflash_config_t config_spi = { + .wl_handle = wl_handle }; + tinyusb_msc_storage_init_spiflash(&config_spi); - static tusb_desc_device_t descriptor_config = { - .bLength = sizeof(descriptor_config), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0x303A, - .idProduct = 0x4002, - .bcdDevice = 0x100, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, - .bNumConfigurations = 0x01 - }; - static char const *string_desc_arr[] = { - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - "123456", // 3: Serials - "Example MSC", // 4. MSC - }; - - const tinyusb_config_t tusb_cfg = { - .device_descriptor = &descriptor_config, - .string_descriptor = string_desc_arr, - .external_phy = false, - .configuration_descriptor = desc_configuration, - }; - tinyusb_driver_install(&tusb_cfg); - -The mandatory callbacks that are required to be implemented are +- SD-Card .. code-block:: c - void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) - bool tud_msc_test_unit_ready_cb(uint8_t lun) - void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size) - bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) - int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize) - int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) - int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) + static esp_err_t storage_init_sdmmc(sdmmc_card_t **card) + { + *** + sdmmc_host_t host = SDMMC_HOST_DEFAULT(); + sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + // For SD Card, set bus width to use + + slot_config.width = 4; + slot_config.clk = CONFIG_EXAMPLE_PIN_CLK; + slot_config.cmd = CONFIG_EXAMPLE_PIN_CMD; + slot_config.d0 = CONFIG_EXAMPLE_PIN_D0; + slot_config.d1 = CONFIG_EXAMPLE_PIN_D1; + slot_config.d2 = CONFIG_EXAMPLE_PIN_D2; + slot_config.d3 = CONFIG_EXAMPLE_PIN_D3; + slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP; + + sd_card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t)); + (*host.init)(); + sdmmc_host_init_slot(host.slot, (const sdmmc_slot_config_t *) &slot_config); + sdmmc_card_init(&host, sd_card); + *** + } + storage_init_sdmmc(&card); + + const tinyusb_msc_sdmmc_config_t config_sdmmc = { + .card = card + }; + tinyusb_msc_storage_init_sdmmc(&config_sdmmc); + Application Examples -------------------- diff --git a/examples/peripherals/usb/device/tusb_msc/README.md b/examples/peripherals/usb/device/tusb_msc/README.md index 0d741f89a3..721840c3ea 100644 --- a/examples/peripherals/usb/device/tusb_msc/README.md +++ b/examples/peripherals/usb/device/tusb_msc/README.md @@ -25,7 +25,7 @@ As a USB stack, a TinyUSB component is used. - Result: Host PC can't access the partition over USB MSC. Application example can perform operations (read, write) on partition. 2. USB which accesses the ESP MSC Partition is already plugged-in at boot time. - Result: Host PC recongnize it as removable device and can access the partition over USB MSC. Application example can't perform any operation on partition. -3. USB which accesses the ESP MSC Partition is plugged-in at boo-up. After boot-up, it is ejected on Host PC manually by user. +3. USB which accesses the ESP MSC Partition is plugged-in at boot-up. After boot-up, it is ejected on Host PC manually by user. - Result: Host PC can't access the partition over USB MSC. Application example can perform operations (read, write) on partition. 4. USB which accesses the ESP MSC Partition is plugged-in at boot-up. It is then unplugged(removed) from Host PC manually by user. - Result: The behaviour is different for bus-powered devices and self-powered devices @@ -75,7 +75,7 @@ Note that even if card's D3 line is not connected to the ESP chip, it still has 1. By default, the example will compile to access SPI Flash as storage media. Here, SPI Flash Wear Levelling WL_SECTOR_SIZE is set to 512 and WL_SECTOR_MODE is set to PERF in Menuconfig. 2. In order to access SD MMC card as storage media, configuration has to be changed using `idf.py menuconfig`: - - i. Open "USB DEV MSC Example Configuration" and select "SDMMC CARD" for "Storage Media Used" + - i. Open "USB Dev MSC Example Configuration" and select "SDMMC CARD" for "Storage Media Used" - ii. Open "SD/MMC bus width" and select between "4 lines (D0 - D3)" or "1 line (D0)" - iii. Select the GPIO Pin numbers for SD Card Pin. - iv. Save the configuration. @@ -97,15 +97,22 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui After the flashing you should see the output at idf monitor: ``` -I (311) cpu_start: Starting scheduler on PRO CPU. -I (0) cpu_start: Starting scheduler on APP CPU. -I (332) gpio: GPIO[4]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 -I (332) example_msc_main: Initializing storage... -I (342) example_msc_storage: Initializing wear levelling -I (350) example_main: Mount storage... -I (350) example_sdmmc: Initializing FAT -I (372) example_msc_main: USB MSC initialization -I (372) tusb_desc: +I (329) app_start: Starting scheduler on CPU0 +I (334) app_start: Starting scheduler on CPU1 +I (334) main_task: Started on CPU0 +I (344) main_task: Calling app_main() +I (344) gpio: GPIO[4]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 +I (354) example_main: Initializing storage... +I (364) example_main: Initializing wear levelling +I (374) example_main: Mount storage... +I (374) example_main: +ls command output: +.fseventsd +_pic.jpg +.__pic.jpg +README.MD +I (384) example_main: USB MSC initialization +I (384) tusb_desc: ┌─────────────────────────────────┐ │ USB Device Descriptor Summary │ ├───────────────────┬─────────────┤ @@ -131,21 +138,13 @@ I (372) tusb_desc: ├───────────────────┼─────────────┤ │bNumConfigurations │ 0x1 │ └───────────────────┴─────────────┘ -I (532) TinyUSB: TinyUSB Driver installed -I (532) example_msc_main: USB MSC initialization DONE -I (552) example_msc_main: -ls command output: -README.MD -.fseventsd +I (554) TinyUSB: TinyUSB Driver installed +I (564) example_main: USB MSC initialization DONE Type 'help' to get the list of commands. Use UP/DOWN arrows to navigate through command history. Press TAB when typing command name to auto-complete. -esp32s3> I (912) example_msc_main: tud_mount_cb MSC START: Expose Over USB -I (912) example_msc_main: Unmount storage... -I (2032) example_msc_main: tud_msc_scsi_cb() invoked: SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL -I (2032) example_msc_main: tud_msc_capacity_cb() size(1024000), sec_size(512) -esp32s3> +I (724) main_task: Returned from app_main() esp32s3> esp32s3> help help @@ -171,43 +170,32 @@ exit esp32s3> esp32s3> read -E (19102) example_msc_main: storage exposed over USB. Application can't read from storage. +E (80054) example_main: storage exposed over USB. Application can't read from storage. Command returned non-zero error code: 0xffffffff (ESP_FAIL) esp32s3> write -E (22412) example_msc_main: storage exposed over USB. Application can't write to storage. +E (83134) example_main: storage exposed over USB. Application can't write to storage. Command returned non-zero error code: 0xffffffff (ESP_FAIL) esp32s3> size -E (24962) example_msc_main: storage exposed over USB. Application can't access storage +E (85354) example_main: storage exposed over USB. Application can't access storage Command returned non-zero error code: 0xffffffff (ESP_FAIL) esp32s3> status storage exposed over USB: Yes +esp32s3> expose +E (108344) example_main: storage is already exposed +Command returned non-zero error code: 0xffffffff (ESP_FAIL) esp32s3> esp32s3> -esp32s3> I (49692) example_msc_main: tud_msc_scsi_cb() invoked: SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL -I (49692) example_msc_main: tud_msc_start_stop_cb() invoked, power_condition=0, start=0, load_eject=1 -I (49702) example_msc_main: tud_msc_start_stop_cb: MSC EJECT: Mount on Example -I (49712) example_msc_main: Mount storage... -I (49712) example_msc_storage: Initializing FAT -I (49712) example_msc_main: -ls command output: -README.MD -esp32s3> -esp32s3> -esp32s3> status -storage exposed over USB: No esp32s3> read Mass Storage Devices are one of the most common USB devices. It use Mass Storage Class (MSC) that allow access to their internal data storage. In this example, ESP chip will be recognised by host (PC) as Mass Storage Device. Upon connection to USB host (PC), the example application will initialize the storage module and then the storage will be seen as removable device on PC. esp32s3> write esp32s3> size -storage size(1024000), sec_size(512) -esp32s3> +Storage Capacity 0MB +esp32s3> status +storage exposed over USB: No esp32s3> expose -I (76402) example_msc_main: Unmount storage... -esp32s3> I (76772) example_msc_main: tud_msc_scsi_cb() invoked: SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL -I (76772) example_msc_main: tud_msc_capacity_cb() size(1024000), sec_size(512) -esp32s3> +I (181224) example_main: Unmount storage... esp32s3> status storage exposed over USB: Yes esp32s3> diff --git a/examples/peripherals/usb/device/tusb_msc/main/CMakeLists.txt b/examples/peripherals/usb/device/tusb_msc/main/CMakeLists.txt index 2a16eb6667..de4c14c1ea 100644 --- a/examples/peripherals/usb/device/tusb_msc/main/CMakeLists.txt +++ b/examples/peripherals/usb/device/tusb_msc/main/CMakeLists.txt @@ -2,12 +2,7 @@ set(srcs "tusb_msc_main.c") set(requires fatfs console) if(CONFIG_EXAMPLE_STORAGE_MEDIA_SPIFLASH) - list(APPEND srcs "tusb_msc_storage_spiffs.c") - list(APPEND requires "wear_levelling") -endif() - -if(CONFIG_EXAMPLE_STORAGE_MEDIA_SDMMCCARD) - list(APPEND srcs "tusb_msc_storage_sdmmc.c") + list(APPEND requires wear_levelling) endif() idf_component_register( diff --git a/examples/peripherals/usb/device/tusb_msc/main/Kconfig.projbuild b/examples/peripherals/usb/device/tusb_msc/main/Kconfig.projbuild index 5b98a734fa..04714f22a9 100644 --- a/examples/peripherals/usb/device/tusb_msc/main/Kconfig.projbuild +++ b/examples/peripherals/usb/device/tusb_msc/main/Kconfig.projbuild @@ -1,4 +1,4 @@ -menu "USB DEV MSC Example Configuration" +menu "USB Dev MSC Example Configuration" choice EXAMPLE_STORAGE_MEDIA prompt "Storage Media Used" diff --git a/examples/peripherals/usb/device/tusb_msc/main/idf_component.yml b/examples/peripherals/usb/device/tusb_msc/main/idf_component.yml index b60893c81e..06b047d6a2 100644 --- a/examples/peripherals/usb/device/tusb_msc/main/idf_component.yml +++ b/examples/peripherals/usb/device/tusb_msc/main/idf_component.yml @@ -1,4 +1,4 @@ ## IDF Component Manager Manifest File dependencies: - espressif/esp_tinyusb: "^1.1" + espressif/esp_tinyusb: "^1.2" idf: "^5.0" diff --git a/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_main.c b/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_main.c index 38a5d13e28..bd3055d7ec 100644 --- a/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_main.c +++ b/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_main.c @@ -11,182 +11,20 @@ * For different scenarios and behaviour, Refer to README of this example. */ -#include #include #include -#include "esp_log.h" #include "esp_console.h" -#include "tinyusb.h" -#include "class/msc/msc_device.h" -#include "tusb_msc_storage.h" +#include "esp_check.h" #include "driver/gpio.h" +#include "tinyusb.h" +#include "tusb_msc_storage.h" +#ifdef CONFIG_EXAMPLE_STORAGE_MEDIA_SDMMCCARD +#include "diskio_impl.h" +#include "diskio_sdmmc.h" +#endif static const char *TAG = "example_main"; -/* TinyUSB MSC callbacks - ********************************************************************* */ - -/** SCSI ASC/ASCQ codes. **/ -/** User can add and use more codes as per the need of the application **/ -#define SCSI_CODE_ASC_MEDIUM_NOT_PRESENT 0x3A /** SCSI ASC code for 'MEDIUM NOT PRESENT' **/ -#define SCSI_CODE_ASC_INVALID_COMMAND_OPERATION_CODE 0x20 /** SCSI ASC code for 'INVALID COMMAND OPERATION CODE' **/ -#define SCSI_CODE_ASCQ 0x00 - -static void _mount(void); -static void _unmount(void); -static bool is_eject = false; - -// Invoked when received SCSI_CMD_INQUIRY -// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively -void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) -{ - (void) lun; - ESP_LOGD(TAG, "tud_msc_inquiry_cb() invoked"); - - const char vid[] = "TinyUSB"; - const char pid[] = "Flash Storage"; - const char rev[] = "0.1"; - - memcpy(vendor_id, vid, strlen(vid)); - memcpy(product_id, pid, strlen(pid)); - memcpy(product_rev, rev, strlen(rev)); -} - -// Invoked when received Test Unit Ready command. -// return true allowing host to read/write this LUN e.g SD card inserted -bool tud_msc_test_unit_ready_cb(uint8_t lun) -{ - (void) lun; - ESP_LOGD(TAG, "tud_msc_test_unit_ready_cb() invoked"); - - if (is_eject) { - tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, SCSI_CODE_ASC_MEDIUM_NOT_PRESENT, SCSI_CODE_ASCQ); - return false; - } else { - ESP_LOGD(TAG, "tud_msc_test_unit_ready_cb: MSC START: Expose Over USB"); - _unmount(); - return true; - } -} - -// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size -// Application update block count and block size -void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size) -{ - (void) lun; - - uint32_t sec_count = storage_get_sector_count(); - uint32_t sec_size = storage_get_sector_size(); - ESP_LOGD(TAG, "tud_msc_capacity_cb() sec_count(%lu), sec_size(%lu)", sec_count, sec_size); - *block_count = sec_count; - *block_size = (uint16_t)sec_size; -} - -// Invoked when received Start Stop Unit command -// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage -// - Start = 1 : active mode, if load_eject = 1 : load disk storage -bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) -{ - (void) lun; - (void) power_condition; - ESP_LOGI(TAG, "tud_msc_start_stop_cb() invoked, power_condition=%d, start=%d, load_eject=%d", power_condition, start, load_eject); - - if (load_eject && !start) { - is_eject = true; - ESP_LOGI(TAG, "tud_msc_start_stop_cb: MSC EJECT: Mount on Example"); - _mount(); - } - return true; -} - -// Invoked when received SCSI READ10 command -// - Address = lba * BLOCK_SIZE + offset -// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. -int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize) -{ - ESP_LOGD(TAG, "tud_msc_read10_cb() invoked, lun=%d, lba=%lu, offset=%lu, bufsize=%lu", lun, lba, offset, bufsize); - - esp_err_t err = storage_read_sector(lba, offset, bufsize, buffer); - if (err != ESP_OK) { - ESP_LOGE(TAG, "storage_read_sector failed: 0x%x", err); - return 0; - } - return bufsize; -} - -// Invoked when received SCSI WRITE10 command -// - Address = lba * BLOCK_SIZE + offset -// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. -int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) -{ - ESP_LOGD(TAG, "tud_msc_write10_cb() invoked, lun=%d, lba=%lu, offset=%lu, bufsize=%lu", lun, lba, offset, bufsize); - - esp_err_t err = storage_write_sector(lba, offset, bufsize, buffer); - if (err != ESP_OK) { - ESP_LOGE(TAG, "storage_write_sector failed: 0x%x", err); - return 0; - } - return bufsize; -} - -/** - * Invoked when received an SCSI command not in built-in list below. - * - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, TEST_UNIT_READY, START_STOP_UNIT, MODE_SENSE6, REQUEST_SENSE - * - READ10 and WRITE10 has their own callbacks - * - * \param[in] lun Logical unit number - * \param[in] scsi_cmd SCSI command contents which application must examine to response accordingly - * \param[out] buffer Buffer for SCSI Data Stage. - * - For INPUT: application must fill this with response. - * - For OUTPUT it holds the Data from host - * \param[in] bufsize Buffer's length. - * - * \return Actual bytes processed, can be zero for no-data command. - * \retval negative Indicate error e.g unsupported command, tinyusb will \b STALL the corresponding - * endpoint and return failed status in command status wrapper phase. - */ -int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) -{ - int32_t ret; - - ESP_LOGD(TAG, "tud_msc_scsi_cb() invoked. bufsize=%d", bufsize); - - switch (scsi_cmd[0]) { - case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: - /* SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL is the Prevent/Allow Medium Removal - command (1Eh) that requests the library to enable or disable user access to - the storage media/partition. */ - ESP_LOGI(TAG, "tud_msc_scsi_cb() invoked: SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL"); - ret = 0; - break; - default: - ESP_LOGW(TAG, "tud_msc_scsi_cb() invoked: %d", scsi_cmd[0]); - tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_CODE_ASC_INVALID_COMMAND_OPERATION_CODE, SCSI_CODE_ASCQ); - ret = -1; - break; - } - return ret; -} - -// Invoked when device is unmounted -void tud_umount_cb(void) -{ - is_eject = true; - ESP_LOGI(TAG, "tud_umount_cb: Mount on Example"); - _mount(); -} - -// Invoked when device is mounted (configured) -void tud_mount_cb(void) -{ - ESP_LOGI(TAG, "tud_mount_cb MSC START: Expose Over USB"); - _unmount(); -} -/*********************************************************************** TinyUSB MSC callbacks*/ - -/* Application Code - ********************************************************************* */ - /* TinyUSB descriptors ********************************************************************* */ #define EPNUM_MSC 1 @@ -239,53 +77,51 @@ static char const *string_desc_arr[] = { }; /*********************************************************************** TinyUSB descriptors*/ -#define VBUS_MONITORING_GPIO_NUM GPIO_NUM_4 #define BASE_PATH "/data" // base path to mount the partition -static bool is_mount = false; #define PROMPT_STR CONFIG_IDF_TARGET -static int f_unmount(int argc, char **argv); -static int f_read(int argc, char **argv); -static int f_write(int argc, char **argv); -static int f_size(int argc, char **argv); -static int f_status(int argc, char **argv); -static int f_exit(int argc, char **argv); +static int console_unmount(int argc, char **argv); +static int console_read(int argc, char **argv); +static int console_write(int argc, char **argv); +static int console_size(int argc, char **argv); +static int console_status(int argc, char **argv); +static int console_exit(int argc, char **argv); const esp_console_cmd_t cmds[] = { { .command = "read", .help = "read BASE_PATH/README.MD and print its contents", .hint = NULL, - .func = &f_read, + .func = &console_read, }, { .command = "write", .help = "create file BASE_PATH/README.MD if it does not exist", .hint = NULL, - .func = &f_write, + .func = &console_write, }, { .command = "size", .help = "show storage size and sector size", .hint = NULL, - .func = &f_size, + .func = &console_size, }, { .command = "expose", .help = "Expose Storage to Host", .hint = NULL, - .func = &f_unmount, + .func = &console_unmount, }, { .command = "status", .help = "Status of storage exposure over USB", .hint = NULL, - .func = &f_status, + .func = &console_status, }, { .command = "exit", .help = "exit from application", .hint = NULL, - .func = &f_exit, + .func = &console_exit, } }; @@ -293,10 +129,8 @@ const esp_console_cmd_t cmds[] = { static void _mount(void) { ESP_LOGI(TAG, "Mount storage..."); - if (!is_mount) { - ESP_ERROR_CHECK(storage_mount(BASE_PATH)); - is_mount = true; - } + ESP_ERROR_CHECK(tinyusb_msc_storage_mount(BASE_PATH)); + // List all the files in this directory ESP_LOGI(TAG, "\nls command output:"); @@ -319,29 +153,22 @@ static void _mount(void) return; } -// unmount the partition -static void _unmount(void) +// unmount storage +static int console_unmount(int argc, char **argv) { - if (!is_mount) { - ESP_LOGD(TAG, "storage exposed over USB..."); - return; + if (tinyusb_msc_storage_in_use_by_usb_host()) { + ESP_LOGE(TAG, "storage is already exposed"); + return -1; } ESP_LOGI(TAG, "Unmount storage..."); - ESP_ERROR_CHECK(storage_unmount()); - is_mount = false; - is_eject = false; -} - -static int f_unmount(int argc, char **argv) -{ - _unmount(); + ESP_ERROR_CHECK(tinyusb_msc_storage_unmount()); return 0; } // read BASE_PATH/README.MD and print its contents -static int f_read(int argc, char **argv) +static int console_read(int argc, char **argv) { - if (!is_mount) { + if (tinyusb_msc_storage_in_use_by_usb_host()) { ESP_LOGE(TAG, "storage exposed over USB. Application can't read from storage."); return -1; } @@ -361,9 +188,9 @@ static int f_read(int argc, char **argv) } // create file BASE_PATH/README.MD if it does not exist -static int f_write(int argc, char **argv) +static int console_write(int argc, char **argv) { - if (!is_mount) { + if (tinyusb_msc_storage_in_use_by_usb_host()) { ESP_LOGE(TAG, "storage exposed over USB. Application can't write to storage."); return -1; } @@ -382,56 +209,55 @@ static int f_write(int argc, char **argv) } // Show storage size and sector size -static int f_size(int argc, char **argv) +static int console_size(int argc, char **argv) { - if (!is_mount) { + if (tinyusb_msc_storage_in_use_by_usb_host()) { ESP_LOGE(TAG, "storage exposed over USB. Application can't access storage"); return -1; } - uint32_t sec_count = storage_get_sector_count(); - uint32_t sec_size = storage_get_sector_size(); + uint32_t sec_count = tinyusb_msc_storage_get_sector_count(); + uint32_t sec_size = tinyusb_msc_storage_get_sector_size(); printf("Storage Capacity %lluMB\n", ((uint64_t) sec_count) * sec_size / (1024 * 1024)); return 0; } // exit from application -static int f_status(int argc, char **argv) +static int console_status(int argc, char **argv) { - printf("storage exposed over USB: %s\n", is_mount ? "No" : "Yes"); + printf("storage exposed over USB: %s\n", tinyusb_msc_storage_in_use_by_usb_host() ? "Yes" : "No"); return 0; } // exit from application -static int f_exit(int argc, char **argv) +static int console_exit(int argc, char **argv) { + tinyusb_msc_storage_deinit(); printf("Application Exiting\n"); exit(0); return 0; } -void app_main(void) -{ - // Configure GPIO Pin for vbus monitoring - const gpio_config_t vbus_gpio_config = { - .pin_bit_mask = BIT64(VBUS_MONITORING_GPIO_NUM), - .mode = GPIO_MODE_INPUT, - .intr_type = GPIO_INTR_DISABLE, - .pull_up_en = true, - .pull_down_en = false, - }; - ESP_ERROR_CHECK(gpio_config(&vbus_gpio_config)); - - ESP_LOGI(TAG, "Initializing storage..."); - tinyusb_config_storage_t storage_config; - #ifdef CONFIG_EXAMPLE_STORAGE_MEDIA_SPIFLASH - // configuration is to defined in case of SPI Flash - storage_config.storage_type = TINYUSB_STORAGE_SPI; - tinyusb_config_spiffs_t config_spi; - storage_config.spiffs_config = &config_spi; -#else // CONFIG_EXAMPLE_STORAGE_MEDIA_SPIFLASH - storage_config.storage_type = TINYUSB_STORAGE_SDMMC; - tinyusb_config_sdmmc_t config_sdmmc; +static esp_err_t storage_init_spiflash(wl_handle_t *wl_handle) +{ + ESP_LOGI(TAG, "Initializing wear levelling"); + + const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, NULL); + if (data_partition == NULL) { + ESP_LOGE(TAG, "Failed to find FATFS partition. Check the partition table."); + return ESP_ERR_NOT_FOUND; + } + + return wl_mount(data_partition, wl_handle); +} +#else // CONFIG_EXAMPLE_STORAGE_MEDIA_SPIFLASH +static esp_err_t storage_init_sdmmc(sdmmc_card_t **card) +{ + esp_err_t ret = ESP_OK; + bool host_init = false; + sdmmc_card_t *sd_card; + + ESP_LOGI(TAG, "Initializing SDCard"); // By default, SD card frequency is initialized to SDMMC_FREQ_DEFAULT (20MHz) // For setting a specific frequency, use host.max_freq_khz (range 400kHz - 40MHz for SDMMC) @@ -467,13 +293,64 @@ void app_main(void) // connected on the bus. This is for debug / example purpose only. slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP; - config_sdmmc.host = host; - config_sdmmc.slot_config = slot_config; - storage_config.sdmmc_config = &config_sdmmc; + // not using ff_memalloc here, as allocation in internal RAM is preferred + sd_card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t)); + ESP_GOTO_ON_FALSE(sd_card, ESP_ERR_NO_MEM, clean, TAG, "could not allocate new sdmmc_card_t"); + ESP_GOTO_ON_ERROR((*host.init)(), clean, TAG, "Host Config Init fail"); + host_init = true; + + ESP_GOTO_ON_ERROR(sdmmc_host_init_slot(host.slot, (const sdmmc_slot_config_t *) &slot_config), + clean, TAG, "Host init slot fail"); + + while (sdmmc_card_init(&host, sd_card)) { + ESP_LOGE(TAG, "The detection pin of the slot is disconnected(Insert uSD card). Retrying..."); + vTaskDelay(pdMS_TO_TICKS(3000)); + } + + // Card has been initialized, print its properties + sdmmc_card_print_info(stdout, sd_card); + *card = sd_card; + + return ESP_OK; + +clean: + if (host_init) { + if (host.flags & SDMMC_HOST_FLAG_DEINIT_ARG) { + host.deinit_p(host.slot); + } else { + (*host.deinit)(); + } + } + if (sd_card) { + free(sd_card); + sd_card = NULL; + } + return ret; +} #endif // CONFIG_EXAMPLE_STORAGE_MEDIA_SPIFLASH - ESP_ERROR_CHECK(storage_init(&storage_config)); +void app_main(void) +{ + ESP_LOGI(TAG, "Initializing storage..."); + +#ifdef CONFIG_EXAMPLE_STORAGE_MEDIA_SPIFLASH + static wl_handle_t wl_handle = WL_INVALID_HANDLE; + ESP_ERROR_CHECK(storage_init_spiflash(&wl_handle)); + + const tinyusb_msc_spiflash_config_t config_spi = { + .wl_handle = wl_handle + }; + ESP_ERROR_CHECK(tinyusb_msc_storage_init_spiflash(&config_spi)); +#else // CONFIG_EXAMPLE_STORAGE_MEDIA_SPIFLASH + static sdmmc_card_t *card = NULL; + ESP_ERROR_CHECK(storage_init_sdmmc(&card)); + + const tinyusb_msc_sdmmc_config_t config_sdmmc = { + .card = card + }; + ESP_ERROR_CHECK(tinyusb_msc_storage_init_sdmmc(&config_sdmmc)); +#endif // CONFIG_EXAMPLE_STORAGE_MEDIA_SPIFLASH //mounted in the app by default _mount(); @@ -485,8 +362,6 @@ void app_main(void) .string_descriptor_count = sizeof(string_desc_arr) / sizeof(string_desc_arr[0]), .external_phy = false, .configuration_descriptor = desc_configuration, - .self_powered = true, - .vbus_monitor_io = VBUS_MONITORING_GPIO_NUM, }; ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg)); ESP_LOGI(TAG, "USB MSC initialization DONE"); @@ -506,4 +381,3 @@ void app_main(void) } ESP_ERROR_CHECK(esp_console_start_repl(repl)); } -/*********************************************************************** Application Code*/ diff --git a/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_storage.h b/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_storage.h deleted file mode 100644 index e717490f3d..0000000000 --- a/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_storage.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "esp_err.h" -#include "driver/sdmmc_host.h" - -/* structs, unions - ********************************************************************* */ - -/** - * @brief enum for storage media that are supported - */ -typedef enum { - TINYUSB_STORAGE_INVALID, - TINYUSB_STORAGE_SPI, - TINYUSB_STORAGE_SDMMC, - TINYUSB_STORAGE_MAX, -} tinyusb_storage_type_t; - -#if SOC_SDMMC_HOST_SUPPORTED -/** - * @brief Configuration structure for sdmmc initialization - * - * User configurable parameters that are used while - * initializing the sdmmc media. - */ -typedef struct { - sdmmc_host_t host; - sdmmc_slot_config_t slot_config; -} tinyusb_config_sdmmc_t; -#endif - -/** - * @brief Configuration structure for spiffs initialization - * - * User configurable parameters that are used while - * initializing the SPI Flash media. - */ -typedef struct { - // Place holder. Currently, nothing to configure -} tinyusb_config_spiffs_t; - -/** - * @brief Configuration structure for storage initialization - */ -typedef struct { - tinyusb_storage_type_t storage_type; - union { - tinyusb_config_spiffs_t *spiffs_config; -#if SOC_SDMMC_HOST_SUPPORTED - tinyusb_config_sdmmc_t *sdmmc_config; -#endif - }; -} tinyusb_config_storage_t; -/*********************************************************************** structs, unions */ -/* Public functions - ********************************************************************* */ - -/** - * @brief Initialize the Storage. - * - * Initialize the instance of storage media. - * Once the storage is initialized, other storage functions can be used. - * - * @param config pointer to tinyusb_config_storage_t to pass - * user defined configuration during initialization. - * @return esp_err_t - * - ESP_OK, if success; - * - ESP_ERR_NO_MEM, if there was no memory to allocate storage components; - */ -esp_err_t storage_init(const tinyusb_config_storage_t *config); - -/** - * @brief Mount the storage partition locally on the firmware application. - * - * Get the available drive number. Register spi flash partition. - * Connect POSIX and C standard library IO function with FATFS. - * Mounts the partition. - * This API is used by the firmware application. If the storage partition is - * mounted by this API, host (PC) can't access the storage via MSC. - * - * @param base_path path prefix where FATFS should be registered - * @return esp_err_t - * - ESP_OK, if success; - * - ESP_ERR_NOT_FOUND if the maximum count of volumes is already mounted - * - ESP_ERR_NO_MEM if not enough memory or too many VFSes already registered; - */ -esp_err_t storage_mount(const char *base_path); - -/** - * @brief Unmount the storage partition from the firmware application. - * - * Unmount the partition. Unregister diskio driver. - * Unregister the SPI flash partition. - * Finally, Un-register FATFS from VFS. - * After this function is called, storage device can be seen (recognized) by host (PC). - * - * @return esp_err_t - * - ESP_OK on success - * - ESP_ERR_INVALID_STATE if FATFS is not registered in VFS - */ -esp_err_t storage_unmount(void); - -/** - * @brief Get number of sectors in storage media - * - * @return usable size, in bytes - */ -uint32_t storage_get_sector_count(void); - -/** - * @brief Get sector size of storage media - * - * @return sector count - */ -uint32_t storage_get_sector_size(void); - -/** - * @brief Read data from the storage - * - * @param lba Logical block address of the location of block - * @param offset offset within the lba - * @param size Size of data to be read, in bytes. - * @param dest Pointer to the buffer where data should be stored. - * Pointer must be non-NULL and buffer must be at least 'size' bytes long. - * @return esp_err_t - * - ESP_OK, if data was read successfully; - * - ESP_ERR_INVALID_ARG, if src_offset exceeds partition size; - * - ESP_ERR_INVALID_SIZE, if read would go out of bounds of the partition; - * - or one of error codes from lower-level flash driver. - */ -esp_err_t storage_read_sector(uint32_t lba, uint32_t offset, size_t size, void *dest); - -/** - * @brief Write data to the storage - * - * Before writing data to flash, corresponding region of flash needs to be erased. - * - * @param lba Logical block address of the location of block - * @param offset offset within the lba - * @param size Size of data to be written, in bytes. - * @param src Pointer to the source buffer. Pointer must be non-NULL and - * buffer must be at least 'size' bytes long. - * @return esp_err_t - * - ESP_OK, if data was written successfully; - * - ESP_ERR_INVALID_ARG, if dst_offset exceeds partition size; - * - ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition; - * - or one of error codes from lower-level flash driver. - */ -esp_err_t storage_write_sector(uint32_t lba, uint32_t offset, size_t size, const void *src); - -/*********************************************************************** Public functions*/ - -#ifdef __cplusplus -} -#endif diff --git a/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_storage_sdmmc.c b/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_storage_sdmmc.c deleted file mode 100644 index 5a49f11abf..0000000000 --- a/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_storage_sdmmc.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - -// DESCRIPTION: -// This file contains the code for accessing the storage medium in SD card. - -#include "esp_log.h" -#include "esp_err.h" -#include "esp_check.h" -#include "esp_vfs_fat.h" -#include "diskio_impl.h" -#include "driver/sdmmc_host.h" -#include "diskio_sdmmc.h" -#include "tusb_msc_storage.h" - -static sdmmc_card_t *s_card; -static bool s_fat_mounted; -static const char *s_base_path; - -static const char *TAG = "msc_sdmmc"; - -esp_err_t storage_init(const tinyusb_config_storage_t *config) -{ - esp_err_t ret = ESP_OK; - bool host_init = false; - assert(config->storage_type == TINYUSB_STORAGE_SDMMC); - - ESP_LOGI(TAG, "Initializing SDCard"); - - sdmmc_host_t host = config->sdmmc_config->host; - sdmmc_slot_config_t slot_config = config->sdmmc_config->slot_config; - - // not using ff_memalloc here, as allocation in internal RAM is preferred - s_card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t)); - ESP_GOTO_ON_FALSE(s_card, ESP_ERR_NO_MEM, clean, TAG, "could not allocate new sdmmc_card_t"); - - ESP_GOTO_ON_ERROR((*host.init)(), clean, TAG, "Host Config Init fail"); - host_init = true; - - ESP_GOTO_ON_ERROR(sdmmc_host_init_slot(host.slot, (const sdmmc_slot_config_t *) &slot_config), - clean, TAG, "Host init slot fail"); - - while (sdmmc_card_init(&host, s_card)) { - ESP_LOGE(TAG, "The detection pin of the slot is disconnected(Insert uSD card). Retrying..."); - vTaskDelay(pdMS_TO_TICKS(3000)); - } - - // Card has been initialized, print its properties - sdmmc_card_print_info(stdout, s_card); - - return ESP_OK; - -clean: - if (host_init) { - if (host.flags & SDMMC_HOST_FLAG_DEINIT_ARG) { - host.deinit_p(host.slot); - } else { - (*host.deinit)(); - } - } - if (s_card) { - free(s_card); - s_card = NULL; - } - return ret; -} - -static inline size_t esp_vfs_fat_get_allocation_unit_size( - size_t sector_size, size_t requested_size) -{ - size_t alloc_unit_size = requested_size; - const size_t max_sectors_per_cylinder = 128; - const size_t max_size = sector_size * max_sectors_per_cylinder; - alloc_unit_size = MAX(alloc_unit_size, sector_size); - alloc_unit_size = MIN(alloc_unit_size, max_size); - return alloc_unit_size; -} - -static esp_err_t partition_card(const esp_vfs_fat_mount_config_t *mount_config, - const char *drv, sdmmc_card_t *card, BYTE pdrv) -{ - FRESULT res = FR_OK; - esp_err_t err; - const size_t workbuf_size = 4096; - void *workbuf = NULL; - ESP_LOGW(TAG, "partitioning card"); - - workbuf = ff_memalloc(workbuf_size); - if (workbuf == NULL) { - return ESP_ERR_NO_MEM; - } - - LBA_t plist[] = {100, 0, 0, 0}; - res = f_fdisk(pdrv, plist, workbuf); - if (res != FR_OK) { - err = ESP_FAIL; - ESP_LOGD(TAG, "f_fdisk failed (%d)", res); - goto fail; - } - size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size( - card->csd.sector_size, - mount_config->allocation_unit_size); - ESP_LOGW(TAG, "formatting card, allocation unit size=%d", alloc_unit_size); - const MKFS_PARM opt = {(BYTE)FM_ANY, 0, 0, 0, alloc_unit_size}; - res = f_mkfs(drv, &opt, workbuf, workbuf_size); - if (res != FR_OK) { - err = ESP_FAIL; - ESP_LOGD(TAG, "f_mkfs failed (%d)", res); - goto fail; - } - - free(workbuf); - return ESP_OK; -fail: - free(workbuf); - return err; -} - -static esp_err_t mount_to_vfs_fat(const esp_vfs_fat_mount_config_t *mount_config, sdmmc_card_t *card, uint8_t pdrv, - const char *base_path) -{ - FATFS *fs = NULL; - esp_err_t err; - ff_diskio_register_sdmmc(pdrv, card); - ff_sdmmc_set_disk_status_check(pdrv, mount_config->disk_status_check_enable); - ESP_LOGD(TAG, "using pdrv=%i", pdrv); - char drv[3] = {(char)('0' + pdrv), ':', 0}; - - // connect FATFS to VFS - err = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs); - if (err == ESP_ERR_INVALID_STATE) { - // it's okay, already registered with VFS - } else if (err != ESP_OK) { - ESP_LOGD(TAG, "esp_vfs_fat_register failed 0x(%x)", err); - goto fail; - } - - // Try to mount partition - FRESULT res = f_mount(fs, drv, 1); - if (res != FR_OK) { - err = ESP_FAIL; - ESP_LOGW(TAG, "failed to mount card (%d)", res); - if (!((res == FR_NO_FILESYSTEM || res == FR_INT_ERR) - && mount_config->format_if_mount_failed)) { - goto fail; - } - - err = partition_card(mount_config, drv, card, pdrv); - if (err != ESP_OK) { - goto fail; - } - - ESP_LOGW(TAG, "mounting again"); - res = f_mount(fs, drv, 0); - if (res != FR_OK) { - err = ESP_FAIL; - ESP_LOGD(TAG, "f_mount failed after formatting (%d)", res); - goto fail; - } - } - return ESP_OK; - -fail: - if (fs) { - f_mount(NULL, drv, 0); - } - esp_vfs_fat_unregister_path(base_path); - ff_diskio_unregister(pdrv); - return err; -} - -esp_err_t storage_mount(const char *base_path) -{ - if (s_fat_mounted) { - return ESP_OK; - } - - ESP_LOGI(TAG, "Initializing FAT"); - - // Options for mounting the filesystem. - // If format_if_mount_failed is set to true, SD card will be partitioned and - // formatted in case when mounting fails. - esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = true, - .max_files = 5, - .allocation_unit_size = 16 * 1024 - }; - - // connect driver to FATFS - BYTE pdrv = 0xFF; - ESP_RETURN_ON_ERROR(ff_diskio_get_drive(&pdrv), TAG, - "The maximum count of volumes is already mounted"); - - ESP_LOGI(TAG, "using pdrv=%i", pdrv); - - ESP_RETURN_ON_ERROR(mount_to_vfs_fat(&mount_config, s_card, pdrv, base_path), TAG, - "Failed to mount storage"); - - s_fat_mounted = true; - s_base_path = base_path; - return ESP_OK; -} - -static esp_err_t unmount_card_core(const char *base_path, sdmmc_card_t *card) -{ - BYTE pdrv = ff_diskio_get_pdrv_card(card); - if (pdrv == 0xff) { - return ESP_ERR_INVALID_ARG; - } - - // unmount - char drv[3] = {(char)('0' + pdrv), ':', 0}; - f_mount(0, drv, 0); - // release SD driver - ff_diskio_unregister(pdrv); - - return esp_vfs_fat_unregister_path(base_path); -} - -esp_err_t storage_unmount(void) -{ - if (!s_fat_mounted) { - return ESP_OK; - } - - esp_err_t err = unmount_card_core(s_base_path, s_card); - - s_base_path = NULL; - s_fat_mounted = false; - - return err; - -} - -uint32_t storage_get_sector_count(void) -{ - assert(s_card); - - return (uint32_t)s_card->csd.capacity; -} - -uint32_t storage_get_sector_size(void) -{ - assert(s_card); - - return (uint32_t)s_card->csd.sector_size; -} - -esp_err_t storage_read_sector(uint32_t lba, uint32_t offset, size_t size, void *dest) -{ - assert(s_card); - return sdmmc_read_sectors(s_card, dest, lba, size / storage_get_sector_size()); -} - -esp_err_t storage_write_sector(uint32_t lba, uint32_t offset, size_t size, const void *src) -{ - assert(s_card); - - if (s_fat_mounted) { - ESP_LOGE(TAG, "can't write, FAT mounted"); - return ESP_ERR_INVALID_STATE; - } - size_t addr = lba * storage_get_sector_size() + offset; // Address of the data to be read, relative to the beginning of the partition. - size_t sector_size = s_card->csd.sector_size; - if (addr % sector_size != 0 || size % sector_size != 0) { - return ESP_ERR_INVALID_ARG; - } - - ESP_RETURN_ON_ERROR(sdmmc_erase_sectors(s_card, lba, size / storage_get_sector_size(), SDMMC_ERASE_ARG), - TAG, "Failed to erase"); - - return sdmmc_write_sectors(s_card, src, lba, size / storage_get_sector_size()); -} diff --git a/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_storage_spiffs.c b/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_storage_spiffs.c deleted file mode 100644 index c451a2495e..0000000000 --- a/examples/peripherals/usb/device/tusb_msc/main/tusb_msc_storage_spiffs.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - -// DESCRIPTION: -// This file contains the code for accessing the storage medium i.e. SPI Flash. - -#include "esp_log.h" -#include "esp_err.h" -#include "esp_check.h" -#include "esp_vfs_fat.h" -#include "diskio_impl.h" -#include "diskio_wl.h" -#include "wear_levelling.h" -#include "esp_partition.h" -#include "tusb_msc_storage.h" - -static wl_handle_t s_wl_handle = WL_INVALID_HANDLE; -static bool s_fat_mounted; -static const char *s_base_path; - -static const char *TAG = "msc_spiflash"; - -esp_err_t storage_init(const tinyusb_config_storage_t *config) -{ - assert(config->storage_type == TINYUSB_STORAGE_SPI); - ESP_LOGI(TAG, "Initializing wear levelling"); - - const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, NULL); - if (data_partition == NULL) { - ESP_LOGE(TAG, "Failed to find FATFS partition. Check the partition table."); - return ESP_ERR_NOT_FOUND; - } - - return wl_mount(data_partition, &s_wl_handle); -} - -static inline size_t esp_vfs_fat_get_allocation_unit_size( - size_t sector_size, size_t requested_size) -{ - size_t alloc_unit_size = requested_size; - const size_t max_sectors_per_cylinder = 128; - const size_t max_size = sector_size * max_sectors_per_cylinder; - alloc_unit_size = MAX(alloc_unit_size, sector_size); - alloc_unit_size = MIN(alloc_unit_size, max_size); - return alloc_unit_size; -} - -esp_err_t storage_mount(const char *base_path) -{ - const size_t workbuf_size = 4096; - void *workbuf = NULL; - esp_err_t ret; - - if (s_fat_mounted) { - return ESP_OK; - } - - ESP_LOGI(TAG, "Initializing FAT"); - - // connect driver to FATFS - BYTE pdrv = 0xFF; - ESP_RETURN_ON_ERROR(ff_diskio_get_drive(&pdrv), TAG, - "The maximum count of volumes is already mounted"); - ESP_LOGD(TAG, "using pdrv=%i", pdrv); - char drv[3] = {(char)('0' + pdrv), ':', 0}; - - ESP_GOTO_ON_ERROR(ff_diskio_register_wl_partition(pdrv, s_wl_handle), - fail, TAG, "Failed pdrv=%d", pdrv); - - FATFS *fs; - ret = esp_vfs_fat_register(base_path, drv, 2, &fs); - if (ret == ESP_ERR_INVALID_STATE) { - // it's okay, already registered with VFS - } else if (ret != ESP_OK) { - ESP_LOGE(TAG, "esp_vfs_fat_register failed (0x%x)", ret); - goto fail; - } - - // Try to mount partition - FRESULT fresult = f_mount(fs, drv, 1); - if (fresult != FR_OK) { - ESP_LOGW(TAG, "f_mount failed (%d)", fresult); - if (!((fresult == FR_NO_FILESYSTEM || fresult == FR_INT_ERR))) { - ret = ESP_FAIL; - goto fail; - } - workbuf = ff_memalloc(workbuf_size); - if (workbuf == NULL) { - ret = ESP_ERR_NO_MEM; - goto fail; - } - size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size( - CONFIG_WL_SECTOR_SIZE, - 4096); - - ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d", alloc_unit_size); - const MKFS_PARM opt = {(BYTE)FM_FAT, 0, 0, 0, 0}; - fresult = f_mkfs("", &opt, workbuf, workbuf_size); // Use default volume - if (fresult != FR_OK) { - ret = ESP_FAIL; - ESP_LOGE(TAG, "f_mkfs failed (%d)", fresult); - goto fail; - } - free(workbuf); - workbuf = NULL; - ESP_LOGI(TAG, "Mounting again"); - fresult = f_mount(fs, drv, 0); - if (fresult != FR_OK) { - ret = ESP_FAIL; - ESP_LOGE(TAG, "f_mount failed after formatting (%d)", fresult); - goto fail; - } - } - s_fat_mounted = true; - s_base_path = base_path; - - return ESP_OK; - -fail: - free(workbuf); - esp_vfs_fat_unregister_path(base_path); - ff_diskio_unregister(pdrv); - s_fat_mounted = false; - ESP_LOGW(TAG, "Failed to mount storage (0x%x)", ret); - return ret; -} - -esp_err_t storage_unmount(void) -{ - if (!s_fat_mounted) { - return ESP_OK; - } - - BYTE pdrv = ff_diskio_get_pdrv_wl(s_wl_handle); - if (pdrv == 0xff) { - return ESP_ERR_INVALID_STATE; - } - char drv[3] = {(char)('0' + pdrv), ':', 0}; - - f_mount(0, drv, 0); - ff_diskio_unregister(pdrv); - ff_diskio_clear_pdrv_wl(s_wl_handle); - esp_err_t err = esp_vfs_fat_unregister_path(s_base_path); - s_base_path = NULL; - s_fat_mounted = false; - - return err; - -} - -uint32_t storage_get_sector_count(void) -{ - assert(s_wl_handle != WL_INVALID_HANDLE); - - size_t size = wl_sector_size(s_wl_handle); - if (size == 0) { - ESP_LOGW(TAG, "WL Sector size is zero !!!"); - return 0; - } - return (uint32_t)(wl_size(s_wl_handle) / size); -} - -uint32_t storage_get_sector_size(void) -{ - assert(s_wl_handle != WL_INVALID_HANDLE); - - return (uint32_t)wl_sector_size(s_wl_handle); -} - -esp_err_t storage_read_sector(uint32_t lba, uint32_t offset, size_t size, void *dest) -{ - assert(s_wl_handle != WL_INVALID_HANDLE); - size_t addr = lba * storage_get_sector_size() + offset; // Address of the data to be read, relative to the beginning of the partition. - return wl_read(s_wl_handle, addr, dest, size); -} - -esp_err_t storage_write_sector(uint32_t lba, uint32_t offset, size_t size, const void *src) -{ - assert(s_wl_handle != WL_INVALID_HANDLE); - size_t addr = lba * storage_get_sector_size() + offset; // Address of the data to be read, relative to the beginning of the partition. - if (s_fat_mounted) { - ESP_LOGE(TAG, "can't write, FAT mounted"); - return ESP_ERR_INVALID_STATE; - } - size_t sector_size = wl_sector_size(s_wl_handle); - if (addr % sector_size != 0 || size % sector_size != 0) { - return ESP_ERR_INVALID_ARG; - } - - ESP_RETURN_ON_ERROR(wl_erase_range(s_wl_handle, addr, size), - TAG, "Failed to erase"); - return wl_write(s_wl_handle, addr, src, size); -} diff --git a/examples/peripherals/usb/device/tusb_msc/pytest_usb_device_msc.py b/examples/peripherals/usb/device/tusb_msc/pytest_usb_device_msc.py index b62fa9893b..dc8868a8f1 100644 --- a/examples/peripherals/usb/device/tusb_msc/pytest_usb_device_msc.py +++ b/examples/peripherals/usb/device/tusb_msc/pytest_usb_device_msc.py @@ -8,7 +8,7 @@ from pytest_embedded import Dut @pytest.mark.usb_device def test_usb_device_msc_example(dut: Dut) -> None: dut.expect('Mount storage') - dut.expect('Initializing FAT') + dut.expect('TinyUSB Driver installed') dut.expect('USB MSC initialization DONE') dut.write(' help') dut.expect('read')