Merge branch 'feat/usb_host_external_power_switch_ci' into 'master'

Feat/usb host external power switch for esp32s2(s3) CI target runners

Closes IEC-238

See merge request espressif/esp-idf!35247
This commit is contained in:
Peter Marcisovsky 2025-01-09 01:16:20 +08:00
commit c4a4de0bb1
10 changed files with 174 additions and 7 deletions

View File

@ -0,0 +1,26 @@
menu "USB HCD Test"
orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps"
config USB_HCD_TEST_OTG_DRVVBUS_ENABLE
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
bool "Enable driving VBUS by an internal DRVVBUS signal from USB-OTG peripheral"
default n
help
USB-OTG peripheral features a DRVVBUS signal, which controls the VBUS voltage. The DRVVBUS signal can be
either internally connected to a PHY (if a PHY supports it), in such a case the PHY would be controlling
the VBUS voltage by itself. Or the DRVVBUS can be handled by an external logic (a transistor switch).
Our PHY does not support the DRVVBUS signal, thus we must use an external logic to control the VBUS
voltage. The DRVVBUS signal is controlled via HCD_PORT_CMD_POWER_OFF and HCD_PORT_CMD_POWER_ON
config USB_HCD_TEST_OTG_DRVVBUS_GPIO
depends on USB_HCD_TEST_OTG_DRVVBUS_ENABLE
int "Connect a GPIO to the internal DRVVBUS signal"
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 1
help
GPIO number, that will be internally connected to the DRVVBUS signal.
USB Host CI target runners feature an external power switch controlled by this GPIO, to control the VBUS
voltage of USB devices during test.
endmenu

View File

@ -21,12 +21,18 @@
#include "test_hcd_common.h"
#include "mock_msc.h"
#include "unity.h"
#include "sdkconfig.h"
#define PORT_NUM 1
#define EVENT_QUEUE_LEN 5
#define ENUM_ADDR 1 // Device address to use for tests that enumerate the device
#define ENUM_CONFIG 1 // Device configuration number to use for tests that enumerate the device
#ifdef CONFIG_USB_HCD_TEST_OTG_DRVVBUS_ENABLE
#define OTG_DRVVBUS_ENABLE
#define OTG_DRVVBUS_GPIO CONFIG_USB_HCD_TEST_OTG_DRVVBUS_GPIO
#endif
typedef struct {
hcd_port_handle_t port_hdl;
hcd_port_event_t port_event;
@ -159,6 +165,24 @@ hcd_port_handle_t test_hcd_setup(void)
.ext_io_conf = NULL,
.otg_io_conf = NULL,
};
#ifdef OTG_DRVVBUS_ENABLE
const usb_phy_otg_io_conf_t otg_io_conf = {
.iddig_io_num = -1,
.avalid_io_num = -1,
.vbusvalid_io_num = -1,
.idpullup_io_num = -1,
.dppulldown_io_num = -1,
.dmpulldown_io_num = -1,
.drvvbus_io_num = OTG_DRVVBUS_GPIO,
.bvalid_io_num = -1,
.sessend_io_num = -1,
.chrgvbus_io_num = -1,
.dischrgvbus_io_num = -1
};
phy_config.otg_io_conf = &otg_io_conf;
#endif // OTG_DRVVBUS_ENABLE
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_new_phy(&phy_config, &phy_hdl), "Failed to init USB PHY");
// Create a queue for port callback to queue up port events
QueueHandle_t port_evt_queue = xQueueCreate(EVENT_QUEUE_LEN, sizeof(port_event_msg_t));

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@ -11,6 +11,6 @@ from pytest_embedded import Dut
@pytest.mark.usb_host_flash_disk
def test_usb_hcd(dut: Dut) -> None:
if (dut.target == 'esp32s3'):
dut.run_all_single_board_cases(group='full_speed')
dut.run_all_single_board_cases(group='full_speed', reset=True)
else:
dut.run_all_single_board_cases(group='high_speed')
dut.run_all_single_board_cases(group='high_speed', reset=True)

View File

@ -0,0 +1,5 @@
# Use external power switch to control USB device's power
# switch is controlled by GPIO 21
CONFIG_USB_HCD_TEST_OTG_DRVVBUS_ENABLE=y
CONFIG_USB_HCD_TEST_OTG_DRVVBUS_GPIO=21

View File

@ -1,5 +1,7 @@
menu "USB Host Library Test"
orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps"
config USB_HOST_TEST_CHECK_MANU_STR
bool "Check manufacturer string descriptor"
default y
@ -21,4 +23,25 @@ menu "USB Host Library Test"
USB Host tests that check string descriptors will check the serial string descriptor
of the connected device.
config USB_HOST_TEST_OTG_DRVVBUS_ENABLE
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
bool "Enable driving VBUS by an internal DRVVBUS signal from USB-OTG peripheral"
default n
help
USB-OTG peripheral features a DRVVBUS signal, which controls the VBUS voltage. The DRVVBUS signal can be
either internally connected to a PHY (if a PHY supports it), in such a case the PHY would be controlling
the VBUS voltage by itself. Or the DRVVBUS can be handled by an external logic (a transistor switch).
Our PHY does not support the DRVVBUS signal, thus we must use an external logic to control the VBUS
voltage. The DRVVBUS signal is controlled via HCD_PORT_CMD_POWER_OFF and HCD_PORT_CMD_POWER_ON
config USB_HOST_TEST_OTG_DRVVBUS_GPIO
depends on USB_HOST_TEST_OTG_DRVVBUS_ENABLE
int "Connect a GPIO to the internal DRVVBUS signal"
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
default 1
help
GPIO number, that will be internally connected to the DRVVBUS signal.
USB Host CI target runners feature an external power switch controlled by this GPIO, to control the VBUS
voltage of USB devices during test.
endmenu

View File

@ -10,15 +10,18 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "dev_msc.h"
#include "test_usb_host_common.h"
#include "usb/usb_host.h"
void setUp(void)
{
unity_utils_record_free_mem();
dev_msc_init();
// Install PHY separately
test_usb_host_setup_phy();
// Install USB Host
usb_host_config_t host_config = {
.skip_phy_setup = false,
.skip_phy_setup = true,
.root_port_unpowered = false,
.intr_flags = ESP_INTR_FLAG_LEVEL1,
};
@ -33,6 +36,7 @@ void tearDown(void)
// Clean up USB Host
printf("USB Host uninstall\n");
ESP_ERROR_CHECK(usb_host_uninstall());
test_usb_host_delete_phy();
// Short delay to allow task to be cleaned up after client uninstall
vTaskDelay(10);
unity_utils_evaluate_leaks();

View File

@ -0,0 +1,65 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "esp_intr_alloc.h"
#include "esp_err.h"
#include "usb/usb_types_ch9.h"
#include "esp_private/usb_phy.h"
#include "test_usb_host_common.h"
#include "unity.h"
#include "sdkconfig.h"
#ifdef CONFIG_USB_HOST_TEST_OTG_DRVVBUS_ENABLE
#define OTG_DRVVBUS_ENABLE
#define OTG_DRVVBUS_GPIO CONFIG_USB_HOST_TEST_OTG_DRVVBUS_GPIO
#endif
static usb_phy_handle_t phy_hdl = NULL;
void test_usb_host_setup_phy(void)
{
// Deinitialize PHY from previous failed test
if (phy_hdl != NULL) {
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_del_phy(phy_hdl), "Failed to delete PHY");
phy_hdl = NULL;
}
// Initialize the internal USB PHY to connect to the USB OTG peripheral
usb_phy_config_t phy_config = {
.controller = USB_PHY_CTRL_OTG,
.target = USB_PHY_TARGET_INT,
.otg_mode = USB_OTG_MODE_HOST,
.otg_speed = USB_PHY_SPEED_UNDEFINED, // In Host mode, the speed is determined by the connected device
.ext_io_conf = NULL,
.otg_io_conf = NULL,
};
#ifdef OTG_DRVVBUS_ENABLE
const usb_phy_otg_io_conf_t otg_io_conf = {
.iddig_io_num = -1,
.avalid_io_num = -1,
.vbusvalid_io_num = -1,
.idpullup_io_num = -1,
.dppulldown_io_num = -1,
.dmpulldown_io_num = -1,
.drvvbus_io_num = OTG_DRVVBUS_GPIO,
.bvalid_io_num = -1,
.sessend_io_num = -1,
.chrgvbus_io_num = -1,
.dischrgvbus_io_num = -1
};
phy_config.otg_io_conf = &otg_io_conf;
#endif // OTG_DRVVBUS_ENABLE
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_new_phy(&phy_config, &phy_hdl), "Failed to init USB PHY");
}
void test_usb_host_delete_phy(void)
{
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_del_phy(phy_hdl), "Failed to delete PHY");
phy_hdl = NULL;
}

View File

@ -0,0 +1,15 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @brief Install PHY separately from the usb_host_install()
*/
void test_usb_host_setup_phy(void);
/**
* @brief Uninstall PHY
*/
void test_usb_host_delete_phy(void);

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@ -11,6 +11,6 @@ from pytest_embedded import Dut
@pytest.mark.usb_host_flash_disk
def test_usb_host(dut: Dut) -> None:
if (dut.target == 'esp32s3'):
dut.run_all_single_board_cases(group='full_speed')
dut.run_all_single_board_cases(group='full_speed', reset=True)
else:
dut.run_all_single_board_cases(group='high_speed')
dut.run_all_single_board_cases(group='high_speed', reset=True)

View File

@ -0,0 +1,5 @@
# Use external power switch to control USB device's power
# switch is controlled by GPIO 21
CONFIG_USB_HOST_TEST_OTG_DRVVBUS_ENABLE=y
CONFIG_USB_HOST_TEST_OTG_DRVVBUS_GPIO=21