From 58606027da8eb7d552b03ba22130d60dcfaec844 Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Wed, 10 Jan 2024 10:06:20 +0100 Subject: [PATCH] feat(usb/host): Calculate FIFO sizes based on USB configuration --- components/hal/include/hal/usb_dwc_hal.h | 2 +- components/hal/include/hal/usb_dwc_ll.h | 71 +------------------- components/hal/usb_dwc_hal.c | 84 +++++++++++------------- 3 files changed, 41 insertions(+), 116 deletions(-) diff --git a/components/hal/include/hal/usb_dwc_hal.h b/components/hal/include/hal/usb_dwc_hal.h index 38fd1fe341..2ee7104b6f 100644 --- a/components/hal/include/hal/usb_dwc_hal.h +++ b/components/hal/include/hal/usb_dwc_hal.h @@ -176,7 +176,7 @@ typedef struct { 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 */ //FIFO related - const usb_dwc_hal_fifo_config_t *fifo_config; /**< FIFO sizes configuration */ + usb_dwc_hal_fifo_config_t fifo_config; /**< FIFO sizes configuration */ union { struct { uint32_t dbnc_lock_enabled: 1; /**< Debounce lock enabled */ diff --git a/components/hal/include/hal/usb_dwc_ll.h b/components/hal/include/hal/usb_dwc_ll.h index 7d0b021f47..e52e3bfa0f 100644 --- a/components/hal/include/hal/usb_dwc_ll.h +++ b/components/hal/include/hal/usb_dwc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,75 +32,6 @@ extern "C" { #define USB_DWC_QTD_LIST_MEM_ALIGN 512 #define USB_DWC_FRAME_LIST_MEM_ALIGN 512 // The frame list needs to be 512 bytes aligned (contrary to the databook) -/* -Although we have a 256 lines, only 200 lines are useable due to EPINFO_CTL. -Todo: Check sizes again and express this macro in terms of DWC config options (IDF-7384) -*/ -#define USB_DWC_FIFO_TOTAL_USABLE_LINES 200 - -/* ----------------------------------------------------------------------------- ------------------------------- DWC Configuration ------------------------------- ------------------------------------------------------------------------------ */ - -/** - * @brief Default FIFO sizes (see 2.1.2.4 for programming guide) - * - * RXFIFO - * - Recommended: ((LPS/4) * 2) + 2 - * - Actual: Whatever leftover size: USB_DWC_FIFO_TOTAL_USABLE_LINES(200) - 48 - 48 = 104 - * - Worst case can accommodate two packets of 204 bytes, or one packet of 408 - * NPTXFIFO - * - Recommended: (LPS/4) * 2 - * - Actual: Assume LPS is 64, and 3 packets: (64/4) * 3 = 48 - * - Worst case can accommodate three packets of 64 bytes or one packet of 192 - * PTXFIFO - * - Recommended: (LPS/4) * 2 - * - Actual: Assume LPS is 64, and 3 packets: (64/4) * 3 = 48 - * - Worst case can accommodate three packets of 64 bytes or one packet of 192 - */ -#define USB_DWC_FIFO_RX_LINES_DEFAULT 104 -#define USB_DWC_FIFO_NPTX_LINES_DEFAULT 48 -#define USB_DWC_FIFO_PTX_LINES_DEFAULT 48 - -/** - * @brief FIFO sizes that bias to giving RX FIFO more capacity - * - * RXFIFO - * - Recommended: ((LPS/4) * 2) + 2 - * - Actual: Whatever leftover size: USB_DWC_FIFO_TOTAL_USABLE_LINES(200) - 32 - 16 = 152 - * - Worst case can accommodate two packets of 300 bytes or one packet of 600 bytes - * NPTXFIFO - * - Recommended: (LPS/4) * 2 - * - Actual: Assume LPS is 64, and 1 packets: (64/4) * 1 = 16 - * - Worst case can accommodate one packet of 64 bytes - * PTXFIFO - * - Recommended: (LPS/4) * 2 - * - Actual: Assume LPS is 64, and 3 packets: (64/4) * 2 = 32 - * - Worst case can accommodate two packets of 64 bytes or one packet of 128 - */ -#define USB_DWC_FIFO_RX_LINES_BIASRX 152 -#define USB_DWC_FIFO_NPTX_LINES_BIASRX 16 -#define USB_DWC_FIFO_PTX_LINES_BIASRX 32 - -/** - * @brief FIFO sizes that bias to giving Periodic TX FIFO more capacity (i.e., ISOC OUT) - * - * RXFIFO - * - Recommended: ((LPS/4) * 2) + 2 - * - Actual: Assume LPS is 64, and 2 packets: ((64/4) * 2) + 2 = 34 - * - Worst case can accommodate two packets of 64 bytes or one packet of 128 - * NPTXFIFO - * - Recommended: (LPS/4) * 2 - * - Actual: Assume LPS is 64, and 1 packets: (64/4) * 1 = 16 - * - Worst case can accommodate one packet of 64 bytes - * PTXFIFO - * - Recommended: (LPS/4) * 2 - * - Actual: Whatever leftover size: USB_DWC_FIFO_TOTAL_USABLE_LINES(200) - 34 - 16 = 150 - * - Worst case can accommodate two packets of 300 bytes or one packet of 600 bytes - */ -#define USB_DWC_FIFO_RX_LINES_BIASTX 34 -#define USB_DWC_FIFO_NPTX_LINES_BIASTX 16 -#define USB_DWC_FIFO_PTX_LINES_BIASTX 150 /* ----------------------------------------------------------------------------- ------------------------------- Global Registers ------------------------------- diff --git a/components/hal/usb_dwc_hal.c b/components/hal/usb_dwc_hal.c index 5875d9e6fe..300fd6c263 100644 --- a/components/hal/usb_dwc_hal.c +++ b/components/hal/usb_dwc_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,40 +21,7 @@ #define BENDPOINTADDRESS_NUM_MSK 0x0F //Endpoint number mask of the bEndpointAddress field of an endpoint descriptor #define BENDPOINTADDRESS_DIR_MSK 0x80 //Endpoint direction mask of the bEndpointAddress field of an endpoint descriptor -#define CORE_REG_GSNPSID 0x4F54400A -#define CORE_REG_GHWCFG1 0x00000000 -#define CORE_REG_GHWCFG2 0x224DD930 -#define CORE_REG_GHWCFG3 0x00C804B5 -#define CORE_REG_GHWCFG4 0xD3F0A030 - -// ----------------------- Configs ------------------------- - -/** - * @brief Default FIFO sizes (see 2.1.2.4 for programming guide) - */ -const usb_dwc_hal_fifo_config_t fifo_config_default = { - .rx_fifo_lines = USB_DWC_FIFO_RX_LINES_DEFAULT, - .nptx_fifo_lines = USB_DWC_FIFO_NPTX_LINES_DEFAULT, - .ptx_fifo_lines = USB_DWC_FIFO_PTX_LINES_DEFAULT, -}; - -/** - * @brief FIFO sizes that bias to giving RX FIFO more capacity - */ -const usb_dwc_hal_fifo_config_t fifo_config_bias_rx = { - .rx_fifo_lines = USB_DWC_FIFO_RX_LINES_BIASRX, - .nptx_fifo_lines = USB_DWC_FIFO_NPTX_LINES_BIASRX, - .ptx_fifo_lines = USB_DWC_FIFO_PTX_LINES_BIASRX, -}; - -/** - * @brief FIFO sizes that bias to giving Periodic TX FIFO more capacity (i.e., ISOC OUT) - */ -const usb_dwc_hal_fifo_config_t fifo_config_bias_ptx = { - .rx_fifo_lines = USB_DWC_FIFO_RX_LINES_BIASTX, - .nptx_fifo_lines = USB_DWC_FIFO_NPTX_LINES_BIASTX, - .ptx_fifo_lines = USB_DWC_FIFO_PTX_LINES_BIASTX, -}; +#define CORE_REG_GSNPSID 0x4F54400A //Release number of USB_DWC used in Espressif's SoCs // -------------------- Configurable ----------------------- @@ -193,22 +160,49 @@ void usb_dwc_hal_core_soft_reset(usb_dwc_hal_context_t *hal) void usb_dwc_hal_set_fifo_bias(usb_dwc_hal_context_t *hal, const usb_hal_fifo_bias_t fifo_bias) { - const usb_dwc_hal_fifo_config_t *fifo_config; + /* + * EPINFO_CTL is located at the end of FIFO, its size is fixed in HW. + * The reserved size is always the worst-case, which is device mode that requires 4 locations per EP direction (including EP0). + * Here we just read the FIFO size from HW register, to avoid any ambivalence + */ + uint32_t ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4; + usb_dwc_ll_ghwcfg_get_hw_config(hal->dev, &ghwcfg1, &ghwcfg2, &ghwcfg3, &ghwcfg4); + const uint16_t fifo_size_lines = ((usb_dwc_ghwcfg3_reg_t)ghwcfg3).dfifodepth; + + /* + * Recommended FIFO sizes (see 2.1.2.4 for programming guide) + * + * RXFIFO: ((LPS/4) * 2) + 2 + * NPTXFIFO: (LPS/4) * 2 + * PTXFIFO: (LPS/4) * 2 + * + * Recommended sizes fit 2 packets of each type. For S2 and S3 we can't fit even one MPS ISOC packet (1023 FS and 1024 HS). + * So the calculations below are compromises between the available FIFO size and optimal performance. + */ + usb_dwc_hal_fifo_config_t fifo_config; switch (fifo_bias) { + // Define minimum viable (fits at least 1 MPS) FIFO sizes for non-biased FIFO types + // Allocate the remaining size to the biased FIFO type case USB_HAL_FIFO_BIAS_DEFAULT: - fifo_config = &fifo_config_default; + fifo_config.nptx_fifo_lines = OTG_DFIFO_DEPTH / 4; + fifo_config.ptx_fifo_lines = OTG_DFIFO_DEPTH / 8; + fifo_config.rx_fifo_lines = fifo_size_lines - fifo_config.ptx_fifo_lines - fifo_config.nptx_fifo_lines; break; case USB_HAL_FIFO_BIAS_RX: - fifo_config = &fifo_config_bias_rx; + fifo_config.nptx_fifo_lines = OTG_DFIFO_DEPTH / 16; + fifo_config.ptx_fifo_lines = OTG_DFIFO_DEPTH / 8; + fifo_config.rx_fifo_lines = fifo_size_lines - fifo_config.ptx_fifo_lines - fifo_config.nptx_fifo_lines; break; case USB_HAL_FIFO_BIAS_PTX: - fifo_config = &fifo_config_bias_ptx; + fifo_config.rx_fifo_lines = OTG_DFIFO_DEPTH / 8 + 2; // 2 extra lines are allocated for status information. See USB-OTG Programming Guide, chapter 2.1.2.1 + fifo_config.nptx_fifo_lines = OTG_DFIFO_DEPTH / 16; + fifo_config.ptx_fifo_lines = fifo_size_lines - fifo_config.nptx_fifo_lines - fifo_config.rx_fifo_lines; break; default: abort(); } - HAL_ASSERT((fifo_config->rx_fifo_lines + fifo_config->nptx_fifo_lines + fifo_config->ptx_fifo_lines) <= USB_DWC_FIFO_TOTAL_USABLE_LINES); + HAL_ASSERT((fifo_config.rx_fifo_lines + fifo_config.nptx_fifo_lines + fifo_config.ptx_fifo_lines) <= fifo_size_lines); //Check that none of the channels are active for (int i = 0; i < OTG_NUM_HOST_CHAN; i++) { if (hal->channels.hdls[i] != NULL) { @@ -216,14 +210,14 @@ void usb_dwc_hal_set_fifo_bias(usb_dwc_hal_context_t *hal, const usb_hal_fifo_bi } } //Set the new FIFO lengths - usb_dwc_ll_grxfsiz_set_fifo_size(hal->dev, fifo_config->rx_fifo_lines); - usb_dwc_ll_gnptxfsiz_set_fifo_size(hal->dev, fifo_config->rx_fifo_lines, fifo_config->nptx_fifo_lines); - usb_dwc_ll_hptxfsiz_set_ptx_fifo_size(hal->dev, fifo_config->rx_fifo_lines + fifo_config->nptx_fifo_lines, fifo_config->ptx_fifo_lines); + usb_dwc_ll_grxfsiz_set_fifo_size(hal->dev, fifo_config.rx_fifo_lines); + usb_dwc_ll_gnptxfsiz_set_fifo_size(hal->dev, fifo_config.rx_fifo_lines, fifo_config.nptx_fifo_lines); + usb_dwc_ll_hptxfsiz_set_ptx_fifo_size(hal->dev, fifo_config.rx_fifo_lines + fifo_config.nptx_fifo_lines, fifo_config.ptx_fifo_lines); //Flush the FIFOs usb_dwc_ll_grstctl_flush_nptx_fifo(hal->dev); usb_dwc_ll_grstctl_flush_ptx_fifo(hal->dev); usb_dwc_ll_grstctl_flush_rx_fifo(hal->dev); - hal->fifo_config = fifo_config; + hal->fifo_config = fifo_config; // Implicit struct copy hal->flags.fifo_sizes_set = 1; } @@ -232,7 +226,7 @@ void usb_dwc_hal_get_mps_limits(usb_dwc_hal_context_t *hal, usb_hal_fifo_mps_lim HAL_ASSERT(hal && mps_limits); HAL_ASSERT(hal->flags.fifo_sizes_set); - const usb_dwc_hal_fifo_config_t *fifo_config = hal->fifo_config; + const usb_dwc_hal_fifo_config_t *fifo_config = &(hal->fifo_config); mps_limits->in_mps = (fifo_config->rx_fifo_lines - 2) * 4; // Two lines are reserved for status quadlets internally by USB_DWC mps_limits->non_periodic_out_mps = fifo_config->nptx_fifo_lines * 4; mps_limits->periodic_out_mps = fifo_config->ptx_fifo_lines * 4;