diff --git a/components/hal/include/hal/usbh_hal.h b/components/hal/include/hal/usbh_hal.h index 6360f7b3f3..bec00b30cf 100644 --- a/components/hal/include/hal/usbh_hal.h +++ b/components/hal/include/hal/usbh_hal.h @@ -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 */ @@ -18,7 +18,6 @@ NOTE: Thread safety is the responsibility fo the HAL user. All USB Host HAL #include #include #include "soc/usbh_struct.h" -#include "soc/usb_wrap_struct.h" #include "hal/usbh_ll.h" #include "hal/usb_types_private.h" #include "hal/assert.h" @@ -152,7 +151,6 @@ typedef struct { typedef struct { //Context 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 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 */ @@ -181,6 +179,7 @@ typedef struct { * * Entry: * - 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 * - Interrupt allocated but DISABLED (in case of an unknown interupt state) * Exit: diff --git a/components/hal/include/hal/usbh_ll.h b/components/hal/include/hal/usbh_ll.h index 63f7b8219d..4320ead0a3 100644 --- a/components/hal/include/hal/usbh_ll.h +++ b/components/hal/include/hal/usbh_ll.h @@ -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 */ @@ -13,7 +13,6 @@ extern "C" { #include #include #include "soc/usbh_struct.h" -#include "soc/usb_wrap_struct.h" #include "hal/usb_types_private.h" #include "hal/misc.h" @@ -153,25 +152,6 @@ typedef struct { uint8_t *buffer; } 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 ------------------------------- @@ -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 * - * @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 */ static inline void usbh_ll_hcfg_set_defaults(usbh_dev_t *hw, usb_priv_speed_t speed) diff --git a/components/hal/usbh_hal.c b/components/hal/usbh_hal.c index a0e038b0e5..b4a10ca5c5 100644 --- a/components/hal/usbh_hal.c +++ b/components/hal/usbh_hal.c @@ -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 */ @@ -84,7 +84,6 @@ static void set_defaults(usbh_hal_context_t *hal) { - usbh_ll_internal_phy_conf(hal->wrap_dev); //Enable and configure internal PHY //GAHBCFG register usb_ll_en_dma_mode(hal->dev); #ifdef CONFIG_IDF_TARGET_ESP32S2 @@ -114,7 +113,6 @@ void usbh_hal_init(usbh_hal_context_t *hal) //Initialize HAL context memset(hal, 0, sizeof(usbh_hal_context_t)); hal->dev = dev; - hal->wrap_dev = &USB_WRAP; 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_dis_global_intr(hal->dev); //Disable interrupt signal hal->dev = NULL; - hal->wrap_dev = NULL; } void usbh_hal_core_soft_reset(usbh_hal_context_t *hal) diff --git a/components/usb/hcd.c b/components/usb/hcd.c index 5c6720631d..7aa13c7936 100644 --- a/components/usb/hcd.c +++ b/components/usb/hcd.c @@ -1026,20 +1026,6 @@ esp_err_t hcd_install(const hcd_config_t *config) goto err; } 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(); return ESP_OK; @@ -1060,7 +1046,6 @@ esp_err_t hcd_uninstall(void) HCD_EXIT_CRITICAL(); return ESP_ERR_INVALID_STATE; } - periph_module_disable(PERIPH_USB_MODULE); hcd_obj_t *p_hcd_obj_dmy = s_hcd_obj; s_hcd_obj = NULL; HCD_EXIT_CRITICAL(); diff --git a/components/usb/include/esp_private/usb_phy.h b/components/usb/include/esp_private/usb_phy.h index 5e8f9c8df1..5260e0589e 100644 --- a/components/usb/include/esp_private/usb_phy.h +++ b/components/usb/include/esp_private/usb_phy.h @@ -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 */ @@ -63,6 +63,8 @@ typedef struct phy_context_t *usb_phy_handle_t; /**< USB PHY context handle * * @brief Initialize a new USB PHY * Configure at least PHY source. * + * This function will enable the OTG Controller + * * @param[in] config USB PHY configurtion struct * @param[out] handle_ret USB PHY context handle * diff --git a/components/usb/include/usb/usb_host.h b/components/usb/include/usb/usb_host.h index 8902bbe954..72ad885545 100644 --- a/components/usb/include/usb/usb_host.h +++ b/components/usb/include/usb/usb_host.h @@ -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 */ @@ -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 */ 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; /** @@ -118,6 +122,9 @@ typedef struct { * - 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 * + * @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 * @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 * 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 */ esp_err_t usb_host_uninstall(void); diff --git a/components/usb/private_include/hcd.h b/components/usb/private_include/hcd.h index b1e24ae530..de0746461d 100644 --- a/components/usb/private_include/hcd.h +++ b/components/usb/private_include/hcd.h @@ -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 */ @@ -180,9 +180,10 @@ typedef struct { * @brief Installs the Host Controller Driver * * - 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 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 * @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: * - 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_ERR_INVALID_STATE: HCD is not in the right condition to be uninstalled */ diff --git a/components/usb/private_include/usbh.h b/components/usb/private_include/usbh.h index 6d530f7f49..e27441fa70 100644 --- a/components/usb/private_include/usbh.h +++ b/components/usb/private_include/usbh.h @@ -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 */ @@ -88,6 +88,8 @@ typedef struct { * - This function will internally install the HCD * - 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 * @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 * - 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 */ esp_err_t usbh_uninstall(void); diff --git a/components/usb/test/common/test_usb_common.c b/components/usb/test/common/test_usb_common.c index 61f997a98a..c9855ace11 100644 --- a/components/usb/test/common/test_usb_common.c +++ b/components/usb/test/common/test_usb_common.c @@ -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 */ @@ -7,27 +7,38 @@ #include #include "freertos/FreeRTOS.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" -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) { //Delay of 0 ticks causes a yield. So skip if delay_ticks is 0. vTaskDelay(delay_ticks); } - usb_wrap_dev_t *wrap = &USB_WRAP; - 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; - } + ESP_ERROR_CHECK(usb_phy_action(phy_hdl, (connected) ? USB_PHY_ACTION_HOST_ALLOW_CONN : USB_PHY_ACTION_HOST_FORCE_DISCONN)); } diff --git a/components/usb/test/common/test_usb_common.h b/components/usb/test/common/test_usb_common.h index fc8a8379d3..ac88f3432e 100644 --- a/components/usb/test/common/test_usb_common.h +++ b/components/usb/test/common/test_usb_common.h @@ -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 */ @@ -7,10 +7,20 @@ #include #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 * * @param connected For into connected state if true, disconnected if false * @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); diff --git a/components/usb/test/hcd/test_hcd_common.c b/components/usb/test/hcd/test_hcd_common.c index 9116ffa72d..3741289dd8 100644 --- a/components/usb/test/hcd/test_hcd_common.c +++ b/components/usb/test/hcd/test_hcd_common.c @@ -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 */ @@ -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) { + 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 QueueHandle_t port_evt_queue = xQueueCreate(EVENT_QUEUE_LEN, sizeof(port_event_msg_t)); 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_NOT_EQUAL(NULL, 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; } @@ -171,6 +172,7 @@ void test_hcd_teardown(hcd_port_handle_t port_hdl) //Uninstall the HCD TEST_ASSERT_EQUAL(ESP_OK, hcd_uninstall()); 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) @@ -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)); //Wait for connection event 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_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)); @@ -209,7 +211,7 @@ void test_hcd_wait_for_disconn(hcd_port_handle_t port_hdl, bool already_disabled } //Wait for a safe disconnect 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_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)); diff --git a/components/usb/test/hcd/test_hcd_common.h b/components/usb/test/hcd/test_hcd_common.h index a41c9fe451..282e733528 100644 --- a/components/usb/test/hcd/test_hcd_common.h +++ b/components/usb/test/hcd/test_hcd_common.h @@ -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 */ @@ -65,7 +65,7 @@ void test_hcd_teardown(hcd_port_handle_t port_hdl); /** * @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 * @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 * - * @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 already_disabled Whether the HCD port is already in the disabled state diff --git a/components/usb/test/hcd/test_hcd_isoc.c b/components/usb/test/hcd/test_hcd_isoc.c index 7358ff979e..67b6d8f997 100644 --- a/components/usb/test/hcd/test_hcd_isoc.c +++ b/components/usb/test/hcd/test_hcd_isoc.c @@ -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 */ @@ -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 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 test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl)); diff --git a/components/usb/test/hcd/test_hcd_port.c b/components/usb/test/hcd/test_hcd_port.c index 78f17b300b..c79c3047d7 100644 --- a/components/usb/test/hcd/test_hcd_port.c +++ b/components/usb/test/hcd/test_hcd_port.c @@ -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 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 test_hcd_expect_port_event(port_hdl, HCD_PORT_EVENT_DISCONNECTION); 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); vTaskDelay(pdMS_TO_TICKS(10)); //Give a short delay let reset command start in main thread //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 } diff --git a/components/usb/test/usb_host/msc_client_async_dconn.c b/components/usb/test/usb_host/msc_client_async_dconn.c index bbbd9170c2..92de464abd 100644 --- a/components/usb/test/usb_host/msc_client_async_dconn.c +++ b/components/usb/test/usb_host/msc_client_async_dconn.c @@ -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 */ @@ -219,7 +219,7 @@ void msc_client_async_dconn_task(void *arg) TEST_ASSERT_EQUAL(ESP_OK, usb_host_transfer_submit(xfer_in[i])); } //Trigger a disconnect - test_usb_force_conn_state(false, 0); + test_usb_set_phy_state(false, 0); //Next stage set from transfer callback break; } diff --git a/components/usb/test/usb_host/test_usb_host_async.c b/components/usb/test/usb_host/test_usb_host_async.c index aa3a394e96..f69034de74 100644 --- a/components/usb/test/usb_host/test_usb_host_async.c +++ b/components/usb/test/usb_host/test_usb_host_async.c @@ -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 */ @@ -10,6 +10,7 @@ #include "freertos/semphr.h" #include "esp_err.h" #include "esp_intr_alloc.h" +#include "test_usb_common.h" #include "test_usb_mock_classes.h" #include "msc_client.h" #include "ctrl_client.h" @@ -46,8 +47,10 @@ Procedure: 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 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, }; 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); //Clean up USB Host 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_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing //Install USB Host 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, }; 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); //Clean up USB Host ESP_ERROR_CHECK(usb_host_uninstall()); + test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing } diff --git a/components/usb/test/usb_host/test_usb_host_plugging.c b/components/usb/test/usb_host/test_usb_host_plugging.c index 4136529abf..146dcb83ee 100644 --- a/components/usb/test/usb_host/test_usb_host_plugging.c +++ b/components/usb/test/usb_host/test_usb_host_plugging.c @@ -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 */ @@ -26,13 +26,15 @@ static void trigger_dconn_timer_cb(TimerHandle_t xTimer) { 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_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing //Install USB Host Library 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, }; 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)); //Clean up USB Host ESP_ERROR_CHECK(usb_host_uninstall()); + test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing } #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_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing //Install USB Host 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, }; 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); //Clean up USB Host ESP_ERROR_CHECK(usb_host_uninstall()); + test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing } diff --git a/components/usb/usb_host.c b/components/usb/usb_host.c index 8d2f3159c4..41b9ce9dcc 100644 --- a/components/usb/usb_host.c +++ b/components/usb/usb_host.c @@ -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 */ @@ -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 "hub.h" #include "usbh.h" +#include "esp_private/usb_phy.h" #include "usb/usb_host.h" static portMUX_TYPE host_lock = portMUX_INITIALIZER_UNLOCKED; @@ -146,6 +147,7 @@ typedef struct { struct { SemaphoreHandle_t event_sem; SemaphoreHandle_t mux_lock; + usb_phy_handle_t phy_handle; //Will be NULL if host library is installed with skip_phy_setup } constant; } 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); host_lib_obj->constant.event_sem = event_sem; 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 usbh_config_t usbh_config = { .notif_cb = notif_callback, @@ -420,6 +437,10 @@ assign_err: hub_err: ESP_ERROR_CHECK(usbh_uninstall()); 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: if (mux_lock) { vSemaphoreDelete(mux_lock); @@ -444,7 +465,6 @@ esp_err_t usb_host_uninstall(void) //Stop the root hub ESP_ERROR_CHECK(hub_root_stop()); - //Uninstall Hub and USBH ESP_ERROR_CHECK(hub_uninstall()); ESP_ERROR_CHECK(usbh_uninstall()); @@ -454,6 +474,10 @@ esp_err_t usb_host_uninstall(void) p_host_lib_obj = NULL; 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 vSemaphoreDelete(host_lib_obj->constant.mux_lock); vSemaphoreDelete(host_lib_obj->constant.event_sem); diff --git a/examples/peripherals/usb/host/cdc/cdc_acm_bg96/main/cdc_acm_host_bg96.cpp b/examples/peripherals/usb/host/cdc/cdc_acm_bg96/main/cdc_acm_host_bg96.cpp index f7b39949a3..5e7581788c 100644 --- a/examples/peripherals/usb/host/cdc/cdc_acm_bg96/main/cdc_acm_host_bg96.cpp +++ b/examples/peripherals/usb/host/cdc/cdc_acm_bg96/main/cdc_acm_host_bg96.cpp @@ -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 */ @@ -178,6 +178,7 @@ extern "C" void app_main(void) //Install USB Host driver. Should only be called once in entire application ESP_LOGI(TAG, "Installing USB Host"); usb_host_config_t host_config = { + .skip_phy_setup = false, .intr_flags = ESP_INTR_FLAG_LEVEL1, }; ESP_ERROR_CHECK(usb_host_install(&host_config)); diff --git a/examples/peripherals/usb/host/cdc/cdc_acm_host/main/usb-cdc.c b/examples/peripherals/usb/host/cdc/cdc_acm_host/main/usb-cdc.c index 3f6c21d3d5..8534c4416c 100644 --- a/examples/peripherals/usb/host/cdc/cdc_acm_host/main/usb-cdc.c +++ b/examples/peripherals/usb/host/cdc/cdc_acm_host/main/usb-cdc.c @@ -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 */ @@ -53,6 +53,7 @@ void app_main(void) //Install USB Host driver. Should only be called once in entire application ESP_LOGI(TAG, "Installing USB Host"); usb_host_config_t host_config = { + .skip_phy_setup = false, .intr_flags = ESP_INTR_FLAG_LEVEL1, }; ESP_ERROR_CHECK(usb_host_install(&host_config)); diff --git a/examples/peripherals/usb/host/cdc/common/cdc_acm_host/test/test_cdc_acm_host.c b/examples/peripherals/usb/host/cdc/common/cdc_acm_host/test/test_cdc_acm_host.c index fff3c91f5a..b1bf076238 100644 --- a/examples/peripherals/usb/host/cdc/common/cdc_acm_host/test/test_cdc_acm_host.c +++ b/examples/peripherals/usb/host/cdc/common/cdc_acm_host/test/test_cdc_acm_host.c @@ -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 */ @@ -14,6 +14,7 @@ #include "esp_log.h" #include "esp_err.h" +#include "esp_private/usb_phy.h" #include "usb/usb_host.h" #include "usb/cdc_acm_host.h" #include @@ -27,33 +28,32 @@ static uint8_t tx_buf[] = "HELLO"; static uint8_t tx_buf2[] = "WORLD"; static int nb_of_responses; 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) { //Delay of 0 ticks causes a yield. So skip if delay_ticks is 0. vTaskDelay(delay_ticks); } - usb_wrap_dev_t *wrap = &USB_WRAP; - 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; - } + ESP_ERROR_CHECK(usb_phy_action(phy_hdl, (connected) ? USB_PHY_ACTION_HOST_ALLOW_CONN : USB_PHY_ACTION_HOST_FORCE_DISCONN)); } 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 const usb_host_config_t host_config = { + .skip_phy_setup = true, .intr_flags = ESP_INTR_FLAG_LEVEL1, }; 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 usb_host_lib_handle_events(0, NULL); // Make sure there are now pending events 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); } @@ -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_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 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()); vTaskDelay(20); //Short delay to allow task to be cleaned up } diff --git a/examples/peripherals/usb/host/msc/components/msc/test/test_msc.c b/examples/peripherals/usb/host/msc/components/msc/test/test_msc.c index 98d47aac69..58adb6369c 100644 --- a/examples/peripherals/usb/host/msc/components/msc/test/test_msc.c +++ b/examples/peripherals/usb/host/msc/components/msc/test/test_msc.c @@ -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 */ @@ -18,6 +18,7 @@ #include "freertos/semphr.h" #include "esp_err.h" #include "esp_log.h" +#include "esp_private/usb_phy.h" #include "usb/usb_host.h" #include "msc_host.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_vfs_handle_t vfs_handle; 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) { //Delay of 0 ticks causes a yield. So skip if delay_ticks is 0. vTaskDelay(delay_ticks); } - usb_wrap_dev_t *wrap = &USB_WRAP; - 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; - } + ESP_ERROR_CHECK(usb_phy_action(phy_hdl, (connected) ? USB_PHY_ACTION_HOST_ALLOW_CONN : USB_PHY_ACTION_HOST_FORCE_DISCONN)); } 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"); //Trigger a disconnect waiting_for_sudden_disconnect = true; - test_usb_force_conn_state(false, 0); + force_conn_state(false, 0); // Make sure flag was leared in callback 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)) ); - 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) ); 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); vSemaphoreDelete(ready_to_deinit_usb); 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); } diff --git a/examples/peripherals/usb/host/msc/main/msc_example_main.c b/examples/peripherals/usb/host/msc/main/msc_example_main.c index 6514f9174d..4a3d7371dd 100644 --- a/examples/peripherals/usb/host/msc/main/msc_example_main.c +++ b/examples/peripherals/usb/host/msc/main/msc_example_main.c @@ -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 */ @@ -133,7 +133,10 @@ void app_main(void) app_queue = xQueueCreate(3, sizeof(msc_host_event_t)); 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) ); task_created = xTaskCreate(handle_usb_events, "usb_events", 2048, NULL, 2, NULL);