4. ESP32S3 使用USB 加载SD_SDIO 当作 U盘使用

1.ESP32-S2 USB烧录 输出日志
2.ESP32-S2 USB 挂载内部Flash,当作U盘使用,无线U盘
3.ESP32-S2 USB 挂载SPI-SD,当作U盘使用,无线U盘
4. ESP32S3 使用USB 加载SD_SDIO 当作 U盘使用

1.环境搭建,下载USB库

需要IDF-v4.4 的环境,因为后面使用到的tinyusb依赖v4.4

USB库下载链接:github.com/espressif/esp-iot-solution

4. ESP32S3 使用USB 加载SD_SDIO 当作 U盘使用_第1张图片
将拉取下来的库放到IDF的根目录下
4. ESP32S3 使用USB 加载SD_SDIO 当作 U盘使用_第2张图片

2.将tinyusb添加至项目中

这里使用 SDMMC 官方例程进行移植

注意:你放置的esp-iot-solution是不是在IDF的根目录下!

set(EXTRA_COMPONENT_DIRS {IDF_PATH}/esp-iot-solution/components/usb/tinyusb)

4. ESP32S3 使用USB 加载SD_SDIO 当作 U盘使用_第3张图片

3.Configuration配置

首先将芯片设置为 ESP32S3,否则下面步骤无法操作

3.1 使能 Use TinyUSB Stack

4. ESP32S3 使用USB 加载SD_SDIO 当作 U盘使用_第4张图片

3.2 Enable TinyUSB MSC

4. ESP32S3 使用USB 加载SD_SDIO 当作 U盘使用_第5张图片

3.3 Enable TinyUSB CDC 虚拟串口

4. ESP32S3 使用USB 加载SD_SDIO 当作 U盘使用_第6张图片

4.修改main.c

/* SD card and FAT filesystem example.
   This example code is in the Public Domain (or CC0 licensed, at your option.)
 
   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
 
// This example uses SDMMC peripheral to communicate with SD card.
 
#include 
#include 
#include 
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "driver/sdmmc_host.h"
#include "tusb_msc.h"
#include "tusb_cdc_acm.h"
 
static const char *TAG = "example";
 
 
#define MOUNT_POINT "/sdcard"
static bool usb_install = false;
static bool usb_cdc = false;
static uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE + 1];
static void tinyusb_cdc_rx_callback(int itf, cdcacm_event_t *event)
{
    /* initialization */
    size_t rx_size = 0;
 
    printf("%s need = %d\n", __func__, CONFIG_TINYUSB_CDC_RX_BUFSIZE);
    /* read */
    esp_err_t ret = tinyusb_cdcacm_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE, &rx_size);
    if (ret == ESP_OK) {
 
        printf("rx_buf[%s]\n", buf);
 
    } else {
        ESP_LOGE(TAG, "Read error");
    }
 
}
 
void usb_cdc_init(void)
{
	if(usb_install == false)
	{
		tinyusb_config_t tusb_cfg = {
			.descriptor = NULL,
			.string_descriptor = NULL,
			.external_phy = false // In the most cases you need to use a `false` value
		};
		ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
		usb_install = true;
	}
 
 
    tinyusb_config_cdcacm_t amc_cfg = { 
        .usb_dev = TINYUSB_USBDEV_0,
        .cdc_port = TINYUSB_CDC_ACM_0,
        .rx_unread_buf_sz = 4096,
        .callback_rx = &tinyusb_cdc_rx_callback, // the first way to register a callback
        .callback_rx_wanted_char = NULL,
        .callback_line_state_changed = NULL,
        .callback_line_coding_changed = NULL
    }; // the configuration uses default values
    ESP_ERROR_CHECK(tusb_cdc_acm_init(&amc_cfg));
	usb_cdc = true;
    ESP_LOGI(TAG, "USB initialization cdc device DONE");
}
 
void usb_msc_init(void)
{
	if(usb_install == false)
	{
		tinyusb_config_t tusb_cfg = {
			.descriptor = NULL,
			.string_descriptor = NULL,
			.external_phy = false // In the most cases you need to use a `false` value
		};
		ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
		usb_install = true;
	}
    tinyusb_config_msc_t msc_cfg = {
        .pdrv = 0,
    };
    ESP_ERROR_CHECK(tusb_msc_init(&msc_cfg));
    ESP_LOGI(TAG, "USB initialization msc device DONE");
 
}
void cdc_printf(const char* fmt,...) 
{
	if(usb_cdc == true)
	{
		uint8_t buffer[256] = {0};
		va_list ap;
		va_start(ap,fmt);          			//ap指向fmt的地址
		vsprintf((char *)buffer,fmt,ap);	//vsprintf返回数组的长度
		va_end(ap);
		
		tinyusb_cdcacm_write_queue(0,buffer,strlen((const char *)buffer));
		tud_cdc_n_write_flush(0);
//	tinyusb_cdcacm_write_flush(0, 0);
	}
}
 
void app_main(void)
{
    esp_err_t ret;
 
    // 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 = {
#ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED
        .format_if_mount_failed = true,
#else
        .format_if_mount_failed = false,
#endif // EXAMPLE_FORMAT_IF_MOUNT_FAILED
        .max_files = 5,
        .allocation_unit_size = 16 * 1024
    };
    sdmmc_card_t *card;
    const char mount_point[] = MOUNT_POINT;
    ESP_LOGI(TAG, "Initializing SD card");
 
    // Use settings defined above to initialize SD card and mount FAT filesystem.
    // Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
    // Please check its source code and implement error recovery when developing
    // production applications.
 
    ESP_LOGI(TAG, "Using SDMMC peripheral");
    sdmmc_host_t host = SDMMC_HOST_DEFAULT();
    // This initializes the slot without card detect (CD) and write protect (WP) signals.
    // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
    sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
 
    // To use 1-line SD mode, change this to 1:
    slot_config.width = 4;
    // On chips where the GPIOs used for SD card can be configured, set them in
    // the slot_config structure:
#ifdef SOC_SDMMC_USE_GPIO_MATRIX
    slot_config.clk = GPIO_NUM_14;
    slot_config.cmd = GPIO_NUM_11;
    slot_config.d0 = GPIO_NUM_4;
    slot_config.d1 = GPIO_NUM_45;
    slot_config.d2 = GPIO_NUM_48;
    slot_config.d3 = GPIO_NUM_13;
#endif
 
    // Enable internal pullups on enabled pins. The internal pullups
    // are insufficient however, please make sure 10k external pullups are
    // connected on the bus. This is for debug / example purpose only.
    slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP;
 
    ESP_LOGI(TAG, "Mounting filesystem");
    ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card);
 
    if (ret != ESP_OK) {
        if (ret == ESP_FAIL) {
            ESP_LOGE(TAG, "Failed to mount filesystem. "
                     "If you want the card to be formatted, set the EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
        } else {
            ESP_LOGE(TAG, "Failed to initialize the card (%s). "
                     "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
        }
        return;
    }
    ESP_LOGI(TAG, "Filesystem mounted");
 
    // Card has been initialized, print its properties
    sdmmc_card_print_info(stdout, card);
 
    // Use POSIX and C standard library functions to work with files:
 
    // First create a file.
    const char *file_hello = MOUNT_POINT"/hello.txt";
 
    ESP_LOGI(TAG, "Opening file %s", file_hello);
    FILE *f = fopen(file_hello, "w");
    if (f == NULL) {
        ESP_LOGE(TAG, "Failed to open file for writing");
        return;
    }
    fprintf(f, "Hello %s!\n", card->cid.name);
    fclose(f);
    ESP_LOGI(TAG, "File written");
 
    const char *file_foo = MOUNT_POINT"/foo.txt";
 
    // Check if destination file exists before renaming
    struct stat st;
    if (stat(file_foo, &st) == 0) {
        // Delete it if it exists
        unlink(file_foo);
    }
 
    // Rename original file
    ESP_LOGI(TAG, "Renaming file %s to %s", file_hello, file_foo);
    if (rename(file_hello, file_foo) != 0) {
        ESP_LOGE(TAG, "Rename failed");
        return;
    }
 
    // Open renamed file for reading
    ESP_LOGI(TAG, "Reading file %s", file_foo);
    f = fopen(file_foo, "r");
    if (f == NULL) {
        ESP_LOGE(TAG, "Failed to open file for reading");
        return;
    }
 
    // Read a line from file
    char line[64];
    fgets(line, sizeof(line), f);
    fclose(f);
 
    // Strip newline
    char *pos = strchr(line, '\n');
    if (pos) {
        *pos = '\0';
    }
    ESP_LOGI(TAG, "Read from file: '%s'", line);
    usb_cdc_init();
    usb_msc_init();
    while(1)
    {
        cdc_printf("test\r\n") ;
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    // All done, unmount partition and disable SDMMC peripheral
    // esp_vfs_fat_sdcard_unmount(mount_point, card);
    ESP_LOGI(TAG, "Card unmounted");
}

编译烧录
使用的SDIO接口,但是速度都点慢。之前使用SPI_SD 上次速度都有600~300kb/s左右,之后慢慢研究。。。
4. ESP32S3 使用USB 加载SD_SDIO 当作 U盘使用_第7张图片

补充:将 MSC FIFO size 修改成 4096 上传/下载的速度立马提升几倍
4. ESP32S3 使用USB 加载SD_SDIO 当作 U盘使用_第8张图片

4. ESP32S3 使用USB 加载SD_SDIO 当作 U盘使用_第9张图片
还有虚拟了一个串口,可以收发,就不演示了

感谢 :https://blog.csdn.net/wang123qweasd/article/details/127382780

你可能感兴趣的:(ESP32,ESP32)