安装 ESP-IDF USB Host

这里会初始化:

  • ESP32-P4 USB 2.0 High-Speed控制器
  • USB PHY
  • USB Host协议栈
  • Root Hub:usb支持很多hub枚举,这里是根hub。板子高速USB口接了USB HUB
  • USB设备枚举能力
#include "usb/usb_host.h" //主要头文件
const usb_host_config_t config = {
    .skip_phy_setup = false,
    .intr_flags = ESP_INTR_FLAG_LEVEL1, //USB控制器产生的中断使用Level 1中断优先级。
    .peripheral_map = BIT1 //BIT0 → USB 2.0 High-Speed DWC控制器; BIT1 → Full-Speed USB控制器  默认的BIT0
};
esp_err_t err = usb_host_install(&config);
if (err != ESP_OK) {
    return err;
}

static usb_host_client_handle_t s_probe_client;

static void usb_probe_event(const usb_host_client_event_msg_t *event, void *arg)
{
    (void)arg;
    switch (event->event) {
    case USB_HOST_CLIENT_EVENT_NEW_DEV:
        inspect_usb_device(event->new_dev.address);
        break;
    case USB_HOST_CLIENT_EVENT_DEV_REMOVED:
        ESP_LOGI(TAG, "USB device address=%u removed", event->dev_removed.address);
        break;
    default:
        break;
    }
}
const usb_host_client_config_t probe_config = {
    .is_synchronous = false, //采用异步事件模式
    .max_num_event_msg = 4, 
    .flags = {
        .notify_dev_removed = 1,
    },
    .async.client_event_callback = usb_probe_event, //消息回调 上面的函数
    .async.callback_arg = NULL,
};
usb_host_client_register(&probe_config, &s_probe_client);

xTaskCreate(usb_library_task, "usb_lib", 4096, NULL, 15, NULL); //见下usb_library_task
usb_host_install安装的是整个USB Host系统
但是具体业务模块还需要作为Client注册进去。

USB Host事件处理任务

启动一个任务用来处理

这个任务负责处理:

  • USB设备插入
  • USB设备拔出
  • USB传输完成
  • Hub端口变化
  • 设备地址分配
  • 设备资源释放
xTaskCreate(usb_library_task, "usb_lib", 4096, NULL, 15, NULL)

static void usb_library_task(void *arg)
{
    (void)arg;
    for (;;) {
        uint32_t flags = 0;
        esp_err_t err = usb_host_lib_handle_events(portMAX_DELAY, &flags); //维护整个USB总线正常运行
        if (err != ESP_OK) {
            vTaskDelay(pdMS_TO_TICKS(100));
        } else if (flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
            (void)usb_host_device_free_all(); //Host栈准备退出时,释放仍由Host库管理的全部USB设备。
        }
    }
}
usb_host_lib_handle_events

它会处理:

  • USB控制器事件
  • USB传输完成
  • Root Hub端口变化
  • 外部Hub端口变化
  • 设备插入和拔出
  • 设备复位
  • 分配USB地址
  • 枚举状态机
  • 断开设备后的资源回收

如果不持续调用usb_host_lib_handle_events(),可能出现:

  • 设备不能完成枚举
  • 插拔事件不处理
  • 传输完成事件积压
  • 拔出后资源无法释放
  • Hub下游设备无法继续工作
static void usb_probe_task(void *arg)
{
    while (true) {
        esp_err_t err = usb_host_client_handle_events(
            s_probe_client,
            portMAX_DELAY
        );

        if (err != ESP_OK) {
            break;
        }
    }

    vTaskDelete(NULL);
}

Client的事件需要有人持续处理。