mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/usb_msc_updates' into 'master'
refactor(usb_host/msc_example): Increase transfer speeds See merge request espressif/esp-idf!26319
This commit is contained in:
commit
717aa73886
@ -1,4 +1,4 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
espressif/esp_tinyusb: "^1.2"
|
||||
espressif/esp_tinyusb: "^1.4.2"
|
||||
idf: "^5.0"
|
||||
|
@ -347,7 +347,8 @@ void app_main(void)
|
||||
|
||||
const tinyusb_msc_spiflash_config_t config_spi = {
|
||||
.wl_handle = wl_handle,
|
||||
.callback_mount_changed = storage_mount_changed_cb /* First way to register the callback. This is while initializing the storage. */
|
||||
.callback_mount_changed = storage_mount_changed_cb, /* First way to register the callback. This is while initializing the storage. */
|
||||
.mount_config.max_files = 5,
|
||||
};
|
||||
ESP_ERROR_CHECK(tinyusb_msc_storage_init_spiflash(&config_spi));
|
||||
ESP_ERROR_CHECK(tinyusb_msc_register_callback(TINYUSB_MSC_EVENT_MOUNT_CHANGED, storage_mount_changed_cb)); /* Other way to register the callback i.e. registering using separate API. If the callback had been already registered, it will be overwritten. */
|
||||
@ -357,7 +358,8 @@ void app_main(void)
|
||||
|
||||
const tinyusb_msc_sdmmc_config_t config_sdmmc = {
|
||||
.card = card,
|
||||
.callback_mount_changed = storage_mount_changed_cb /* First way to register the callback. This is while initializing the storage. */
|
||||
.callback_mount_changed = storage_mount_changed_cb, /* First way to register the callback. This is while initializing the storage. */
|
||||
.mount_config.max_files = 5,
|
||||
};
|
||||
ESP_ERROR_CHECK(tinyusb_msc_storage_init_sdmmc(&config_sdmmc));
|
||||
ESP_ERROR_CHECK(tinyusb_msc_register_callback(TINYUSB_MSC_EVENT_MOUNT_CHANGED, storage_mount_changed_cb)); /* Other way to register the callback i.e. registering using separate API. If the callback had been already registered, it will be overwritten. */
|
||||
|
@ -5,15 +5,24 @@
|
||||
|
||||
## Overview
|
||||
|
||||
This example demonstrates usage of Mass Storage Class to get access to storage on USB memory stick.
|
||||
Upon connection of USB stick, storage is mounted to Virtual filesystem. Example then creates `ESP` subdirectory(if not present already), as well as `text.txt` file. Its content is then repetitively printed to monitor until USB stick is manually ejected. User can decide whether or not to deinitialize the whole
|
||||
USB stack or not by shorting GPIO10 to ground. When GPIO10 is left unconnected USB stack is not deinitialized, USB stick can be plugged-in again.
|
||||
This example demonstrates usage of the MSC (Mass Storage Class) to access storage on a USB flash drive. Upon connection of the flash drive, it is mounted to the Virtual filesystem. The following example operations are then performed:
|
||||
|
||||
1. Print device info (capacity, sectors size, and count...)
|
||||
2. List all folders and files in the root directory of the USB flash drive
|
||||
3. Create `ESP` subdirectory (if not present already), as well as a `text.txt` file
|
||||
4. Run read/write benchmarks by transferring 1 MB of data to a `dummy` file
|
||||
|
||||
|
||||
### USB Reconnections
|
||||
|
||||
The example is run in a loop so that it can demonstrate USB connection and reconnection handling. If you want to deinitialize the entire USB Host Stack, you can short GPIO0 to GND. GPIO0 is usually mapped to a BOOT button, thus pressing the button will deinitialize the stack.
|
||||
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* Development board with USB capable ESP SoC (ESP32-S2/ESP32-S3)
|
||||
* A USB cable for Power supply and programming
|
||||
* A USB memory stick
|
||||
* A USB flash drive
|
||||
|
||||
### Common Pin Assignments
|
||||
|
||||
@ -30,7 +39,7 @@ ESP BOARD USB CONNECTOR (type A)
|
||||
--
|
||||
```
|
||||
|
||||
Additionally, GPIO10 can be shorted to ground in order to deinitialize USB stack after ejecting USB stick.
|
||||
Additionally, GPIO0 can be shorted to ground in order to deinitialize USB stack.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
@ -48,16 +57,27 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
|
||||
|
||||
```
|
||||
...
|
||||
I (274) cpu_start: Starting scheduler on PRO CPU.
|
||||
I (339) APP: Waiting for USB stick to be connected
|
||||
I (380) example: Waiting for USB flash drive to be connected
|
||||
I (790) example: MSC device connected
|
||||
...
|
||||
Device info:
|
||||
PID: 0x5678
|
||||
VID: 0xFFFF
|
||||
iProduct: Disk 2.0
|
||||
iManufacturer: USB
|
||||
iSerialNumber: 92072836B2589224378
|
||||
I (719) APP: Writing file
|
||||
I (749) APP: Reading file
|
||||
I (749) APP: Read from file: 'Hello World!'
|
||||
I (759) APP: Done
|
||||
Capacity: 29339 MB
|
||||
Sector size: 512
|
||||
Sector count: 60088319
|
||||
PID: 0x5595
|
||||
VID: 0x0781
|
||||
iProduct: SanDisk 3.2Gen1
|
||||
iManufacturer: USB
|
||||
iSerialNumber: 0401545df64623a907abf299bae54c9
|
||||
I (990) example: ls command output:
|
||||
SYSTEM~1
|
||||
ESP
|
||||
DUMMY
|
||||
I (1000) example: Reading file
|
||||
I (1010) example: Read from file '/usb/esp/test.txt': 'Hello World!'
|
||||
I (1030) example: Writing to file /usb/esp/dummy
|
||||
I (2160) example: Write speed 0.93 MiB/s
|
||||
I (2160) example: Reading from file /usb/esp/dummy
|
||||
I (3110) example: Read speed 1.10 MiB/s
|
||||
I (3140) example: Example finished, you can disconnect the USB flash drive
|
||||
```
|
||||
|
@ -1,4 +1,4 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
idf: ">=4.4"
|
||||
usb_host_msc: "^1.0.4"
|
||||
usb_host_msc: "^1.1.1"
|
||||
|
@ -8,43 +8,87 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <inttypes.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "usb/usb_host.h"
|
||||
#include "msc_host.h"
|
||||
#include "msc_host_vfs.h"
|
||||
#include "usb/msc_host.h"
|
||||
#include "usb/msc_host_vfs.h"
|
||||
#include "ffconf.h"
|
||||
#include "errno.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
|
||||
#define USB_DISCONNECT_PIN GPIO_NUM_10
|
||||
|
||||
#define READY_TO_UNINSTALL (HOST_NO_CLIENT | HOST_ALL_FREE)
|
||||
|
||||
typedef enum {
|
||||
HOST_NO_CLIENT = 0x1,
|
||||
HOST_ALL_FREE = 0x2,
|
||||
DEVICE_CONNECTED = 0x4,
|
||||
DEVICE_DISCONNECTED = 0x8,
|
||||
DEVICE_ADDRESS_MASK = 0xFF0,
|
||||
} app_event_t;
|
||||
|
||||
static const char *TAG = "example";
|
||||
static EventGroupHandle_t usb_flags;
|
||||
#define MNT_PATH "/usb" // Path in the Virtual File System, where the USB flash drive is going to be mounted
|
||||
#define APP_QUIT_PIN GPIO_NUM_0 // BOOT button on most boards
|
||||
#define BUFFER_SIZE 4096 // The read/write performance can be improved with larger buffer for the cost of RAM, 4kB is enough for most usecases
|
||||
|
||||
/**
|
||||
* @brief Application Queue and its messages ID
|
||||
*/
|
||||
static QueueHandle_t app_queue;
|
||||
typedef struct {
|
||||
enum {
|
||||
APP_QUIT, // Signals request to exit the application
|
||||
APP_DEVICE_CONNECTED, // USB device connect event
|
||||
APP_DEVICE_DISCONNECTED, // USB device disconnect event
|
||||
} id;
|
||||
union {
|
||||
uint8_t new_dev_address; // Address of new USB device for APP_DEVICE_CONNECTED event if
|
||||
} data;
|
||||
} app_message_t;
|
||||
|
||||
/**
|
||||
* @brief BOOT button pressed callback
|
||||
*
|
||||
* Signal application to exit the main task
|
||||
*
|
||||
* @param[in] arg Unused
|
||||
*/
|
||||
static void gpio_cb(void *arg)
|
||||
{
|
||||
BaseType_t xTaskWoken = pdFALSE;
|
||||
app_message_t message = {
|
||||
.id = APP_QUIT,
|
||||
};
|
||||
|
||||
if (app_queue) {
|
||||
xQueueSendFromISR(app_queue, &message, &xTaskWoken);
|
||||
}
|
||||
|
||||
if (xTaskWoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief MSC driver callback
|
||||
*
|
||||
* Signal device connection/disconnection to the main task
|
||||
*
|
||||
* @param[in] event MSC event
|
||||
* @param[in] arg MSC event data
|
||||
*/
|
||||
static void msc_event_cb(const msc_host_event_t *event, void *arg)
|
||||
{
|
||||
if (event->event == MSC_DEVICE_CONNECTED) {
|
||||
ESP_LOGI(TAG, "MSC device connected");
|
||||
// Obtained USB device address is placed after application events
|
||||
xEventGroupSetBits(usb_flags, DEVICE_CONNECTED | (event->device.address << 4));
|
||||
app_message_t message = {
|
||||
.id = APP_DEVICE_CONNECTED,
|
||||
.data.new_dev_address = event->device.address,
|
||||
};
|
||||
xQueueSend(app_queue, &message, portMAX_DELAY);
|
||||
} else if (event->event == MSC_DEVICE_DISCONNECTED) {
|
||||
xEventGroupSetBits(usb_flags, DEVICE_DISCONNECTED);
|
||||
ESP_LOGI(TAG, "MSC device disconnected");
|
||||
app_message_t message = {
|
||||
.id = APP_DEVICE_DISCONNECTED,
|
||||
};
|
||||
xQueueSend(app_queue, &message, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,24 +101,19 @@ static void print_device_info(msc_host_device_info_t *info)
|
||||
printf("\t Capacity: %llu MB\n", capacity);
|
||||
printf("\t Sector size: %"PRIu32"\n", info->sector_size);
|
||||
printf("\t Sector count: %"PRIu32"\n", info->sector_count);
|
||||
printf("\t PID: 0x%4X \n", info->idProduct);
|
||||
printf("\t VID: 0x%4X \n", info->idVendor);
|
||||
printf("\t PID: 0x%04X \n", info->idProduct);
|
||||
printf("\t VID: 0x%04X \n", info->idVendor);
|
||||
wprintf(L"\t iProduct: %S \n", info->iProduct);
|
||||
wprintf(L"\t iManufacturer: %S \n", info->iManufacturer);
|
||||
wprintf(L"\t iSerialNumber: %S \n", info->iSerialNumber);
|
||||
}
|
||||
|
||||
static bool file_exists(const char *file_path)
|
||||
{
|
||||
struct stat buffer;
|
||||
return stat(file_path, &buffer) == 0;
|
||||
}
|
||||
|
||||
static void file_operations(void)
|
||||
{
|
||||
const char *directory = "/usb/esp";
|
||||
const char *file_path = "/usb/esp/test.txt";
|
||||
|
||||
// Create /usb/esp directory
|
||||
struct stat s = {0};
|
||||
bool directory_exists = stat(directory, &s) == 0;
|
||||
if (!directory_exists) {
|
||||
@ -83,7 +122,8 @@ static void file_operations(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (!file_exists(file_path)) {
|
||||
// Create /usb/esp/test.txt file, if it doesn't exist
|
||||
if (stat(file_path, &s) != 0) {
|
||||
ESP_LOGI(TAG, "Creating file");
|
||||
FILE *f = fopen(file_path, "w");
|
||||
if (f == NULL) {
|
||||
@ -94,6 +134,7 @@ static void file_operations(void)
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
// Read back the file
|
||||
FILE *f;
|
||||
ESP_LOGI(TAG, "Reading file");
|
||||
f = fopen(file_path, "r");
|
||||
@ -109,69 +150,64 @@ static void file_operations(void)
|
||||
if (pos) {
|
||||
*pos = '\0';
|
||||
}
|
||||
ESP_LOGI(TAG, "Read from file: '%s'", line);
|
||||
ESP_LOGI(TAG, "Read from file '%s': '%s'", file_path, line);
|
||||
}
|
||||
|
||||
// Handles common USB host library events
|
||||
static void handle_usb_events(void *args)
|
||||
void speed_test(void)
|
||||
{
|
||||
while (1) {
|
||||
uint32_t event_flags;
|
||||
usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
|
||||
#define TEST_FILE "/usb/esp/dummy"
|
||||
#define ITERATIONS 256 // 256 * 4kb = 1MB
|
||||
int64_t test_start, test_end;
|
||||
|
||||
// Release devices once all clients has deregistered
|
||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
|
||||
usb_host_device_free_all();
|
||||
xEventGroupSetBits(usb_flags, HOST_NO_CLIENT);
|
||||
}
|
||||
// Give ready_to_uninstall_usb semaphore to indicate that USB Host library
|
||||
// can be deinitialized, and terminate this task.
|
||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
|
||||
xEventGroupSetBits(usb_flags, HOST_ALL_FREE);
|
||||
FILE *f = fopen(TEST_FILE, "wb+");
|
||||
if (f == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
// Set larger buffer for this file. It results in larger and more effective USB transfers
|
||||
setvbuf(f, NULL, _IOFBF, BUFFER_SIZE);
|
||||
|
||||
// Allocate application buffer used for read/write
|
||||
uint8_t *data = malloc(BUFFER_SIZE);
|
||||
assert(data);
|
||||
|
||||
ESP_LOGI(TAG, "Writing to file %s", TEST_FILE);
|
||||
test_start = esp_timer_get_time();
|
||||
for (int i = 0; i < ITERATIONS; i++) {
|
||||
if (fwrite(data, BUFFER_SIZE, 1, f) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
test_end = esp_timer_get_time();
|
||||
ESP_LOGI(TAG, "Write speed %1.2f MiB/s", (BUFFER_SIZE * ITERATIONS) / (float)(test_end - test_start));
|
||||
rewind(f);
|
||||
|
||||
vTaskDelete(NULL);
|
||||
ESP_LOGI(TAG, "Reading from file %s", TEST_FILE);
|
||||
test_start = esp_timer_get_time();
|
||||
for (int i = 0; i < ITERATIONS; i++) {
|
||||
if (0 == fread(data, BUFFER_SIZE, 1, f)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
test_end = esp_timer_get_time();
|
||||
ESP_LOGI(TAG, "Read speed %1.2f MiB/s", (BUFFER_SIZE * ITERATIONS) / (float)(test_end - test_start));
|
||||
|
||||
fclose(f);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static uint8_t wait_for_msc_device(void)
|
||||
/**
|
||||
* @brief USB task
|
||||
*
|
||||
* Install USB Host Library and MSC driver.
|
||||
* Handle USB Host Library events
|
||||
*
|
||||
* @param[in] args Unused
|
||||
*/
|
||||
static void usb_task(void *args)
|
||||
{
|
||||
EventBits_t event;
|
||||
|
||||
ESP_LOGI(TAG, "Waiting for USB stick to be connected");
|
||||
event = xEventGroupWaitBits(usb_flags, DEVICE_CONNECTED | DEVICE_ADDRESS_MASK,
|
||||
pdTRUE, pdFALSE, portMAX_DELAY);
|
||||
ESP_LOGI(TAG, "connection...");
|
||||
// Extract USB device address from event group bits
|
||||
return (event & DEVICE_ADDRESS_MASK) >> 4;
|
||||
}
|
||||
|
||||
static bool wait_for_event(EventBits_t event, TickType_t timeout)
|
||||
{
|
||||
return xEventGroupWaitBits(usb_flags, event, pdTRUE, pdTRUE, timeout) & event;
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
msc_host_device_handle_t msc_device;
|
||||
msc_host_vfs_handle_t vfs_handle;
|
||||
msc_host_device_info_t info;
|
||||
BaseType_t task_created;
|
||||
|
||||
const gpio_config_t input_pin = {
|
||||
.pin_bit_mask = BIT64(USB_DISCONNECT_PIN),
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||
};
|
||||
ESP_ERROR_CHECK(gpio_config(&input_pin));
|
||||
|
||||
usb_flags = xEventGroupCreate();
|
||||
assert(usb_flags);
|
||||
|
||||
const usb_host_config_t host_config = { .intr_flags = ESP_INTR_FLAG_LEVEL1 };
|
||||
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
||||
task_created = xTaskCreate(handle_usb_events, "usb_events", 2048, NULL, 2, NULL);
|
||||
assert(task_created);
|
||||
|
||||
const msc_host_driver_config_t msc_config = {
|
||||
.create_backround_task = true,
|
||||
@ -181,37 +217,109 @@ void app_main(void)
|
||||
};
|
||||
ESP_ERROR_CHECK(msc_host_install(&msc_config));
|
||||
|
||||
const esp_vfs_fat_mount_config_t mount_config = {
|
||||
.format_if_mount_failed = false,
|
||||
.max_files = 3,
|
||||
.allocation_unit_size = 1024,
|
||||
};
|
||||
while (true) {
|
||||
uint32_t event_flags;
|
||||
usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
|
||||
|
||||
do {
|
||||
uint8_t device_address = wait_for_msc_device();
|
||||
|
||||
ESP_ERROR_CHECK(msc_host_install_device(device_address, &msc_device));
|
||||
|
||||
msc_host_print_descriptors(msc_device);
|
||||
|
||||
ESP_ERROR_CHECK(msc_host_get_device_info(msc_device, &info));
|
||||
print_device_info(&info);
|
||||
|
||||
ESP_ERROR_CHECK(msc_host_vfs_register(msc_device, "/usb", &mount_config, &vfs_handle));
|
||||
|
||||
while (!wait_for_event(DEVICE_DISCONNECTED, 200)) {
|
||||
file_operations();
|
||||
// Release devices once all clients has deregistered
|
||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
|
||||
if (usb_host_device_free_all() == ESP_OK) {
|
||||
break;
|
||||
};
|
||||
}
|
||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
xEventGroupClearBits(usb_flags, READY_TO_UNINSTALL);
|
||||
ESP_ERROR_CHECK(msc_host_vfs_unregister(vfs_handle));
|
||||
ESP_ERROR_CHECK(msc_host_uninstall_device(msc_device));
|
||||
|
||||
} while (gpio_get_level(USB_DISCONNECT_PIN) != 0);
|
||||
|
||||
ESP_LOGI(TAG, "Uninitializing USB ...");
|
||||
ESP_ERROR_CHECK(msc_host_uninstall());
|
||||
wait_for_event(READY_TO_UNINSTALL, portMAX_DELAY);
|
||||
vTaskDelay(10); // Give clients some time to uninstall
|
||||
ESP_LOGI(TAG, "Deinitializing USB");
|
||||
ESP_ERROR_CHECK(usb_host_uninstall());
|
||||
ESP_LOGI(TAG, "Done");
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// Create FreeRTOS primitives
|
||||
app_queue = xQueueCreate(5, sizeof(app_message_t));
|
||||
assert(app_queue);
|
||||
|
||||
BaseType_t task_created = xTaskCreate(usb_task, "usb_task", 4096, NULL, 2, NULL);
|
||||
assert(task_created);
|
||||
|
||||
// Init BOOT button: Pressing the button simulates app request to exit
|
||||
// It will disconnect the USB device and uninstall the MSC driver and USB Host Lib
|
||||
const gpio_config_t input_pin = {
|
||||
.pin_bit_mask = BIT64(APP_QUIT_PIN),
|
||||
.mode = GPIO_MODE_INPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||
.intr_type = GPIO_INTR_NEGEDGE,
|
||||
};
|
||||
ESP_ERROR_CHECK(gpio_config(&input_pin));
|
||||
ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1));
|
||||
ESP_ERROR_CHECK(gpio_isr_handler_add(APP_QUIT_PIN, gpio_cb, NULL));
|
||||
|
||||
ESP_LOGI(TAG, "Waiting for USB flash drive to be connected");
|
||||
msc_host_device_handle_t msc_device = NULL;
|
||||
msc_host_vfs_handle_t vfs_handle = NULL;
|
||||
|
||||
// Perform all example operations in a loop to allow USB reconnections
|
||||
while (1) {
|
||||
app_message_t msg;
|
||||
xQueueReceive(app_queue, &msg, portMAX_DELAY);
|
||||
|
||||
if (msg.id == APP_DEVICE_CONNECTED) {
|
||||
// 1. MSC flash drive connected. Open it and map it to Virtual File System
|
||||
ESP_ERROR_CHECK(msc_host_install_device(msg.data.new_dev_address, &msc_device));
|
||||
const esp_vfs_fat_mount_config_t mount_config = {
|
||||
.format_if_mount_failed = false,
|
||||
.max_files = 3,
|
||||
.allocation_unit_size = 8192,
|
||||
};
|
||||
ESP_ERROR_CHECK(msc_host_vfs_register(msc_device, MNT_PATH, &mount_config, &vfs_handle));
|
||||
|
||||
// 2. Print information about the connected disk
|
||||
msc_host_device_info_t info;
|
||||
ESP_ERROR_CHECK(msc_host_get_device_info(msc_device, &info));
|
||||
msc_host_print_descriptors(msc_device);
|
||||
print_device_info(&info);
|
||||
|
||||
// 3. List all the files in root directory
|
||||
ESP_LOGI(TAG, "ls command output:");
|
||||
struct dirent *d;
|
||||
DIR *dh = opendir(MNT_PATH);
|
||||
assert(dh);
|
||||
while ((d = readdir(dh)) != NULL) {
|
||||
printf("%s\n", d->d_name);
|
||||
}
|
||||
closedir(dh);
|
||||
|
||||
// 4. The disk is mounted to Virtual File System, perform some basic demo file operation
|
||||
file_operations();
|
||||
|
||||
// 5. Perform speed test
|
||||
speed_test();
|
||||
|
||||
ESP_LOGI(TAG, "Example finished, you can disconnect the USB flash drive");
|
||||
}
|
||||
if ((msg.id == APP_DEVICE_DISCONNECTED) || (msg.id == APP_QUIT)) {
|
||||
if (vfs_handle) {
|
||||
ESP_ERROR_CHECK(msc_host_vfs_unregister(vfs_handle));
|
||||
vfs_handle = NULL;
|
||||
}
|
||||
if (msc_device) {
|
||||
ESP_ERROR_CHECK(msc_host_uninstall_device(msc_device));
|
||||
msc_device = NULL;
|
||||
}
|
||||
if (msg.id == APP_QUIT) {
|
||||
// This will cause the usb_task to exit
|
||||
ESP_ERROR_CHECK(msc_host_uninstall());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Done");
|
||||
gpio_isr_handler_remove(APP_QUIT_PIN);
|
||||
vQueueDelete(app_queue);
|
||||
}
|
||||
|
27
examples/peripherals/usb/host/msc/pytest_usb_host_msc.py
Normal file
27
examples/peripherals/usb/host/msc/pytest_usb_host_msc.py
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.usb_host_flash_disk
|
||||
def test_usb_host_msc_example(dut: Dut) -> None:
|
||||
# Check result of file_operations()
|
||||
dut.expect_exact("example: Read from file '/usb/esp/test.txt': 'Hello World!'")
|
||||
|
||||
# Check result of speed_test()
|
||||
write_throughput = float(dut.expect(r'example: Write speed ([0-9]*[.]?[0-9]+) MiB')[1].decode())
|
||||
read_throughput = float(dut.expect(r'example: Read speed ([0-9]*[.]?[0-9]+) MiB')[1].decode())
|
||||
|
||||
# These values should be updated for HS targets
|
||||
if write_throughput > 0.9:
|
||||
print('Write throughput put OK')
|
||||
else:
|
||||
print('write throughput too slow!')
|
||||
if read_throughput > 1.0:
|
||||
print('Read throughput put OK')
|
||||
else:
|
||||
print('Read throughput too slow!')
|
Loading…
x
Reference in New Issue
Block a user