USB host msc example gives errors after unplugging and pluggind

david.vlastnik
Posts: 2
Joined: Fri Jul 08, 2022 8:36 am

USB host msc example gives errors after unplugging and pluggind

Postby david.vlastnik » Fri Jul 08, 2022 8:49 am

Hello there,

I am using the example of USB host msc from espressif github. When I run it and plug in usb stick it works nice, but after I unplug it and plug it bag in it restarts for some reason.

It gives me this:

Code: Select all

I (2892) ThermalChamber: Writing file
I (14932) ThermalChamber: Writing file
E (21992) USBH: Device 1 gone
I (21992) ThermalChamber: MSC device disconnected
I (24952) ThermalChamber: Waiting for USB stick to be connected
I (26292) ThermalChamber: MSC device connected
I (26292) ThermalChamber: connection...
E (27392) Transfer failed: Status 3
E (27392) USB_MSC: msc_bulk_transfer(533): 
E (27392) USB_MSC_SCSI: bot_execute_command(292): 
E (27392) diskio_usb: scsi_cmd_read10 failed (263)
ESP_ERROR_CHECK failed: esp_err_t 0x1701 (ERROR) at 0x40379004
0x40379004: _esp_error_check_failed at C:/Espressif/frameworks/esp-idf-v4.4.1/components/esp_system/esp_err.c:42

file: "../main/main.c" line 243
func: app_main
expression: msc_host_vfs_register(msc_device, "/usb", &mount_config, &vfs_handle)

abort() was called at PC 0x40379007 on core 0
0x40379007: _esp_error_check_failed at C:/Espressif/frameworks/esp-idf-v4.4.1/components/esp_system/esp_err.c:43



Backtrace:0x40375a12:0x3fcf3c500x40379011:0x3fcf3c70 0x4037f81e:0x3fcf3c90 0x40379007:0x3fcf3d00 0x42006634:0x3fcf3d20 0x4202d071:0x3fcf3e70 0x4037c075:0x3fcf3e90
0x40375a12: panic_abort at C:/Espressif/frameworks/esp-idf-v4.4.1/components/esp_system/panic.c:402

0x40379011: esp_system_abort at C:/Espressif/frameworks/esp-idf-v4.4.1/components/esp_system/esp_system.c:128

0x4037f81e: abort at C:/Espressif/frameworks/esp-idf-v4.4.1/components/newlib/abort.c:46

0x40379007: _esp_error_check_failed at C:/Espressif/frameworks/esp-idf-v4.4.1/components/esp_system/esp_err.c:43

0x42006634: app_main at C:\Users\david\OneDrive\Plocha\esp32\usb_msc\msc\build/../main/main.c:243 (discriminator 1)

0x4202d071: main_task at C:/Espressif/frameworks/esp-idf-v4.4.1/components/freertos/port/port_common.c:129 (discriminator 2)

0x4037c075: vPortTaskWrapper at C:/Espressif/frameworks/esp-idf-v4.4.1/components/freertos/port/xtensa/port.c:131

Code: Select all

#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_err.h"
#include "esp_log.h"
#include "usb/usb_host.h"
#include "msc_host.h"
#include "msc_host_vfs.h"
#include "ffconf.h"
#include "ff.h"
#include "esp_vfs.h"
#include "errno.h"
#include "hal/usb_hal.h"
#include "driver/gpio.h"
#include "esp_vfs_dev.h"

static int size = 0;

#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 = "ThermalChamber";
static EventGroupHandle_t usb_flags;

int file_size(char pathToFile[FILENAME_MAX]) {
	FILE *fp;
    int size_f = 0;

    fp = fopen(pathToFile, "r");
    if (fp == NULL)
    {
        printf("\nFile unable to open...");
		return 0;
    }
    fseek(fp, 0, 2);    /* File pointer at the end of file */
    size_f = ftell(fp);   /* Take a position of file pointer in size variable */
	fclose(fp);
	return size_f;
}

void utilized_storage(const char directory[100]) {
    DIR *d;
    char tempDir[100];
    strcpy(tempDir, directory);
    struct dirent *dir;
    d = opendir(directory);

    if(d) {
        while((dir = readdir(d)) != NULL) {
            if((strcmp(dir->d_name, "SYSTEM~1") != 0) && (strcmp(dir->d_name, ".") != 0) && (strcmp(dir->d_name, "..") != 0)) {
                if(dir->d_type == 2) {
                    //folder
                    strcat(tempDir, dir->d_name);
                    utilized_storage(tempDir);
                    strcpy(tempDir, directory);
                }
                else if(dir->d_type == 1){
                    //file               
                    char tempDir2[100];
					strcpy(tempDir2, tempDir);
                    if(strcmp(tempDir2, "/usb/") != 0) {
					    strcat(tempDir2, "/");
                    }
					strcat(tempDir2, dir->d_name);
                    printf("%s\n", tempDir2);

					size += file_size(tempDir2);
                }
            }
        }
    }
}

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));
    } else if (event->event == MSC_DEVICE_DISCONNECTED) {
        xEventGroupSetBits(usb_flags, DEVICE_DISCONNECTED);
        ESP_LOGI(TAG, "MSC device disconnected");
    }
}

static void print_device_info(msc_host_device_info_t *info)
{
    utilized_storage("/usb/");

    uint64_t capacity = ((uint64_t)info->sector_size * info->sector_count);
    uint64_t freeCapacity = capacity - (uint64_t)size;
    
    printf("Device info:\n");
    printf("\t Sector size: %u\n", info->sector_size);
    printf("\t Sector count: %u\n", info->sector_count);
    printf("\t PID: 0x%4X \n", info->idProduct);
    printf("\t VID: 0x%4X \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);
    printf("\t Storage: %llu B\n", capacity);
    printf("\t Availible storage: %lld B\n", freeCapacity);
}

static void file_operations(void)
{
    const char *directory = "/usb/esp";
    const char *file_path = "/usb/esp/test.csv";


    struct stat s = {0};
    bool directory_exists = stat(directory, &s) == 0;
    if (!directory_exists) {
        if (mkdir(directory, 0775) != 0) {
            ESP_LOGE(TAG, "mkdir failed with errno: %s\n", strerror(errno));
        }
    }
    

    ESP_LOGI(TAG, "Writing file");
    FILE *f = fopen(file_path, "a"); //a -> appending at the end of the existing file, if it doesn't exist, file is created
    if (f == NULL) {
        ESP_LOGE(TAG, "Failed to open file for writing");
        return;
    }

    fprintf(f, "x\n");
    fclose(f);
    

    /*ESP_LOGI(TAG, "Reading file");
    f = fopen(file_path, "r");
    if (f == NULL) {
        ESP_LOGE(TAG, "Failed to open file for reading");
        return;
    }
    char line[64];
    fgets(line, sizeof(line), f);
    fclose(f);
    char *pos = strchr(line, '\n');
    if (pos) {
        *pos = '\0';
    }
    ESP_LOGI(TAG, "Read from file: '%s'", line);*/
}

// Handles common USB host library events
static void handle_usb_events(void *args)
{
    while (1) {
        uint32_t event_flags;
        usb_host_lib_handle_events(portMAX_DELAY, &event_flags);

        // 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);
        }
    }

    vTaskDelete(NULL);
}

static uint8_t wait_for_msc_device(void)
{
    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 = (1 << 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,
        .task_priority = 5,
        .stack_size = 2048,
        .callback = msc_event_cb,
    };
    ESP_ERROR_CHECK( msc_host_install(&msc_config) );


    do {
    const esp_vfs_fat_mount_config_t mount_config = {
            .format_if_mount_failed = false,
            .max_files = 1,
            .allocation_unit_size = 1024,
        };

    
        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_vfs_register(msc_device, "/usb", &mount_config, &vfs_handle) );

        ESP_ERROR_CHECK( msc_host_get_device_info(msc_device, &info) );
        print_device_info(&info);

        while (!wait_for_event(DEVICE_DISCONNECTED, 200)) {
            file_operations();
            vTaskDelay(1000);
        }

        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); //0(true) -> for writing again after removing; 1(false) -> for uninitializing USB
    

    ESP_LOGI(TAG, "Uninitializing USB...");
    ESP_ERROR_CHECK( msc_host_uninstall() );
    wait_for_event(READY_TO_UNINSTALL, portMAX_DELAY);
    ESP_ERROR_CHECK( usb_host_uninstall() );
    ESP_LOGI(TAG, "Done");
}
Thank you for the replies. :D

donalm
Posts: 5
Joined: Wed Apr 06, 2022 10:35 am

Re: USB host msc example gives errors after unplugging and pluggind

Postby donalm » Mon Oct 24, 2022 12:07 pm

Hi David,
Did you have any luck with this? I'm hitting the same issue, unfortunately.
Cheers,
Donal

david.vlastnik
Posts: 2
Joined: Fri Jul 08, 2022 8:36 am

Re: USB host msc example gives errors after unplugging and pluggind

Postby david.vlastnik » Thu Oct 27, 2022 7:14 am

Hello ther donalm,

When i tried to debug it, it always led to msc_host.c, to function msc_bulk_transfer. There is setting of this variable xfer->timeout_ms, which was set to 1000, so I tried to increase it to 3000 and it works nice for me. I guess it is some kind of "waiting timeout", some kind of time that it is waiting for the msc device to initialize and when it is not done in 1000ms, then it throws error.

chegewara
Posts: 2375
Joined: Wed Jun 14, 2017 9:00 pm

Re: USB host msc example gives errors after unplugging and pluggind

Postby chegewara » Sat Oct 29, 2022 1:24 am

david.vlastnik wrote: Hello ther donalm,

When i tried to debug it, it always led to msc_host.c, to function msc_bulk_transfer. There is setting of this variable xfer->timeout_ms, which was set to 1000, so I tried to increase it to 3000 and it works nice for me. I guess it is some kind of "waiting timeout", some kind of time that it is waiting for the msc device to initialize and when it is not done in 1000ms, then it throws error.
You are close enough. USB specification says about 5000ms timeout and as far as i remember it has been fixed in esp-idf recently. Im not sure if its backported or just in master branch.

donalm
Posts: 5
Joined: Wed Apr 06, 2022 10:35 am

Re: USB host msc example gives errors after unplugging and pluggind

Postby donalm » Mon Oct 31, 2022 8:13 am

david.vlastnik wrote:
Thu Oct 27, 2022 7:14 am
Hello ther donalm,

When i tried to debug it, it always led to msc_host.c, to function msc_bulk_transfer. There is setting of this variable xfer->timeout_ms, which was set to 1000, so I tried to increase it to 3000 and it works nice for me. I guess it is some kind of "waiting timeout", some kind of time that it is waiting for the msc device to initialize and when it is not done in 1000ms, then it throws error.
That's great David, thank you for sharing.

parinacota
Posts: 1
Joined: Mon Aug 28, 2023 2:54 pm

Re: USB host msc example gives errors after unplugging and pluggind

Postby parinacota » Mon Aug 28, 2023 3:02 pm

Hello,

I try to run this code as well on an ESP32-S3 (to check if I can flash an RP2040 through USB Mass Storage access), but unfortunately I got an error on the

Code: Select all

#include "msc_host_vfs.h
--> No such file or directory.

I did researches for this files on my computer (VSCode and Arduino libraries), but seems that this file is not on my filesystem at all. And looking for it on GitHub (espressif projects) or Googling it only retrive... this thread.

--> Do you have any hint for this file?

The good thing is my ESP nevers panic yet :-)

With another - lower level - usb example, I was able to list the connected RP2040 as mass-storage and list the attributes, but this is quite far from the file system I wanted to write on...

Regards,

Bertrand

eco747
Posts: 2
Joined: Fri Apr 22, 2016 4:57 pm

Re: USB host msc example gives errors after unplugging and pluggind

Postby eco747 » Fri Sep 22, 2023 8:34 am

Got the same problem with file not found.
I something on github:
https://github.com/nathalislight/esp32s3_USB_Drive

Who is online

Users browsing this forum: Bing [Bot] and 130 guests