usb: USB Host stack uses USB PHY driver

This commit updates the USB Host stack to use the USB PHY driver. The
USB PHY and the OTG Controller should now both be setup/deleted using
usb_new_phy() and usb_del_phy() respectively.

- The hcd_install() now expects the USB PHY and OTG Contorller to be
    already setup before it is called
- usb_host_install() now has an option to skip calling usb_del_phy() if
    the user wants to setup their own USB PHY (e.g., in the case of using
    and external PHY).
- CDC-ACM and MSC examples/test updated to use internal PHY

Closes https://github.com/espressif/esp-idf/issues/8061
This commit is contained in:
Darian Leung 2021-11-18 02:07:53 +08:00
parent 5a2ef15565
commit 854127a57c
23 changed files with 180 additions and 127 deletions

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -18,7 +18,6 @@ NOTE: Thread safety is the responsibility fo the HAL user. All USB Host HAL
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>
#include "soc/usbh_struct.h" #include "soc/usbh_struct.h"
#include "soc/usb_wrap_struct.h"
#include "hal/usbh_ll.h" #include "hal/usbh_ll.h"
#include "hal/usb_types_private.h" #include "hal/usb_types_private.h"
#include "hal/assert.h" #include "hal/assert.h"
@ -152,7 +151,6 @@ typedef struct {
typedef struct { typedef struct {
//Context //Context
usbh_dev_t *dev; /**< Pointer to base address of DWC_OTG registers */ usbh_dev_t *dev; /**< Pointer to base address of DWC_OTG registers */
usb_wrap_dev_t *wrap_dev; /**< Pointer to base address of USB Wrapper registers */
//Host Port related //Host Port related
uint32_t *periodic_frame_list; /**< Pointer to scheduling frame list */ uint32_t *periodic_frame_list; /**< Pointer to scheduling frame list */
usb_hal_frame_list_len_t frame_list_len; /**< Length of the periodic scheduling frame list */ usb_hal_frame_list_len_t frame_list_len; /**< Length of the periodic scheduling frame list */
@ -181,6 +179,7 @@ typedef struct {
* *
* Entry: * Entry:
* - The peripheral must have been reset and clock un-gated * - The peripheral must have been reset and clock un-gated
* - The USB PHY (internal or external) and associated GPIOs must already be configured
* - GPIO pins configured * - GPIO pins configured
* - Interrupt allocated but DISABLED (in case of an unknown interupt state) * - Interrupt allocated but DISABLED (in case of an unknown interupt state)
* Exit: * Exit:

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -13,7 +13,6 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "soc/usbh_struct.h" #include "soc/usbh_struct.h"
#include "soc/usb_wrap_struct.h"
#include "hal/usb_types_private.h" #include "hal/usb_types_private.h"
#include "hal/misc.h" #include "hal/misc.h"
@ -153,25 +152,6 @@ typedef struct {
uint8_t *buffer; uint8_t *buffer;
} usbh_ll_dma_qtd_t; } usbh_ll_dma_qtd_t;
/* -----------------------------------------------------------------------------
------------------------------ USB Wrap Registers ------------------------------
----------------------------------------------------------------------------- */
/**
* @brief Configures the internal PHY to operate as HOST
*
* @param hw Start address of the USB Wrap registers
*/
static inline void usbh_ll_internal_phy_conf(usb_wrap_dev_t *hw)
{
//Enable internal PHY
hw->otg_conf.pad_enable = 1;
hw->otg_conf.phy_sel = 0;
//Set pulldowns on D+ and D-
hw->otg_conf.pad_pull_override = 1;
hw->otg_conf.dp_pulldown = 1;
hw->otg_conf.dm_pulldown = 1;
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
------------------------------- Global Registers ------------------------------- ------------------------------- Global Registers -------------------------------
@ -431,7 +411,7 @@ static inline void usbh_ll_hcfg_set_fsls_pclk_sel(usbh_dev_t *hw)
/** /**
* @brief Sets some default values to HCFG to operate in Host mode with scatter/gather DMA * @brief Sets some default values to HCFG to operate in Host mode with scatter/gather DMA
* *
* @param hw Start address of the USB Wrap registers * @param hw Start address of the DWC_OTG registers
* @param speed Speed to initialize the host port at * @param speed Speed to initialize the host port at
*/ */
static inline void usbh_ll_hcfg_set_defaults(usbh_dev_t *hw, usb_priv_speed_t speed) static inline void usbh_ll_hcfg_set_defaults(usbh_dev_t *hw, usb_priv_speed_t speed)

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -84,7 +84,6 @@
static void set_defaults(usbh_hal_context_t *hal) static void set_defaults(usbh_hal_context_t *hal)
{ {
usbh_ll_internal_phy_conf(hal->wrap_dev); //Enable and configure internal PHY
//GAHBCFG register //GAHBCFG register
usb_ll_en_dma_mode(hal->dev); usb_ll_en_dma_mode(hal->dev);
#ifdef CONFIG_IDF_TARGET_ESP32S2 #ifdef CONFIG_IDF_TARGET_ESP32S2
@ -114,7 +113,6 @@ void usbh_hal_init(usbh_hal_context_t *hal)
//Initialize HAL context //Initialize HAL context
memset(hal, 0, sizeof(usbh_hal_context_t)); memset(hal, 0, sizeof(usbh_hal_context_t));
hal->dev = dev; hal->dev = dev;
hal->wrap_dev = &USB_WRAP;
set_defaults(hal); set_defaults(hal);
} }
@ -125,7 +123,6 @@ void usbh_hal_deinit(usbh_hal_context_t *hal)
usb_ll_intr_read_and_clear(hal->dev); //Clear interrupts usb_ll_intr_read_and_clear(hal->dev); //Clear interrupts
usb_ll_dis_global_intr(hal->dev); //Disable interrupt signal usb_ll_dis_global_intr(hal->dev); //Disable interrupt signal
hal->dev = NULL; hal->dev = NULL;
hal->wrap_dev = NULL;
} }
void usbh_hal_core_soft_reset(usbh_hal_context_t *hal) void usbh_hal_core_soft_reset(usbh_hal_context_t *hal)

View File

@ -1026,20 +1026,6 @@ esp_err_t hcd_install(const hcd_config_t *config)
goto err; goto err;
} }
s_hcd_obj = p_hcd_obj_dmy; s_hcd_obj = p_hcd_obj_dmy;
//Set HW prerequisites for each port (there's only one)
periph_module_enable(PERIPH_USB_MODULE);
periph_module_reset(PERIPH_USB_MODULE);
/*
Configure GPIOS for Host mode operation using internal PHY
- Forces ID to GND for A side
- Forces B Valid to GND as we are A side host
- Forces VBUS Valid to HIGH
- Forces A Valid to HIGH
*/
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_OTG_IDDIG_IN_IDX, false);
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_SRP_BVALID_IN_IDX, false);
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, false);
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_AVALID_IN_IDX, false);
HCD_EXIT_CRITICAL(); HCD_EXIT_CRITICAL();
return ESP_OK; return ESP_OK;
@ -1060,7 +1046,6 @@ esp_err_t hcd_uninstall(void)
HCD_EXIT_CRITICAL(); HCD_EXIT_CRITICAL();
return ESP_ERR_INVALID_STATE; return ESP_ERR_INVALID_STATE;
} }
periph_module_disable(PERIPH_USB_MODULE);
hcd_obj_t *p_hcd_obj_dmy = s_hcd_obj; hcd_obj_t *p_hcd_obj_dmy = s_hcd_obj;
s_hcd_obj = NULL; s_hcd_obj = NULL;
HCD_EXIT_CRITICAL(); HCD_EXIT_CRITICAL();

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -63,6 +63,8 @@ typedef struct phy_context_t *usb_phy_handle_t; /**< USB PHY context handle *
* @brief Initialize a new USB PHY * @brief Initialize a new USB PHY
* Configure at least PHY source. * Configure at least PHY source.
* *
* This function will enable the OTG Controller
*
* @param[in] config USB PHY configurtion struct * @param[in] config USB PHY configurtion struct
* @param[out] handle_ret USB PHY context handle * @param[out] handle_ret USB PHY context handle
* *

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -91,7 +91,11 @@ typedef void (*usb_host_client_event_cb_t)(const usb_host_client_event_msg_t *ev
* Configuration structure of the USB Host Library. Provided in the usb_host_install() function * Configuration structure of the USB Host Library. Provided in the usb_host_install() function
*/ */
typedef struct { typedef struct {
int intr_flags; /**< Interrupt flags for the underlying ISR used by the USB Host stack */ bool skip_phy_setup; /**< If set, the USB Host Library will not configure the USB PHY thus allowing the user
to manually configure the USB PHY before calling usb_host_install(). Users should
set this if they want to use an external USB PHY. Otherwise, the USB Host Library
will automatically configure the internal USB PHY */
int intr_flags; /**< Interrupt flags for the underlying ISR used by the USB Host stack */
} usb_host_config_t; } usb_host_config_t;
/** /**
@ -118,6 +122,9 @@ typedef struct {
* - This function should only once to install the USB Host Library * - This function should only once to install the USB Host Library
* - This function should be called before any other USB Host Library functions are called * - This function should be called before any other USB Host Library functions are called
* *
* @note If skip_phy_setup is set in the install configuration, the user is responsible for ensuring that the underlying
* Host Controller is enabled and the USB PHY (internal or external) is already setup before this function is
* called.
* @param[in] config USB Host Library configuration * @param[in] config USB Host Library configuration
* @return esp_err_t * @return esp_err_t
*/ */
@ -131,6 +138,8 @@ esp_err_t usb_host_install(const usb_host_config_t *config);
* - All devices must have been freed by calling usb_host_device_free_all() and receiving the * - All devices must have been freed by calling usb_host_device_free_all() and receiving the
* USB_HOST_LIB_EVENT_FLAGS_ALL_FREE event flag * USB_HOST_LIB_EVENT_FLAGS_ALL_FREE event flag
* *
* @note If skip_phy_setup was set when the Host Library was installed, the user is responsible for diasbling the
* underlying Host Controller and USB PHY (internal or external).
* @return esp_err_t * @return esp_err_t
*/ */
esp_err_t usb_host_uninstall(void); esp_err_t usb_host_uninstall(void);

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -180,9 +180,10 @@ typedef struct {
* @brief Installs the Host Controller Driver * @brief Installs the Host Controller Driver
* *
* - Allocates memory and interrupt resources for the HCD and underlying ports * - Allocates memory and interrupt resources for the HCD and underlying ports
* - Setups up HCD to use internal PHY
* *
* @note This function must be called before any other HCD function is called * @note This function must be called before any other HCD function is called
* @note Before calling this function, the Host Controller must already be un-clock gated and reset. The USB PHY
* (internal or external, and associated GPIOs) must already be configured.
* *
* @param config HCD configuration * @param config HCD configuration
* @retval ESP_OK: HCD successfully installed * @retval ESP_OK: HCD successfully installed
@ -199,6 +200,9 @@ esp_err_t hcd_install(const hcd_config_t *config);
* Before uninstalling the HCD, the following conditions should be met: * Before uninstalling the HCD, the following conditions should be met:
* - All ports must be uninitialized, all pipes freed * - All ports must be uninitialized, all pipes freed
* *
* @note This function will simply free the resources used by the HCD. The underlying Host Controller and USB PHY will
* not be disabled.
*
* @retval ESP_OK: HCD successfully uninstalled * @retval ESP_OK: HCD successfully uninstalled
* @retval ESP_ERR_INVALID_STATE: HCD is not in the right condition to be uninstalled * @retval ESP_ERR_INVALID_STATE: HCD is not in the right condition to be uninstalled
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -88,6 +88,8 @@ typedef struct {
* - This function will internally install the HCD * - This function will internally install the HCD
* - This must be called before calling any Hub driver functions * - This must be called before calling any Hub driver functions
* *
* @note Before calling this function, the Host Controller must already be un-clock gated and reset. The USB PHY
* (internal or external, and associated GPIOs) must already be configured.
* @param usbh_config USBH driver configuration * @param usbh_config USBH driver configuration
* @return esp_err_t * @return esp_err_t
*/ */
@ -99,6 +101,8 @@ esp_err_t usbh_install(const usbh_config_t *usbh_config);
* - This function will uninstall the HCD * - This function will uninstall the HCD
* - The Hub driver must be uninstalled before calling this function * - The Hub driver must be uninstalled before calling this function
* *
* @note This function will simply free the resources used by the USBH. The underlying Host Controller and USB PHY will
* not be disabled.
* @return esp_err_t * @return esp_err_t
*/ */
esp_err_t usbh_uninstall(void); esp_err_t usbh_uninstall(void);

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -7,27 +7,38 @@
#include <stdbool.h> #include <stdbool.h>
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "soc/usb_wrap_struct.h" #include "esp_err.h"
#include "hal/usb_phy_types.h"
#include "esp_private/usb_phy.h"
#include "test_usb_common.h" #include "test_usb_common.h"
void test_usb_force_conn_state(bool connected, TickType_t delay_ticks) static usb_phy_handle_t phy_hdl = NULL;
void test_usb_init_phy(void)
{
//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
.gpio_conf = NULL,
};
ESP_ERROR_CHECK(usb_new_phy(&phy_config, &phy_hdl));
}
void test_usb_deinit_phy(void)
{
//Deinitialize the internal USB PHY
ESP_ERROR_CHECK(usb_del_phy(phy_hdl));
phy_hdl = NULL;
}
void test_usb_set_phy_state(bool connected, TickType_t delay_ticks)
{ {
if (delay_ticks > 0) { if (delay_ticks > 0) {
//Delay of 0 ticks causes a yield. So skip if delay_ticks is 0. //Delay of 0 ticks causes a yield. So skip if delay_ticks is 0.
vTaskDelay(delay_ticks); vTaskDelay(delay_ticks);
} }
usb_wrap_dev_t *wrap = &USB_WRAP; ESP_ERROR_CHECK(usb_phy_action(phy_hdl, (connected) ? USB_PHY_ACTION_HOST_ALLOW_CONN : USB_PHY_ACTION_HOST_FORCE_DISCONN));
if (connected) {
//Disable test mode to return to previous internal PHY configuration
wrap->test_conf.test_enable = 0;
} else {
/*
Mimic a disconnection by using the internal PHY's test mode.
Force Output Enable to 1 (even if the controller isn't outputting). With test_tx_dp and test_tx_dm set to 0,
this will look like a disconnection.
*/
wrap->test_conf.val = 0;
wrap->test_conf.test_usb_wrap_oe = 1;
wrap->test_conf.test_enable = 1;
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -7,10 +7,20 @@
#include <stdbool.h> #include <stdbool.h>
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
/**
* @brief Initialize the internal USB PHY and USB Controller for USB Host testing
*/
void test_usb_init_phy(void);
/**
* @brief Deinitalize the internal USB PHY and USB Controller after USB Host testing
*/
void test_usb_deinit_phy(void);
/** /**
* @brief For the USB PHY into the connected or disconnected state * @brief For the USB PHY into the connected or disconnected state
* *
* @param connected For into connected state if true, disconnected if false * @param connected For into connected state if true, disconnected if false
* @param delay_ticks Delay in ticks before forcing state * @param delay_ticks Delay in ticks before forcing state
*/ */
void test_usb_force_conn_state(bool connected, TickType_t delay_ticks); void test_usb_set_phy_state(bool connected, TickType_t delay_ticks);

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -138,6 +138,7 @@ int test_hcd_get_num_pipe_events(hcd_pipe_handle_t pipe_hdl)
hcd_port_handle_t test_hcd_setup(void) hcd_port_handle_t test_hcd_setup(void)
{ {
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
//Create a queue for port callback to queue up port events //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)); QueueHandle_t port_evt_queue = xQueueCreate(EVENT_QUEUE_LEN, sizeof(port_event_msg_t));
TEST_ASSERT_NOT_EQUAL(NULL, port_evt_queue); TEST_ASSERT_NOT_EQUAL(NULL, port_evt_queue);
@ -157,7 +158,7 @@ hcd_port_handle_t test_hcd_setup(void)
TEST_ASSERT_EQUAL(ESP_OK, hcd_port_init(PORT_NUM, &port_config, &port_hdl)); TEST_ASSERT_EQUAL(ESP_OK, hcd_port_init(PORT_NUM, &port_config, &port_hdl));
TEST_ASSERT_NOT_EQUAL(NULL, port_hdl); TEST_ASSERT_NOT_EQUAL(NULL, port_hdl);
TEST_ASSERT_EQUAL(HCD_PORT_STATE_NOT_POWERED, hcd_port_get_state(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_NOT_POWERED, hcd_port_get_state(port_hdl));
test_usb_force_conn_state(false, 0); //Force disconnected state on PHY test_usb_set_phy_state(false, 0); //Force disconnected state on PHY
return port_hdl; return port_hdl;
} }
@ -171,6 +172,7 @@ void test_hcd_teardown(hcd_port_handle_t port_hdl)
//Uninstall the HCD //Uninstall the HCD
TEST_ASSERT_EQUAL(ESP_OK, hcd_uninstall()); TEST_ASSERT_EQUAL(ESP_OK, hcd_uninstall());
vQueueDelete(port_evt_queue); vQueueDelete(port_evt_queue);
test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
} }
usb_speed_t test_hcd_wait_for_conn(hcd_port_handle_t port_hdl) usb_speed_t test_hcd_wait_for_conn(hcd_port_handle_t port_hdl)
@ -180,7 +182,7 @@ usb_speed_t test_hcd_wait_for_conn(hcd_port_handle_t port_hdl)
TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISCONNECTED, hcd_port_get_state(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISCONNECTED, hcd_port_get_state(port_hdl));
//Wait for connection event //Wait for connection event
printf("Waiting for connection\n"); printf("Waiting for connection\n");
test_usb_force_conn_state(true, pdMS_TO_TICKS(100)); //Allow for connected state on PHY test_usb_set_phy_state(true, pdMS_TO_TICKS(100)); //Allow for connected state on PHY
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_CONNECTION); test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_CONNECTION);
TEST_ASSERT_EQUAL(HCD_PORT_EVENT_CONNECTION, hcd_port_handle_event(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_EVENT_CONNECTION, hcd_port_handle_event(port_hdl));
TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISABLED, hcd_port_get_state(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISABLED, hcd_port_get_state(port_hdl));
@ -209,7 +211,7 @@ void test_hcd_wait_for_disconn(hcd_port_handle_t port_hdl, bool already_disabled
} }
//Wait for a safe disconnect //Wait for a safe disconnect
printf("Waiting for disconnection\n"); printf("Waiting for disconnection\n");
test_usb_force_conn_state(false, pdMS_TO_TICKS(100)); //Force disconnected state on PHY test_usb_set_phy_state(false, pdMS_TO_TICKS(100)); //Force disconnected state on PHY
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION);
TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl));
TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl));

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -65,7 +65,7 @@ void test_hcd_teardown(hcd_port_handle_t port_hdl);
/** /**
* @brief Wait for a connection on an HCD port * @brief Wait for a connection on an HCD port
* *
* @note This function will internally call test_usb_force_conn_state() to allow for a connection * @note This function will internally call test_usb_set_phy_state() to allow for a connection
* *
* @param port_hdl Port handle * @param port_hdl Port handle
* @return usb_speed_t Speed of the connected device * @return usb_speed_t Speed of the connected device
@ -75,7 +75,7 @@ usb_speed_t test_hcd_wait_for_conn(hcd_port_handle_t port_hdl);
/** /**
* @brief Wait for a disconnection on an HCD port * @brief Wait for a disconnection on an HCD port
* *
* @note This fucntion will internally call test_usb_force_conn_state() to force a disconnection * @note This fucntion will internally call test_usb_set_phy_state() to force a disconnection
* *
* @param port_hdl Port handle * @param port_hdl Port handle
* @param already_disabled Whether the HCD port is already in the disabled state * @param already_disabled Whether the HCD port is already in the disabled state

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -155,7 +155,7 @@ TEST_CASE("Test HCD isochronous pipe sudden disconnect", "[hcd][ignore]")
} }
//Add a short delay to let the transfers run for a bit //Add a short delay to let the transfers run for a bit
esp_rom_delay_us(POST_ENQUEUE_DELAY_US); esp_rom_delay_us(POST_ENQUEUE_DELAY_US);
test_usb_force_conn_state(false, 0); test_usb_set_phy_state(false, 0);
//Disconnect event should have occurred. Handle the port event //Disconnect event should have occurred. Handle the port event
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION);
TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl));

View File

@ -66,7 +66,7 @@ TEST_CASE("Test HCD port sudden disconnect", "[hcd][ignore]")
} }
//Add a short delay to let the transfers run for a bit //Add a short delay to let the transfers run for a bit
esp_rom_delay_us(POST_ENQUEUE_DELAY_US); esp_rom_delay_us(POST_ENQUEUE_DELAY_US);
test_usb_force_conn_state(false, 0); test_usb_set_phy_state(false, 0);
//Disconnect event should have occurred. Handle the port event //Disconnect event should have occurred. Handle the port event
test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION);
TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl));
@ -275,7 +275,7 @@ static void concurrent_task(void *arg)
xSemaphoreTake(sync_sem, portMAX_DELAY); xSemaphoreTake(sync_sem, portMAX_DELAY);
vTaskDelay(pdMS_TO_TICKS(10)); //Give a short delay let reset command start in main thread vTaskDelay(pdMS_TO_TICKS(10)); //Give a short delay let reset command start in main thread
//Force a disconnection //Force a disconnection
test_usb_force_conn_state(false, 0); test_usb_set_phy_state(false, 0);
vTaskDelay(portMAX_DELAY); //Block forever and wait to be deleted vTaskDelay(portMAX_DELAY); //Block forever and wait to be deleted
} }

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -219,7 +219,7 @@ void msc_client_async_dconn_task(void *arg)
TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in[i])); TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in[i]));
} }
//Trigger a disconnect //Trigger a disconnect
test_usb_force_conn_state(false, 0); test_usb_set_phy_state(false, 0);
//Next stage set from transfer callback //Next stage set from transfer callback
break; break;
} }

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -10,6 +10,7 @@
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "test_usb_common.h"
#include "test_usb_mock_classes.h" #include "test_usb_mock_classes.h"
#include "msc_client.h" #include "msc_client.h"
#include "ctrl_client.h" #include "ctrl_client.h"
@ -46,8 +47,10 @@ Procedure:
TEST_CASE("Test USB Host async (single client)", "[usb_host][ignore]") TEST_CASE("Test USB Host async (single client)", "[usb_host][ignore]")
{ {
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
//Install USB Host //Install USB Host
usb_host_config_t host_config = { usb_host_config_t host_config = {
.skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
.intr_flags = ESP_INTR_FLAG_LEVEL1, .intr_flags = ESP_INTR_FLAG_LEVEL1,
}; };
ESP_ERROR_CHECK(usb_host_install(&host_config)); ESP_ERROR_CHECK(usb_host_install(&host_config));
@ -83,6 +86,7 @@ TEST_CASE("Test USB Host async (single client)", "[usb_host][ignore]")
vTaskDelay(10); vTaskDelay(10);
//Clean up USB Host //Clean up USB Host
ESP_ERROR_CHECK(usb_host_uninstall()); ESP_ERROR_CHECK(usb_host_uninstall());
test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
} }
/* /*
@ -107,8 +111,10 @@ Procedure:
*/ */
TEST_CASE("Test USB Host async (multi client)", "[usb_host][ignore]") TEST_CASE("Test USB Host async (multi client)", "[usb_host][ignore]")
{ {
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
//Install USB Host //Install USB Host
usb_host_config_t host_config = { usb_host_config_t host_config = {
.skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
.intr_flags = ESP_INTR_FLAG_LEVEL1, .intr_flags = ESP_INTR_FLAG_LEVEL1,
}; };
ESP_ERROR_CHECK(usb_host_install(&host_config)); ESP_ERROR_CHECK(usb_host_install(&host_config));
@ -155,4 +161,5 @@ TEST_CASE("Test USB Host async (multi client)", "[usb_host][ignore]")
vTaskDelay(10); vTaskDelay(10);
//Clean up USB Host //Clean up USB Host
ESP_ERROR_CHECK(usb_host_uninstall()); ESP_ERROR_CHECK(usb_host_uninstall());
test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
} }

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -26,13 +26,15 @@
static void trigger_dconn_timer_cb(TimerHandle_t xTimer) static void trigger_dconn_timer_cb(TimerHandle_t xTimer)
{ {
printf("Forcing Sudden Disconnect\n"); printf("Forcing Sudden Disconnect\n");
test_usb_force_conn_state(false, 0); test_usb_set_phy_state(false, 0);
} }
TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][ignore]") TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][ignore]")
{ {
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
//Install USB Host Library //Install USB Host Library
usb_host_config_t host_config = { usb_host_config_t host_config = {
.skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
.intr_flags = ESP_INTR_FLAG_LEVEL1, .intr_flags = ESP_INTR_FLAG_LEVEL1,
}; };
ESP_ERROR_CHECK(usb_host_install(&host_config)); ESP_ERROR_CHECK(usb_host_install(&host_config));
@ -61,6 +63,7 @@ TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][ignore]"
TEST_ASSERT_EQUAL(pdPASS, xTimerDelete(timer_hdl, portMAX_DELAY)); TEST_ASSERT_EQUAL(pdPASS, xTimerDelete(timer_hdl, portMAX_DELAY));
//Clean up USB Host //Clean up USB Host
ESP_ERROR_CHECK(usb_host_uninstall()); ESP_ERROR_CHECK(usb_host_uninstall());
test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
} }
#define TEST_FORCE_DCONN_NUM_TRANSFERS 3 #define TEST_FORCE_DCONN_NUM_TRANSFERS 3
@ -68,8 +71,10 @@ TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][ignore]"
TEST_CASE("Test USB Host sudden disconnection (single client)", "[usb_host][ignore]") TEST_CASE("Test USB Host sudden disconnection (single client)", "[usb_host][ignore]")
{ {
test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
//Install USB Host //Install USB Host
usb_host_config_t host_config = { usb_host_config_t host_config = {
.skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
.intr_flags = ESP_INTR_FLAG_LEVEL1, .intr_flags = ESP_INTR_FLAG_LEVEL1,
}; };
ESP_ERROR_CHECK(usb_host_install(&host_config)); ESP_ERROR_CHECK(usb_host_install(&host_config));
@ -108,4 +113,5 @@ TEST_CASE("Test USB Host sudden disconnection (single client)", "[usb_host][igno
vTaskDelay(10); vTaskDelay(10);
//Clean up USB Host //Clean up USB Host
ESP_ERROR_CHECK(usb_host_uninstall()); ESP_ERROR_CHECK(usb_host_uninstall());
test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
} }

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -19,6 +19,7 @@ Warning: The USB Host Library API is still a beta version and may be subject to
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#include "hub.h" #include "hub.h"
#include "usbh.h" #include "usbh.h"
#include "esp_private/usb_phy.h"
#include "usb/usb_host.h" #include "usb/usb_host.h"
static portMUX_TYPE host_lock = portMUX_INITIALIZER_UNLOCKED; static portMUX_TYPE host_lock = portMUX_INITIALIZER_UNLOCKED;
@ -146,6 +147,7 @@ typedef struct {
struct { struct {
SemaphoreHandle_t event_sem; SemaphoreHandle_t event_sem;
SemaphoreHandle_t mux_lock; SemaphoreHandle_t mux_lock;
usb_phy_handle_t phy_handle; //Will be NULL if host library is installed with skip_phy_setup
} constant; } constant;
} host_lib_t; } host_lib_t;
@ -374,6 +376,21 @@ esp_err_t usb_host_install(const usb_host_config_t *config)
TAILQ_INIT(&host_lib_obj->mux_protected.client_tailq); TAILQ_INIT(&host_lib_obj->mux_protected.client_tailq);
host_lib_obj->constant.event_sem = event_sem; host_lib_obj->constant.event_sem = event_sem;
host_lib_obj->constant.mux_lock = mux_lock; host_lib_obj->constant.mux_lock = mux_lock;
//Setup the USB PHY if necessary (USB PHY driver will also enable the underlying Host Controller)
if (!config->skip_phy_setup) {
//Host Library defaults to internal PHY
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
.gpio_conf = NULL,
};
ret = usb_new_phy(&phy_config, &host_lib_obj->constant.phy_handle);
if (ret != ESP_OK) {
goto phy_err;
}
}
//Install USBH //Install USBH
usbh_config_t usbh_config = { usbh_config_t usbh_config = {
.notif_cb = notif_callback, .notif_cb = notif_callback,
@ -420,6 +437,10 @@ assign_err:
hub_err: hub_err:
ESP_ERROR_CHECK(usbh_uninstall()); ESP_ERROR_CHECK(usbh_uninstall());
usbh_err: usbh_err:
if (p_host_lib_obj->constant.phy_handle) {
ESP_ERROR_CHECK(usb_del_phy(p_host_lib_obj->constant.phy_handle));
}
phy_err:
alloc_err: alloc_err:
if (mux_lock) { if (mux_lock) {
vSemaphoreDelete(mux_lock); vSemaphoreDelete(mux_lock);
@ -444,7 +465,6 @@ esp_err_t usb_host_uninstall(void)
//Stop the root hub //Stop the root hub
ESP_ERROR_CHECK(hub_root_stop()); ESP_ERROR_CHECK(hub_root_stop());
//Uninstall Hub and USBH //Uninstall Hub and USBH
ESP_ERROR_CHECK(hub_uninstall()); ESP_ERROR_CHECK(hub_uninstall());
ESP_ERROR_CHECK(usbh_uninstall()); ESP_ERROR_CHECK(usbh_uninstall());
@ -454,6 +474,10 @@ esp_err_t usb_host_uninstall(void)
p_host_lib_obj = NULL; p_host_lib_obj = NULL;
HOST_EXIT_CRITICAL(); HOST_EXIT_CRITICAL();
//If the USB PHY was setup, then delete it
if (host_lib_obj->constant.phy_handle) {
ESP_ERROR_CHECK(usb_del_phy(host_lib_obj->constant.phy_handle));
}
//Free memory objects //Free memory objects
vSemaphoreDelete(host_lib_obj->constant.mux_lock); vSemaphoreDelete(host_lib_obj->constant.mux_lock);
vSemaphoreDelete(host_lib_obj->constant.event_sem); vSemaphoreDelete(host_lib_obj->constant.event_sem);

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: CC0-1.0 * SPDX-License-Identifier: CC0-1.0
*/ */
@ -178,6 +178,7 @@ extern "C" void app_main(void)
//Install USB Host driver. Should only be called once in entire application //Install USB Host driver. Should only be called once in entire application
ESP_LOGI(TAG, "Installing USB Host"); ESP_LOGI(TAG, "Installing USB Host");
usb_host_config_t host_config = { usb_host_config_t host_config = {
.skip_phy_setup = false,
.intr_flags = ESP_INTR_FLAG_LEVEL1, .intr_flags = ESP_INTR_FLAG_LEVEL1,
}; };
ESP_ERROR_CHECK(usb_host_install(&host_config)); ESP_ERROR_CHECK(usb_host_install(&host_config));

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: CC0-1.0 * SPDX-License-Identifier: CC0-1.0
*/ */
@ -53,6 +53,7 @@ void app_main(void)
//Install USB Host driver. Should only be called once in entire application //Install USB Host driver. Should only be called once in entire application
ESP_LOGI(TAG, "Installing USB Host"); ESP_LOGI(TAG, "Installing USB Host");
usb_host_config_t host_config = { usb_host_config_t host_config = {
.skip_phy_setup = false,
.intr_flags = ESP_INTR_FLAG_LEVEL1, .intr_flags = ESP_INTR_FLAG_LEVEL1,
}; };
ESP_ERROR_CHECK(usb_host_install(&host_config)); ESP_ERROR_CHECK(usb_host_install(&host_config));

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -14,6 +14,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_private/usb_phy.h"
#include "usb/usb_host.h" #include "usb/usb_host.h"
#include "usb/cdc_acm_host.h" #include "usb/cdc_acm_host.h"
#include <string.h> #include <string.h>
@ -27,33 +28,32 @@ static uint8_t tx_buf[] = "HELLO";
static uint8_t tx_buf2[] = "WORLD"; static uint8_t tx_buf2[] = "WORLD";
static int nb_of_responses; static int nb_of_responses;
static int nb_of_responses2; static int nb_of_responses2;
static usb_phy_handle_t phy_hdl = NULL;
void test_usb_force_conn_state(bool connected, TickType_t delay_ticks) static void force_conn_state(bool connected, TickType_t delay_ticks)
{ {
TEST_ASSERT_NOT_EQUAL(NULL, phy_hdl);
if (delay_ticks > 0) { if (delay_ticks > 0) {
//Delay of 0 ticks causes a yield. So skip if delay_ticks is 0. //Delay of 0 ticks causes a yield. So skip if delay_ticks is 0.
vTaskDelay(delay_ticks); vTaskDelay(delay_ticks);
} }
usb_wrap_dev_t *wrap = &USB_WRAP; ESP_ERROR_CHECK(usb_phy_action(phy_hdl, (connected) ? USB_PHY_ACTION_HOST_ALLOW_CONN : USB_PHY_ACTION_HOST_FORCE_DISCONN));
if (connected) {
//Disable test mode to return to previous internal PHY configuration
wrap->test_conf.test_enable = 0;
} else {
/*
Mimic a disconnection by using the internal PHY's test mode.
Force Output Enable to 1 (even if the controller isn't outputting). With test_tx_dp and test_tx_dm set to 0,
this will look like a disconnection.
*/
wrap->test_conf.val = 0;
wrap->test_conf.test_usb_wrap_oe = 1;
wrap->test_conf.test_enable = 1;
}
} }
void usb_lib_task(void *arg) void usb_lib_task(void *arg)
{ {
//Initialize the internal USB PHY to connect to the USB OTG peripheral. We manually install the USB PHY for testing
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
.gpio_conf = NULL,
};
TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_hdl));
// Install USB Host driver. Should only be called once in entire application // Install USB Host driver. Should only be called once in entire application
const usb_host_config_t host_config = { const usb_host_config_t host_config = {
.skip_phy_setup = true,
.intr_flags = ESP_INTR_FLAG_LEVEL1, .intr_flags = ESP_INTR_FLAG_LEVEL1,
}; };
TEST_ASSERT_EQUAL(ESP_OK, usb_host_install(&host_config)); TEST_ASSERT_EQUAL(ESP_OK, usb_host_install(&host_config));
@ -79,6 +79,9 @@ void usb_lib_task(void *arg)
vTaskDelay(10); // Short delay to allow clients clean-up vTaskDelay(10); // Short delay to allow clients clean-up
usb_host_lib_handle_events(0, NULL); // Make sure there are now pending events usb_host_lib_handle_events(0, NULL); // Make sure there are now pending events
TEST_ASSERT_EQUAL(ESP_OK, usb_host_uninstall()); TEST_ASSERT_EQUAL(ESP_OK, usb_host_uninstall());
//Tear down USB PHY
TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_hdl));
phy_hdl = NULL;
vTaskDelete(NULL); vTaskDelete(NULL);
} }
@ -290,11 +293,11 @@ TEST_CASE("USB Host CDC-ACM driver: Sudden disconnection test", "[cdc_acm][ignor
TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_open(0x303A, 0x4002, 0, &dev_config, &cdc_dev)); TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_open(0x303A, 0x4002, 0, &dev_config, &cdc_dev));
TEST_ASSERT_NOT_NULL(cdc_dev); TEST_ASSERT_NOT_NULL(cdc_dev);
test_usb_force_conn_state(false, pdMS_TO_TICKS(10)); force_conn_state(false, pdMS_TO_TICKS(10));
// Notify will succeed only if CDC_ACM_HOST_DEVICE_DISCONNECTED notification was generated // Notify will succeed only if CDC_ACM_HOST_DEVICE_DISCONNECTED notification was generated
TEST_ASSERT_EQUAL(1, ulTaskNotifyTake(false, pdMS_TO_TICKS(100))); TEST_ASSERT_EQUAL(1, ulTaskNotifyTake(false, pdMS_TO_TICKS(100)));
test_usb_force_conn_state(true, 0); // Switch back to real PHY force_conn_state(true, 0); // Switch back to real PHY
TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_uninstall()); TEST_ASSERT_EQUAL(ESP_OK, cdc_acm_host_uninstall());
vTaskDelay(20); //Short delay to allow task to be cleaned up vTaskDelay(20); //Short delay to allow task to be cleaned up
} }

View File

@ -1,6 +1,6 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -18,6 +18,7 @@
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_private/usb_phy.h"
#include "usb/usb_host.h" #include "usb/usb_host.h"
#include "msc_host.h" #include "msc_host.h"
#include "msc_host_vfs.h" #include "msc_host_vfs.h"
@ -45,27 +46,16 @@ static SemaphoreHandle_t ready_to_deinit_usb;
static msc_host_device_handle_t device; static msc_host_device_handle_t device;
static msc_host_vfs_handle_t vfs_handle; static msc_host_vfs_handle_t vfs_handle;
static volatile bool waiting_for_sudden_disconnect; static volatile bool waiting_for_sudden_disconnect;
static usb_phy_handle_t phy_hdl = NULL;
static void test_usb_force_conn_state(bool connected, TickType_t delay_ticks) static void force_conn_state(bool connected, TickType_t delay_ticks)
{ {
TEST_ASSERT_NOT_EQUAL(NULL, phy_hdl);
if (delay_ticks > 0) { if (delay_ticks > 0) {
//Delay of 0 ticks causes a yield. So skip if delay_ticks is 0. //Delay of 0 ticks causes a yield. So skip if delay_ticks is 0.
vTaskDelay(delay_ticks); vTaskDelay(delay_ticks);
} }
usb_wrap_dev_t *wrap = &USB_WRAP; ESP_ERROR_CHECK(usb_phy_action(phy_hdl, (connected) ? USB_PHY_ACTION_HOST_ALLOW_CONN : USB_PHY_ACTION_HOST_FORCE_DISCONN));
if (connected) {
//Disable test mode to return to previous internal PHY configuration
wrap->test_conf.test_enable = 0;
} else {
/*
Mimic a disconnection by using the internal PHY's test mode.
Force Output Enable to 1 (even if the controller isn't outputting). With test_tx_dp and test_tx_dm set to 0,
this will look like a disconnection.
*/
wrap->test_conf.val = 0;
wrap->test_conf.test_usb_wrap_oe = 1;
wrap->test_conf.test_enable = 1;
}
} }
static void msc_event_cb(const msc_host_event_t *event, void *arg) static void msc_event_cb(const msc_host_event_t *event, void *arg)
@ -173,7 +163,7 @@ static void check_sudden_disconnect(void)
ESP_LOGI(TAG, "Trigger a disconnect"); ESP_LOGI(TAG, "Trigger a disconnect");
//Trigger a disconnect //Trigger a disconnect
waiting_for_sudden_disconnect = true; waiting_for_sudden_disconnect = true;
test_usb_force_conn_state(false, 0); force_conn_state(false, 0);
// Make sure flag was leared in callback // Make sure flag was leared in callback
vTaskDelay( pdMS_TO_TICKS(100) ); vTaskDelay( pdMS_TO_TICKS(100) );
@ -193,7 +183,19 @@ static void msc_setup(void)
TEST_ASSERT( app_queue = xQueueCreate(5, sizeof(msc_host_event_t)) ); TEST_ASSERT( app_queue = xQueueCreate(5, sizeof(msc_host_event_t)) );
const usb_host_config_t host_config = { .intr_flags = ESP_INTR_FLAG_LEVEL1 }; //Initialize the internal USB PHY to connect to the USB OTG peripheral. We manually install the USB PHY for testing
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
.gpio_conf = NULL,
};
TEST_ASSERT_EQUAL(ESP_OK, usb_new_phy(&phy_config, &phy_hdl));
const usb_host_config_t host_config = {
.skip_phy_setup = true,
.intr_flags = ESP_INTR_FLAG_LEVEL1,
};
ESP_OK_ASSERT( usb_host_install(&host_config) ); ESP_OK_ASSERT( usb_host_install(&host_config) );
task_created = xTaskCreate(handle_usb_events, "usb_events", 2048, NULL, 2, NULL); task_created = xTaskCreate(handle_usb_events, "usb_events", 2048, NULL, 2, NULL);
@ -229,6 +231,9 @@ static void msc_teardown(void)
xSemaphoreTake(ready_to_deinit_usb, portMAX_DELAY); xSemaphoreTake(ready_to_deinit_usb, portMAX_DELAY);
vSemaphoreDelete(ready_to_deinit_usb); vSemaphoreDelete(ready_to_deinit_usb);
ESP_OK_ASSERT( usb_host_uninstall() ); ESP_OK_ASSERT( usb_host_uninstall() );
//Tear down USB PHY
TEST_ASSERT_EQUAL(ESP_OK, usb_del_phy(phy_hdl));
phy_hdl = NULL;
vQueueDelete(app_queue); vQueueDelete(app_queue);
} }

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -133,7 +133,10 @@ void app_main(void)
app_queue = xQueueCreate(3, sizeof(msc_host_event_t)); app_queue = xQueueCreate(3, sizeof(msc_host_event_t));
assert(app_queue); assert(app_queue);
const usb_host_config_t host_config = { .intr_flags = ESP_INTR_FLAG_LEVEL1 }; const usb_host_config_t host_config = {
.skip_phy_setup = false,
.intr_flags = ESP_INTR_FLAG_LEVEL1,
};
ESP_ERROR_CHECK( usb_host_install(&host_config) ); ESP_ERROR_CHECK( usb_host_install(&host_config) );
task_created = xTaskCreate(handle_usb_events, "usb_events", 2048, NULL, 2, NULL); task_created = xTaskCreate(handle_usb_events, "usb_events", 2048, NULL, 2, NULL);