ESP MSC OTA

[中文]

esp_msc_ota` is an OTA (Over-The-Air) driver based on USB MSC (USB Mass Storage Class). It supports reading programs from a USB flash drive and burning them into a designated OTA partition, thereby enabling OTA upgrades via USB.

Features:

  1. Supports OTA updates by retrieving programs from a USB flash drive via USB interface.

  2. Supports hot-plugging of the USB flash drive.

User Guide

Hardware requirements:

  • Any development board with a USB OTG interface capable of providing external power.

  • A USB flash drive using the BOT (Bulk-Only Transport) protocol and Transparent SCSI command set.

Partition Table:

  • Includes an OTA partition.

Code examples

  1. Call esp_msc_host_install to initialize the MSC host driver. Set skip_init_usb_host_driver to true only when the application has already installed the USB Host Library and has a task calling usb_host_lib_handle_events().

esp_msc_host_config_t msc_host_config = {
    .base_path = "/usb",
    .host_driver_config = DEFAULT_MSC_HOST_DRIVER_CONFIG(),
    .vfs_fat_mount_config = DEFAULT_ESP_VFS_FAT_MOUNT_CONFIG(),
    .host_config = DEFAULT_USB_HOST_CONFIG()
};
esp_msc_host_handle_t host_handle = NULL;
esp_msc_host_install(&msc_host_config, &host_handle);
  1. Call esp_msc_ota to complete OTA updates. host_handle is required so OTA can wait for the MSC VFS mount and keep it locked while reading. Use ota_bin_path to specify the OTA file path and wait_msc_connect to specify the waiting time for USB drive insertion in FreeRTOS ticks.

esp_msc_ota_config_t config = {
    .host_handle = host_handle,
    .ota_bin_path = "/usb/ota_test.bin",
    .wait_msc_connect = pdMS_TO_TICKS(5000),
};
esp_msc_ota(&config);
  1. Call esp_restart() after a successful OTA update. If the application needs to shut down the MSC host instead, call esp_msc_host_uninstall() only after the USB disk is disconnected and the MSC device is no longer mounted.

  2. Call esp_event_handler_register to register the event handler for obtaining OTA process details.

esp_event_loop_create_default();
esp_event_handler_register(ESP_MSC_OTA_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL);
  1. To observe MSC host events (device connect/disconnect, device install/uninstall, VFS register/unregister), set event_cb and event_cb_arg in esp_msc_host_config_t. Starting from v2.0.0, the MSC host no longer dispatches events through the default esp_event loop and the ESP_MSC_HOST_EVENT event base has been removed; this callback is now the only notification channel for host events.

static void msc_host_event_cb(esp_msc_host_handle_t handle,
                              esp_msc_host_event_t event, void *user_ctx)
{
    switch (event) {
    case ESP_MSC_HOST_CONNECT:
    case ESP_MSC_HOST_DISCONNECT:
    case ESP_MSC_HOST_DEVICE_INSTALL:
    case ESP_MSC_HOST_DEVICE_UNINSTALL:
    case ESP_MSC_HOST_VFS_REGISTER:
    case ESP_MSC_HOST_VFS_UNREGISTER:
        // Handle the corresponding event
        break;
    }
}

esp_msc_host_config_t msc_host_config = {
    /* ... */
    .event_cb = msc_host_event_cb,
    .event_cb_arg = NULL,
};

API Reference

Header File

Functions

bool esp_msc_host_is_mounted(esp_msc_host_handle_t handle)

Check if the MSC VFS is mounted.

Parameters

handle[in] Handle for the MSC host driver

Returns

true if the VFS is mounted

Returns

false if the VFS is not mounted or the handle is invalid

esp_err_t esp_msc_host_wait_mounted(esp_msc_host_handle_t handle, TickType_t timeout)

Block until the MSC VFS is mounted (or timeout elapses).

Returns immediately with ESP_OK when the VFS is already mounted. Otherwise the calling task is suspended and woken up as soon as the internal MSC host task finishes mounting the device.

Parameters
  • handle[in] Handle for the MSC host driver

  • timeout[in] Maximum time to wait, in FreeRTOS ticks. Use portMAX_DELAY to wait indefinitely, or 0 for a non-blocking poll.

Returns

ESP_OK on success

Returns

ESP_ERR_INVALID_ARG if handle is invalid

Returns

ESP_ERR_TIMEOUT if the VFS was not mounted before the timeout expired

esp_err_t esp_msc_host_lock(esp_msc_host_handle_t handle, TickType_t timeout)

Lock MSC file access before reading from the mounted VFS.

This prevents the host task from unregistering VFS while a client is actively reading files from the MSC device.

Parameters
  • handle[in] Handle for the MSC host driver

  • timeout[in] Timeout in FreeRTOS ticks

Returns

ESP_OK on success

Returns

ESP_ERR_INVALID_ARG if handle is invalid

Returns

ESP_ERR_INVALID_STATE if VFS is not mounted

Returns

ESP_ERR_TIMEOUT if the lock cannot be taken in time

esp_err_t esp_msc_host_unlock(esp_msc_host_handle_t handle)

Unlock MSC file access.

Parameters

handle[in] Handle for the MSC host driver

Returns

ESP_OK on success

Returns

ESP_ERR_INVALID_ARG if handle is invalid

esp_err_t esp_msc_host_install(esp_msc_host_config_t *config, esp_msc_host_handle_t *handle)

Install the MSC USB HOST.

Note

When the USB flash drive is inserted, do not call uninstall immediately afterward.

Parameters
Returns

esp_err_t ESP_ERR_INVALID_ARG if any of the parameters are invalid. ESP_ERR_NO_MEM if memory can not be allocated for the driver. ESP_FAIL if the driver fails to install. ESP_OK on success.

esp_err_t esp_msc_host_uninstall(esp_msc_host_handle_t handle)

Uninstall the MSC USB HOST.

Note

When the USB flash drive is inserted, you need to pull out the USB flash drive.

Parameters

handle[in] Handle for the MSC host driver

Returns

esp_err_t ESP_ERR_INVALID_ARG Invalid argument. ESP_ERR_INVALID_STATE if an MSC device is still connected or mounted. ESP_OK on success.

Structures

struct esp_msc_host_config_t

MSC host driver configuration passed to esp_msc_host_install().

Public Members

const char *base_path

Base path for mounting FATFS.

usb_host_config_t host_config

Configuration structure of the USB Host Library. Provided in the usb_host_install() function

msc_host_driver_config_t host_driver_config

MSC configuration structure. Do not register the callback variable

esp_vfs_fat_mount_config_t vfs_fat_mount_config

Configuration arguments for msc_host_vfs_register function

bool skip_init_usb_host_driver

Skip USB Host Library install/uninstall and event handling task. The application must install USB Host and call usb_host_lib_handle_events()

esp_msc_host_event_cb_t event_cb

Optional direct callback for MSC host events

void *event_cb_arg

User context for event_cb

Macros

DEFAULT_USB_HOST_CONFIG()
DEFAULT_MSC_HOST_DRIVER_CONFIG()
DEFAULT_ESP_VFS_FAT_MOUNT_CONFIG()

Type Definitions

typedef struct esp_msc_host_ctx *esp_msc_host_handle_t

Opaque MSC host handle.

The concrete type is private to the component; users must only pass the value returned by esp_msc_host_install() to the host APIs.

typedef void (*esp_msc_host_event_cb_t)(esp_msc_host_handle_t handle, esp_msc_host_event_t event, void *user_ctx)

MSC host event callback.

This callback is optional and is the only notification path for MSC host events. The handle identifies the host instance that generated the event.

Enumerations

enum esp_msc_host_event_t

MSC host events reported through esp_msc_host_event_cb_t.

Values:

enumerator ESP_MSC_HOST_CONNECT

MSC device connected

enumerator ESP_MSC_HOST_DISCONNECT

MSC device disconnected

enumerator ESP_MSC_HOST_DEVICE_INSTALL

MSC device installed

enumerator ESP_MSC_HOST_DEVICE_UNINSTALL

MSC device uninstalled

enumerator ESP_MSC_HOST_VFS_REGISTER

VFS driver registered

enumerator ESP_MSC_HOST_VFS_UNREGISTER

VFS driver unregistered

Header File

Functions

esp_err_t esp_msc_ota_begin(const esp_msc_ota_config_t *config, esp_msc_ota_handle_t *handle)

Start MSC OTA Firmware upgrade.

If this function succeeds, then call esp_msc_ota_performto continue with the OTA process otherwise call esp_msc_ota_end.

Parameters
  • config[in] pointer to esp_msc_ota_config_t structure

  • handle[out] pointer to an allocated data of type esp_msc_ota_handle_t which will be initialised in this function

Returns

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG: Invalid argument (missing/incorrect config, handle, etc.)

  • ESP_ERR_NO_MEM: Failed to allocate memory for msc_ota handle

  • ESP_FAIL: For generic failure.

esp_err_t esp_msc_ota_perform(esp_msc_ota_handle_t handle)

Read data from the firmware on the USB flash drive and start the upgrade,.

It is necessary to call this function several times and ensure that the value returned each time is ESP_OK. and call esp_msc_ota_is_complete_data_received to monitor whether the firmware upgrade is complete or not. Make sure that the VFS file system is not unmounted during the fread process. If you manually unplug the USB flash drive or log out of the USB HOST, stop calling esp_msc_ota_perform before and call esp_msc_ota_abort afterwards.

Parameters

handle[in] Handle for the MSC ota

Returns

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG: Invalid argument

  • ESP_ERR_INVALID_STATE: Invalid state (handle not initialized, etc.)

  • ESP_ERR_INVALID_SIZE: Fread failed

  • ESP_FAIL: For generic failure.

  • For other errors, please check the API for the specific error.

esp_err_t esp_msc_ota_end(esp_msc_ota_handle_t handle)

Clean-up MSC OTA Firmware upgrade.

Note

If this API returns successfully, esp_restart() must be called to boot from the new firmware image esp_https_ota_finish should not be called after calling esp_msc_ota_abort

Parameters

handle[in] Handle for the MSC ota

Returns

  • ESP_ERR_INVALID_ARG: Invalid argument

  • ESP_ERR_INVALID_STATE: Incorrect status

  • ESP_OK: Success

  • For other errors, please check the API for the specific error.

esp_err_t esp_msc_ota_abort(esp_msc_ota_handle_t handle)

Clean-up MSC OTA Firmware upgrade and call esp_ota_abort

Note

esp_msc_ota_abort should not be called after calling esp_msc_ota_finish

Parameters

handle[in] Handle for the MSC ota

Returns

  • ESP_ERR_INVALID_ARG: Invalid argument

  • ESP_ERR_INVALID_STATE: Incorrect status

  • ESP_OK: Success

  • For other errors, please check the API for the specific error.

esp_err_t esp_msc_ota(const esp_msc_ota_config_t *config)

MSC OTA Firmware upgrade.

This function provides a complete set of MSC_OTA upgrade procedures. When the USB flash disk is inserted, it will be upgraded automatically. After the upgrade is completed, please call esp_restart()

Parameters

config[in] pointer to esp_msc_ota_config_t structure

Returns

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG: Invalid argument

  • ESP_OK: Success

  • For other errors, please check the API for the specific error.

esp_err_t esp_msc_ota_get_img_desc(esp_msc_ota_handle_t handle, esp_app_desc_t *new_app_info)

Reads app description from image header. The app description provides information like the “Firmware version” of the image.

Parameters
  • handle[in] pointer to esp_msc_ota_config_t structure

  • new_app_info[out] pointer to an allocated esp_app_desc_t structure

Returns

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG: Invalid argument

  • ESP_ERR_INVALID_STATE: Incorrect status

  • ESP_FAIL: Fail to read image header

esp_msc_ota_status_t esp_msc_ota_get_status(esp_msc_ota_handle_t handle)

Get the status of the MSC ota.

Parameters

handle[in] Handle for the MSC ota

Returns

esp_msc_ota_status_t

bool esp_msc_ota_is_complete_data_received(esp_msc_ota_handle_t handle)

Checks if complete data was received or not.

This API can be called just before esp_msc_ota_end() to validate if the complete image was indeed received.

Parameters

handle[in] Handle for the MSC ota

Returns

true

Returns

false

Structures

struct esp_msc_ota_config_t

esp msc ota config

Public Members

esp_msc_host_handle_t host_handle

MSC host handle. OTA waits for this host’s VFS mounted state and locks file access through the host API

const char *ota_bin_path

OTA binary name, must be an exact match. Note: By default file names cannot exceed 11 bytes e.g. “/usb/ota.bin”

TickType_t wait_msc_connect

Wait time for MSC VFS mount in FreeRTOS ticks

size_t buffer_size

Buffer size for OTA write operation, must larger than 1024

bool bulk_flash_erase

Erase entire flash partition during initialization. By default flash partition is erased during write operation and in chunk of 4K sector size

Type Definitions

typedef struct esp_msc_ota_ctx *esp_msc_ota_handle_t

Opaque MSC OTA handle.

The concrete type is private to the component; users must only pass the value returned by esp_msc_ota_begin() to the OTA APIs. Note that this is a different type from esp_msc_host_handle_t and the two handles must not be used interchangeably.

Enumerations

enum esp_msc_ota_event_t

Declare Event Base for ESP MSC OTA.

MSC OTA events posted on ESP_MSC_OTA_EVENT event base.

Values:

enumerator ESP_MSC_OTA_START

Start update, event data: NULL

enumerator ESP_MSC_OTA_READY_UPDATE

Ready to update, event data: NULL

enumerator ESP_MSC_OTA_WRITE_FLASH

Flash write operation, event data: float *progress

enumerator ESP_MSC_OTA_FAILED

Update failed, event data: esp_err_t *err

enumerator ESP_MSC_OTA_GET_IMG_DESC

Get image description, event data: NULL

enumerator ESP_MSC_OTA_VERIFY_CHIP_ID

Verify chip id, event data: esp_chip_id_t *chip_id

enumerator ESP_MSC_OTA_UPDATE_BOOT_PARTITION

Boot partition update after successful ota update, event data: esp_partition_subtype_t *subtype

enumerator ESP_MSC_OTA_FINISH

OTA finished, event data: NULL

enumerator ESP_MSC_OTA_ABORT

OTA aborted, event data: NULL

enum esp_msc_ota_status_t

Internal state of an esp_msc_ota handle.

Values:

enumerator ESP_MSC_OTA_INIT

Handle allocated but esp_msc_ota_begin() not called yet

enumerator ESP_MSC_OTA_BEGIN

esp_msc_ota_begin() succeeded, ready for esp_msc_ota_perform()

enumerator ESP_MSC_OTA_IN_PROGRESS

Firmware image is being written to flash

enumerator ESP_MSC_OTA_SUCCESS

Full firmware image has been written