feat(hal/usb): Make USB-DWC HAL&LL configuration independent

Previously, we included symbols from soc/usb_dwc_cfg.h and configured
the HAL and LL according to it. Now we get the configuration in runtime
from USB-DWC registers.

Added missing definition for USB FS peripheral on ESP32-P4.
This commit is contained in:
Tomas Rezucha 2024-10-08 12:28:46 +02:00 committed by BOT
parent 1d5a8f6952
commit 177679b74e
13 changed files with 347 additions and 260 deletions

View File

@ -1,4 +1,4 @@
[codespell]
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/*
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,ot,wel,parms
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,ot,wel,parms,ehen
write-changes = true

View File

@ -9,7 +9,6 @@
#include <stdint.h>
#include <stdbool.h>
#include "soc/usb_dwc_struct.h"
#include "soc/usb_dwc_cfg.h"
#include "hal/usb_dwc_types.h"
#include "hal/misc.h"
@ -20,8 +19,7 @@ extern "C" {
/* ----------------------------- Helper Macros ------------------------------ */
// Get USB hardware instance
// TODO: extend this macros when we have support for both FS and HS hardware on P4
#define USB_DWC_LL_GET_HW(num) (&USB_DWC_HS)
#define USB_DWC_LL_GET_HW(num) (((num) == 1) ? &USB_DWC_FS : &USB_DWC_HS)
/* -----------------------------------------------------------------------------
--------------------------------- DWC Constants --------------------------------
@ -221,11 +219,9 @@ static inline void usb_dwc_ll_gusbcfg_set_timeout_cal(usb_dwc_dev_t *hw, uint8_t
static inline void usb_dwc_ll_gusbcfg_set_utmi_phy(usb_dwc_dev_t *hw)
{
#if (OTG_HSPHY_INTERFACE != 0)
hw->gusbcfg_reg.phyif = 1; // 16 bits interface
hw->gusbcfg_reg.ulpiutmisel = 0; // UTMI+
hw->gusbcfg_reg.physel = 0; // HS PHY
#endif // (OTG_HSPHY_INTERFACE != 0)
}
// --------------------------- GRSTCTL Register --------------------------------
@ -352,24 +348,19 @@ static inline uint32_t usb_dwc_ll_gsnpsid_get_id(usb_dwc_dev_t *hw)
// --------------------------- GHWCFGx Register --------------------------------
/**
* @brief Get the hardware configuration registers of the DWC_OTG controller
*
* The hardware configuration regitsers are read only and indicate the various
* features of the DWC_OTG core.
*
* @param hw Start address of the DWC_OTG registers
* @param[out] ghwcfg1 Hardware configuration registesr 1
* @param[out] ghwcfg2 Hardware configuration registesr 2
* @param[out] ghwcfg3 Hardware configuration registesr 3
* @param[out] ghwcfg4 Hardware configuration registesr 4
*/
static inline void usb_dwc_ll_ghwcfg_get_hw_config(usb_dwc_dev_t *hw, uint32_t *ghwcfg1, uint32_t *ghwcfg2, uint32_t *ghwcfg3, uint32_t *ghwcfg4)
static inline unsigned usb_dwc_ll_ghwcfg_get_fifo_depth(usb_dwc_dev_t *hw)
{
*ghwcfg1 = hw->ghwcfg1_reg.val;
*ghwcfg2 = hw->ghwcfg2_reg.val;
*ghwcfg3 = hw->ghwcfg3_reg.val;
*ghwcfg4 = hw->ghwcfg4_reg.val;
return hw->ghwcfg3_reg.dfifodepth;
}
static inline unsigned usb_dwc_ll_ghwcfg_get_hsphy_type(usb_dwc_dev_t *hw)
{
return hw->ghwcfg2_reg.hsphytype;
}
static inline unsigned usb_dwc_ll_ghwcfg_get_channel_num(usb_dwc_dev_t *hw)
{
return hw->ghwcfg2_reg.numhstchnl;
}
// --------------------------- HPTXFSIZ Register -------------------------------
@ -434,47 +425,44 @@ static inline void usb_dwc_ll_hcfg_set_fsls_supp_only(usb_dwc_dev_t *hw)
hw->hcfg_reg.fslssupp = 1;
}
static inline void usb_dwc_ll_hcfg_set_fsls_pclk_sel(usb_dwc_dev_t *hw)
{
hw->hcfg_reg.fslspclksel = 1;
}
/**
* @brief Sets some default values to HCFG to operate in Host mode with scatter/gather DMA
* @brief Set FSLS PHY clock
*
* @attention This function should only be called if FSLS PHY is selected
* @param[in] hw Start address of the DWC_OTG registers
* @param[in] speed Speed to initialize the host port at
*/
static inline void usb_dwc_ll_hcfg_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed)
static inline void usb_dwc_ll_hcfg_set_fsls_phy_clock(usb_dwc_dev_t *hw)
{
hw->hcfg_reg.descdma = 1; //Enable scatt/gatt
#if (OTG_HSPHY_INTERFACE == 0)
/*
Indicate to the OTG core what speed the PHY clock is at
Note: It seems like S2/S3 PHY has an implicit 8 divider applied when in LS mode,
Note: FSLS PHY has an implicit 8 divider applied when in LS mode,
so the values of FSLSPclkSel and FrInt have to be adjusted accordingly.
*/
hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2; //PHY clock on esp32-sx for FS/LS-only
#endif // (OTG_HSPHY_INTERFACE == 0)
hw->hcfg_reg.perschedena = 0; //Disable perio sched
usb_dwc_speed_t speed = (usb_dwc_speed_t)hw->hprt_reg.prtspd;
hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2;
}
// ----------------------------- HFIR Register ---------------------------------
static inline void usb_dwc_ll_hfir_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed)
/**
* @brief Set Frame Interval
*
* @attention This function should only be called if FSLS PHY is selected
* @param[in] hw Start address of the DWC_OTG registers
*/
static inline void usb_dwc_ll_hfir_set_frame_interval(usb_dwc_dev_t *hw)
{
#if (OTG_HSPHY_INTERFACE == 0)
usb_dwc_hfir_reg_t hfir;
hfir.val = hw->hfir_reg.val;
hfir.hfirrldctrl = 0; //Disable dynamic loading
hfir.hfirrldctrl = 0; // Disable dynamic loading
/*
Set frame interval to be equal to 1ms
Note: It seems like our PHY has an implicit 8 divider applied when in LS mode,
Note: FSLS PHY has an implicit 8 divider applied when in LS mode,
so the values of FSLSPclkSel and FrInt have to be adjusted accordingly.
*/
hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000; //esp32-sx targets only support FS or LS
usb_dwc_speed_t speed = (usb_dwc_speed_t)hw->hprt_reg.prtspd;
hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000;
hw->hfir_reg.val = hfir.val;
#endif // (OTG_HSPHY_INTERFACE == 0)
}
// ----------------------------- HFNUM Register --------------------------------

View File

@ -39,7 +39,7 @@ FORCE_INLINE_ATTR void usb_utmi_ll_configure_ls(usb_utmi_dev_t *hw, bool paralle
*
* @param[in] clk_en True to enable, false to disable
*/
FORCE_INLINE_ATTR void usb_utmi_ll_enable_bus_clock(bool clk_en)
FORCE_INLINE_ATTR void _usb_utmi_ll_enable_bus_clock(bool clk_en)
{
// Enable/disable system clock for USB_UTMI and USB_DWC_HS
HP_SYS_CLKRST.soc_clk_ctrl1.reg_usb_otg20_sys_clk_en = clk_en;
@ -48,7 +48,7 @@ FORCE_INLINE_ATTR void usb_utmi_ll_enable_bus_clock(bool clk_en)
}
// HP_SYS_CLKRST.soc_clk_ctrlx and LP_AON_CLKRST.hp_usb_clkrst_ctrlx are shared registers, so this function must be used in an atomic way
#define usb_utmi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; usb_utmi_ll_enable_bus_clock(__VA_ARGS__)
#define usb_utmi_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _usb_utmi_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset the USB UTMI PHY and USB_DWC_HS controller

View File

@ -220,11 +220,9 @@ static inline void usb_dwc_ll_gusbcfg_set_timeout_cal(usb_dwc_dev_t *hw, uint8_t
static inline void usb_dwc_ll_gusbcfg_set_utmi_phy(usb_dwc_dev_t *hw)
{
#if (OTG_HSPHY_INTERFACE != 0)
hw->gusbcfg_reg.phyif = 1; // 16 bits interface
hw->gusbcfg_reg.ulpiutmisel = 0; // UTMI+
hw->gusbcfg_reg.physel = 0; // HS PHY
#endif // (OTG_HSPHY_INTERFACE != 0)
}
// --------------------------- GRSTCTL Register --------------------------------
@ -351,24 +349,19 @@ static inline uint32_t usb_dwc_ll_gsnpsid_get_id(usb_dwc_dev_t *hw)
// --------------------------- GHWCFGx Register --------------------------------
/**
* @brief Get the hardware configuration registers of the DWC_OTG controller
*
* The hardware configuration regitsers are read only and indicate the various
* features of the DWC_OTG core.
*
* @param hw Start address of the DWC_OTG registers
* @param[out] ghwcfg1 Hardware configuration registesr 1
* @param[out] ghwcfg2 Hardware configuration registesr 2
* @param[out] ghwcfg3 Hardware configuration registesr 3
* @param[out] ghwcfg4 Hardware configuration registesr 4
*/
static inline void usb_dwc_ll_ghwcfg_get_hw_config(usb_dwc_dev_t *hw, uint32_t *ghwcfg1, uint32_t *ghwcfg2, uint32_t *ghwcfg3, uint32_t *ghwcfg4)
static inline unsigned usb_dwc_ll_ghwcfg_get_fifo_depth(usb_dwc_dev_t *hw)
{
*ghwcfg1 = hw->ghwcfg1_reg.val;
*ghwcfg2 = hw->ghwcfg2_reg.val;
*ghwcfg3 = hw->ghwcfg3_reg.val;
*ghwcfg4 = hw->ghwcfg4_reg.val;
return hw->ghwcfg3_reg.dfifodepth;
}
static inline unsigned usb_dwc_ll_ghwcfg_get_hsphy_type(usb_dwc_dev_t *hw)
{
return hw->ghwcfg2_reg.hsphytype;
}
static inline unsigned usb_dwc_ll_ghwcfg_get_channel_num(usb_dwc_dev_t *hw)
{
return hw->ghwcfg2_reg.numhstchnl;
}
// --------------------------- HPTXFSIZ Register -------------------------------
@ -433,47 +426,44 @@ static inline void usb_dwc_ll_hcfg_set_fsls_supp_only(usb_dwc_dev_t *hw)
hw->hcfg_reg.fslssupp = 1;
}
static inline void usb_dwc_ll_hcfg_set_fsls_pclk_sel(usb_dwc_dev_t *hw)
{
hw->hcfg_reg.fslspclksel = 1;
}
/**
* @brief Sets some default values to HCFG to operate in Host mode with scatter/gather DMA
* @brief Set FSLS PHY clock
*
* @attention This function should only be called if FSLS PHY is selected
* @param[in] hw Start address of the DWC_OTG registers
* @param[in] speed Speed to initialize the host port at
*/
static inline void usb_dwc_ll_hcfg_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed)
static inline void usb_dwc_ll_hcfg_set_fsls_phy_clock(usb_dwc_dev_t *hw)
{
hw->hcfg_reg.descdma = 1; //Enable scatt/gatt
#if (OTG_HSPHY_INTERFACE == 0)
/*
Indicate to the OTG core what speed the PHY clock is at
Note: It seems like S2/S3 PHY has an implicit 8 divider applied when in LS mode,
Note: FSLS PHY has an implicit 8 divider applied when in LS mode,
so the values of FSLSPclkSel and FrInt have to be adjusted accordingly.
*/
hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2; //PHY clock on esp32-sx for FS/LS-only
#endif // (OTG_HSPHY_INTERFACE == 0)
hw->hcfg_reg.perschedena = 0; //Disable perio sched
usb_dwc_speed_t speed = (usb_dwc_speed_t)hw->hprt_reg.prtspd;
hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2;
}
// ----------------------------- HFIR Register ---------------------------------
static inline void usb_dwc_ll_hfir_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed)
/**
* @brief Set Frame Interval
*
* @attention This function should only be called if FSLS PHY is selected
* @param[in] hw Start address of the DWC_OTG registers
*/
static inline void usb_dwc_ll_hfir_set_frame_interval(usb_dwc_dev_t *hw)
{
#if (OTG_HSPHY_INTERFACE == 0)
usb_dwc_hfir_reg_t hfir;
hfir.val = hw->hfir_reg.val;
hfir.hfirrldctrl = 0; //Disable dynamic loading
hfir.hfirrldctrl = 0; // Disable dynamic loading
/*
Set frame interval to be equal to 1ms
Note: It seems like our PHY has an implicit 8 divider applied when in LS mode,
Note: FSLS PHY has an implicit 8 divider applied when in LS mode,
so the values of FSLSPclkSel and FrInt have to be adjusted accordingly.
*/
hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000; //esp32-sx targets only support FS or LS
usb_dwc_speed_t speed = (usb_dwc_speed_t)hw->hprt_reg.prtspd;
hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000;
hw->hfir_reg.val = hfir.val;
#endif // (OTG_HSPHY_INTERFACE == 0)
}
// ----------------------------- HFNUM Register --------------------------------

View File

@ -220,11 +220,9 @@ static inline void usb_dwc_ll_gusbcfg_set_timeout_cal(usb_dwc_dev_t *hw, uint8_t
static inline void usb_dwc_ll_gusbcfg_set_utmi_phy(usb_dwc_dev_t *hw)
{
#if (OTG_HSPHY_INTERFACE != 0)
hw->gusbcfg_reg.phyif = 1; // 16 bits interface
hw->gusbcfg_reg.ulpiutmisel = 0; // UTMI+
hw->gusbcfg_reg.physel = 0; // HS PHY
#endif // (OTG_HSPHY_INTERFACE != 0)
}
// --------------------------- GRSTCTL Register --------------------------------
@ -351,24 +349,19 @@ static inline uint32_t usb_dwc_ll_gsnpsid_get_id(usb_dwc_dev_t *hw)
// --------------------------- GHWCFGx Register --------------------------------
/**
* @brief Get the hardware configuration registers of the DWC_OTG controller
*
* The hardware configuration regitsers are read only and indicate the various
* features of the DWC_OTG core.
*
* @param hw Start address of the DWC_OTG registers
* @param[out] ghwcfg1 Hardware configuration registesr 1
* @param[out] ghwcfg2 Hardware configuration registesr 2
* @param[out] ghwcfg3 Hardware configuration registesr 3
* @param[out] ghwcfg4 Hardware configuration registesr 4
*/
static inline void usb_dwc_ll_ghwcfg_get_hw_config(usb_dwc_dev_t *hw, uint32_t *ghwcfg1, uint32_t *ghwcfg2, uint32_t *ghwcfg3, uint32_t *ghwcfg4)
static inline unsigned usb_dwc_ll_ghwcfg_get_fifo_depth(usb_dwc_dev_t *hw)
{
*ghwcfg1 = hw->ghwcfg1_reg.val;
*ghwcfg2 = hw->ghwcfg2_reg.val;
*ghwcfg3 = hw->ghwcfg3_reg.val;
*ghwcfg4 = hw->ghwcfg4_reg.val;
return hw->ghwcfg3_reg.dfifodepth;
}
static inline unsigned usb_dwc_ll_ghwcfg_get_hsphy_type(usb_dwc_dev_t *hw)
{
return hw->ghwcfg2_reg.hsphytype;
}
static inline unsigned usb_dwc_ll_ghwcfg_get_channel_num(usb_dwc_dev_t *hw)
{
return hw->ghwcfg2_reg.numhstchnl;
}
// --------------------------- HPTXFSIZ Register -------------------------------
@ -433,47 +426,44 @@ static inline void usb_dwc_ll_hcfg_set_fsls_supp_only(usb_dwc_dev_t *hw)
hw->hcfg_reg.fslssupp = 1;
}
static inline void usb_dwc_ll_hcfg_set_fsls_pclk_sel(usb_dwc_dev_t *hw)
{
hw->hcfg_reg.fslspclksel = 1;
}
/**
* @brief Sets some default values to HCFG to operate in Host mode with scatter/gather DMA
* @brief Set FSLS PHY clock
*
* @attention This function should only be called if FSLS PHY is selected
* @param[in] hw Start address of the DWC_OTG registers
* @param[in] speed Speed to initialize the host port at
*/
static inline void usb_dwc_ll_hcfg_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed)
static inline void usb_dwc_ll_hcfg_set_fsls_phy_clock(usb_dwc_dev_t *hw)
{
hw->hcfg_reg.descdma = 1; //Enable scatt/gatt
#if (OTG_HSPHY_INTERFACE == 0)
/*
Indicate to the OTG core what speed the PHY clock is at
Note: It seems like S2/S3 PHY has an implicit 8 divider applied when in LS mode,
Note: FSLS PHY has an implicit 8 divider applied when in LS mode,
so the values of FSLSPclkSel and FrInt have to be adjusted accordingly.
*/
hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2; //PHY clock on esp32-sx for FS/LS-only
#endif // (OTG_HSPHY_INTERFACE == 0)
hw->hcfg_reg.perschedena = 0; //Disable perio sched
usb_dwc_speed_t speed = (usb_dwc_speed_t)hw->hprt_reg.prtspd;
hw->hcfg_reg.fslspclksel = (speed == USB_DWC_SPEED_FULL) ? 1 : 2;
}
// ----------------------------- HFIR Register ---------------------------------
static inline void usb_dwc_ll_hfir_set_defaults(usb_dwc_dev_t *hw, usb_dwc_speed_t speed)
/**
* @brief Set Frame Interval
*
* @attention This function should only be called if FSLS PHY is selected
* @param[in] hw Start address of the DWC_OTG registers
*/
static inline void usb_dwc_ll_hfir_set_frame_interval(usb_dwc_dev_t *hw)
{
#if (OTG_HSPHY_INTERFACE == 0)
usb_dwc_hfir_reg_t hfir;
hfir.val = hw->hfir_reg.val;
hfir.hfirrldctrl = 0; //Disable dynamic loading
hfir.hfirrldctrl = 0; // Disable dynamic loading
/*
Set frame interval to be equal to 1ms
Note: It seems like our PHY has an implicit 8 divider applied when in LS mode,
Note: FSLS PHY has an implicit 8 divider applied when in LS mode,
so the values of FSLSPclkSel and FrInt have to be adjusted accordingly.
*/
hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000; //esp32-sx targets only support FS or LS
usb_dwc_speed_t speed = (usb_dwc_speed_t)hw->hprt_reg.prtspd;
hfir.frint = (speed == USB_DWC_SPEED_FULL) ? 48000 : 6000;
hw->hfir_reg.val = hfir.val;
#endif // (OTG_HSPHY_INTERFACE == 0)
}
// ----------------------------- HFNUM Register --------------------------------

View File

@ -171,13 +171,23 @@ typedef struct {
* @brief HAL context structure
*/
typedef struct {
//Context
usb_dwc_dev_t *dev; /**< Pointer to base address of DWC_OTG 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 */
//FIFO related
usb_dwc_hal_fifo_config_t fifo_config; /**< FIFO sizes configuration */
// HW context
usb_dwc_dev_t *dev; /**< Pointer to base address of DWC_OTG 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 */
// FIFO related
usb_dwc_hal_fifo_config_t fifo_config; /**< FIFO sizes configuration */
// Configuration of the USB-DWC core. Read from read-only HW registers
struct {
unsigned chan_num_total; /**< Total number of channels for this configuration */
unsigned hsphy_type; /**< HS PHY type of this configuration */
unsigned fifo_size; /**< Total FIFO size [in lines] in this configuration */
} constant_config;
union {
struct {
uint32_t dbnc_lock_enabled: 1; /**< Debounce lock enabled */
@ -188,11 +198,12 @@ typedef struct {
};
uint32_t val;
} flags;
//Channel related
// Channel related
struct {
int num_allocd; /**< Number of channels currently allocated */
uint32_t chan_pend_intrs_msk; /**< Bit mask of channels with pending interrupts */
usb_dwc_hal_chan_t *hdls[OTG_NUM_HOST_CHAN]; /**< Handles of each channel. Set to NULL if channel has not been allocated */
int num_allocated; /**< Number of channels currently allocated */
uint32_t chan_pend_intrs_msk; /**< Bit mask of channels with pending interrupts */
usb_dwc_hal_chan_t **hdls; /**< Handles of each channel. Set to NULL if channel has not been allocated */
} channels;
} usb_dwc_hal_context_t;
@ -208,16 +219,20 @@ typedef struct {
* - Interrupt allocated but DISABLED (in case of an unknown interrupt state)
* Exit:
* - Checks to see if DWC_OTG is alive, and if HW version/config is correct
* - HAl context initialized
* - HAL context initialized
* - Read and save relevant USB-DWC configuration parameters
* - Sets default values to some global and OTG registers (GAHBCFG and GUSBCFG)
* - Umask global interrupt signal
* - Put DWC_OTG into host mode. Require 25ms delay before this takes effect.
* - State -> USB_DWC_HAL_PORT_STATE_OTG
* - Interrupts cleared. Users can now enable their ISR
*
* @param[inout] hal Context of the HAL layer
* @attention The user must allocate memory for channel handlers with
* `hal->channels.hdls = malloc(hal->constant_config.chan_num_total * sizeof(usb_dwc_hal_chan_t*))`
* @param[inout] hal Context of the HAL layer
* @param[in] port_id USB port ID
*/
void usb_dwc_hal_init(usb_dwc_hal_context_t *hal);
void usb_dwc_hal_init(usb_dwc_hal_context_t *hal, int port_id);
/**
* @brief Deinitialize the HAL context
@ -241,7 +256,7 @@ void usb_dwc_hal_deinit(usb_dwc_hal_context_t *hal);
*
* @note This has nothing to do with a USB bus reset. It simply resets the peripheral
*
* @param hal Context of the HAL layer
* @param[in] hal Context of the HAL layer
*/
void usb_dwc_hal_core_soft_reset(usb_dwc_hal_context_t *hal);

View File

@ -10,7 +10,6 @@
#include <stdlib.h> // For abort()
#include "sdkconfig.h"
#include "soc/chip_revision.h"
#include "soc/usb_dwc_cfg.h"
#include "soc/usb_dwc_periph.h"
#include "hal/usb_dwc_hal.h"
#include "hal/usb_dwc_ll.h"
@ -112,10 +111,8 @@ static void set_defaults(usb_dwc_hal_context_t *hal)
usb_dwc_ll_gusbcfg_dis_hnp_cap(hal->dev); //Disable HNP
usb_dwc_ll_gusbcfg_dis_srp_cap(hal->dev); //Disable SRP
// Check if this USB-DWC supports HS PHY, if yes, use it
uint32_t ghwcfg[4];
usb_dwc_ll_ghwcfg_get_hw_config(hal->dev, &ghwcfg[0], &ghwcfg[1], &ghwcfg[2], &ghwcfg[3]);
if (((usb_dwc_ghwcfg2_reg_t)ghwcfg[1]).hsphytype != 0) {
// If this USB-DWC supports HS PHY, use it
if (hal->constant_config.hsphy_type != 0) {
usb_dwc_ll_gusbcfg_set_timeout_cal(hal->dev, 5); // 5 PHY clocks for our HS PHY
usb_dwc_ll_gusbcfg_set_utmi_phy(hal->dev);
}
@ -128,16 +125,29 @@ static void set_defaults(usb_dwc_hal_context_t *hal)
usb_dwc_ll_gusbcfg_force_host_mode(hal->dev);
}
void usb_dwc_hal_init(usb_dwc_hal_context_t *hal)
void usb_dwc_hal_init(usb_dwc_hal_context_t *hal, int port_id)
{
//Check if a peripheral is alive by reading the core ID registers
usb_dwc_dev_t *dev = USB_DWC_LL_GET_HW(0);
// Check if a peripheral is alive by reading the core ID registers
HAL_ASSERT(port_id < SOC_USB_OTG_PERIPH_NUM);
usb_dwc_dev_t *dev = USB_DWC_LL_GET_HW(port_id);
uint32_t core_id = usb_dwc_ll_gsnpsid_get_id(dev);
HAL_ASSERT(core_id == CORE_REG_GSNPSID);
(void) core_id; //Suppress unused variable warning if asserts are disabled
//Initialize HAL context
// Initialize HAL context
memset(hal, 0, sizeof(usb_dwc_hal_context_t));
hal->dev = dev;
// Save constant configuration of this USB-DWC instance
/*
* 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
*/
hal->constant_config.fifo_size = usb_dwc_ll_ghwcfg_get_fifo_depth(dev);
hal->constant_config.hsphy_type = usb_dwc_ll_ghwcfg_get_hsphy_type(dev);
hal->constant_config.chan_num_total = usb_dwc_ll_ghwcfg_get_channel_num(dev);
set_defaults(hal);
}
@ -154,32 +164,31 @@ void usb_dwc_hal_core_soft_reset(usb_dwc_hal_context_t *hal)
{
usb_dwc_ll_grstctl_core_soft_reset(hal->dev);
while (usb_dwc_ll_grstctl_is_core_soft_reset_in_progress(hal->dev)) {
; //Wait until core reset is done
; // Wait until core reset is done
}
while (!usb_dwc_ll_grstctl_is_ahb_idle(hal->dev)) {
; //Wait until AHB Master bus is idle before doing any other operations
; // Wait until AHB Master bus is idle before doing any other operations
}
//Set the default bits
// Set the default bits in USB-DWC registers
set_defaults(hal);
//Clear all the flags and channels
// Clear all the flags and channels
hal->periodic_frame_list = NULL;
hal->flags.val = 0;
hal->channels.num_allocd = 0;
hal->channels.num_allocated = 0;
hal->channels.chan_pend_intrs_msk = 0;
memset(hal->channels.hdls, 0, sizeof(usb_dwc_hal_chan_t *) * OTG_NUM_HOST_CHAN);
if (hal->channels.hdls) {
for (int i = 0; i < hal->constant_config.chan_num_total; i++) {
hal->channels.hdls[i] = NULL;
}
}
}
void usb_dwc_hal_set_fifo_bias(usb_dwc_hal_context_t *hal, const usb_hal_fifo_bias_t fifo_bias)
{
/*
* 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;
HAL_ASSERT(hal->channels.hdls);
const uint16_t fifo_size_lines = hal->constant_config.fifo_size;
/*
* Recommended FIFO sizes (see 2.1.2.4 for programming guide)
*
@ -190,23 +199,28 @@ void usb_dwc_hal_set_fifo_bias(usb_dwc_hal_context_t *hal, const usb_hal_fifo_bi
* 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.
*/
// Information for maintainers: this calculation is here for backward compatibility
// It should be removed when we allow HAL users to configure the FIFO sizes IDF-9042
const int otg_dfifo_depth = hal->constant_config.hsphy_type ? 1024 : 256;
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.nptx_fifo_lines = OTG_DFIFO_DEPTH / 4;
fifo_config.ptx_fifo_lines = OTG_DFIFO_DEPTH / 8;
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.nptx_fifo_lines = OTG_DFIFO_DEPTH / 16;
fifo_config.ptx_fifo_lines = OTG_DFIFO_DEPTH / 8;
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.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.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:
@ -215,7 +229,7 @@ void usb_dwc_hal_set_fifo_bias(usb_dwc_hal_context_t *hal, const usb_hal_fifo_bi
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++) {
for (int i = 0; i < hal->constant_config.chan_num_total; i++) {
if (hal->channels.hdls[i] != NULL) {
HAL_ASSERT(!hal->channels.hdls[i]->flags.active);
}
@ -254,11 +268,15 @@ static inline void debounce_lock_enable(usb_dwc_hal_context_t *hal)
void usb_dwc_hal_port_enable(usb_dwc_hal_context_t *hal)
{
usb_dwc_speed_t speed = usb_dwc_ll_hprt_get_speed(hal->dev);
//Host Configuration
usb_dwc_ll_hcfg_set_defaults(hal->dev, speed);
//Configure HFIR
usb_dwc_ll_hfir_set_defaults(hal->dev, speed);
// Host Configuration
usb_dwc_ll_hcfg_en_scatt_gatt_dma(hal->dev); // Enable Scatther-Gather DMA mode
usb_dwc_ll_hcfg_dis_perio_sched(hal->dev); // Disable Periodic Scheduler (for now)
// Configure PHY clock: Only for USB-DWC with FSLS PHY
if (hal->constant_config.hsphy_type == 0) {
usb_dwc_ll_hcfg_set_fsls_phy_clock(hal->dev);
usb_dwc_ll_hfir_set_frame_interval(hal->dev);
}
}
// ----------------------------------------------------- Channel -------------------------------------------------------
@ -267,17 +285,18 @@ void usb_dwc_hal_port_enable(usb_dwc_hal_context_t *hal)
bool usb_dwc_hal_chan_alloc(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan_obj, void *chan_ctx)
{
HAL_ASSERT(hal->channels.hdls);
HAL_ASSERT(hal->flags.fifo_sizes_set); //FIFO sizes should be set before attempting to allocate a channel
//Attempt to allocate channel
if (hal->channels.num_allocd == OTG_NUM_HOST_CHAN) {
if (hal->channels.num_allocated == hal->constant_config.chan_num_total) {
return false; //Out of free channels
}
int chan_idx = -1;
for (int i = 0; i < OTG_NUM_HOST_CHAN; i++) {
for (int i = 0; i < hal->constant_config.chan_num_total; i++) {
if (hal->channels.hdls[i] == NULL) {
hal->channels.hdls[i] = chan_obj;
chan_idx = i;
hal->channels.num_allocd++;
hal->channels.num_allocated++;
break;
}
}
@ -299,6 +318,7 @@ bool usb_dwc_hal_chan_alloc(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan
void usb_dwc_hal_chan_free(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan_obj)
{
HAL_ASSERT(hal->channels.hdls);
if (chan_obj->type == USB_DWC_XFER_TYPE_INTR || chan_obj->type == USB_DWC_XFER_TYPE_ISOCHRONOUS) {
//Unschedule this channel
for (int i = 0; i < hal->frame_list_len; i++) {
@ -311,8 +331,8 @@ void usb_dwc_hal_chan_free(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan_
usb_dwc_ll_haintmsk_dis_chan_intr(hal->dev, 1 << chan_obj->flags.chan_idx);
//Deallocate channel
hal->channels.hdls[chan_obj->flags.chan_idx] = NULL;
hal->channels.num_allocd--;
HAL_ASSERT(hal->channels.num_allocd >= 0);
hal->channels.num_allocated--;
HAL_ASSERT(hal->channels.num_allocated >= 0);
}
// ---------------- Channel Configuration ------------------
@ -464,6 +484,7 @@ usb_dwc_hal_port_event_t usb_dwc_hal_decode_intr(usb_dwc_hal_context_t *hal)
usb_dwc_hal_chan_t *usb_dwc_hal_get_chan_pending_intr(usb_dwc_hal_context_t *hal)
{
HAL_ASSERT(hal->channels.hdls);
int chan_num = __builtin_ffs(hal->channels.chan_pend_intrs_msk);
if (chan_num) {
hal->channels.chan_pend_intrs_msk &= ~(1 << (chan_num - 1)); //Clear the pending bit for that channel

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -11,94 +11,170 @@ extern "C" {
#endif
/*
HS Instance:
Configuration Set ID: 11
*/
/* 3.1 Basic Config Parameters */
#define OTG_MODE 0
#define OTG_ARCHITECTURE 2
#define OTG_SINGLE_POINT 1
#define OTG_ENABLE_LPM 0
#define OTG_EN_DED_TX_FIFO 1
#define OTG_EN_DESC_DMA 1
#define OTG_MULTI_PROC_INTRPT 1
#define OTG20_MODE 0
#define OTG20_ARCHITECTURE 2
#define OTG20_SINGLE_POINT 1
#define OTG20_ENABLE_LPM 0
#define OTG20_EN_DED_TX_FIFO 1
#define OTG20_EN_DESC_DMA 1
#define OTG20_MULTI_PROC_INTRPT 1
/* 3.2 USB Physical Layer Interface Parameters */
#define OTG_HSPHY_INTERFACE 3
#define OTG_HSPHY_DWIDTH 2
#define OTG_FSPHY_INTERFACE 2
#define OTG_ENABLE_IC_USB 0
#define OTG_ENABLE_HSIC 0
#define OTG_I2C_INTERFACE 0
#define OTG_ULPI_CARKIT 1
#define OTG_ADP_SUPPORT 1
#define OTG_BC_SUPPORT 0
#define OTG_VENDOR_CTL_INTERFACE 1
#define OTG20_HSPHY_INTERFACE 3
#define OTG20_HSPHY_DWIDTH 2
#define OTG20_FSPHY_INTERFACE 2
#define OTG20_ENABLE_IC_USB 0
#define OTG20_ENABLE_HSIC 0
#define OTG20_I2C_INTERFACE 0
#define OTG20_ULPI_CARKIT 1
#define OTG20_ADP_SUPPORT 1
#define OTG20_BC_SUPPORT 0
#define OTG20_VENDOR_CTL_INTERFACE 1
/* 3.3 Device Endpoint Configuration Parameters */
#define OTG_NUM_EPS 15
#define OTG_NUM_IN_EPS 8
#define OTG_NUM_CRL_EPS 1
#define OTG20_NUM_EPS 15
#define OTG20_NUM_IN_EPS 8
#define OTG20_NUM_CRL_EPS 1
/* 3.4 Host Endpoint Configuration Parameters */
#define OTG_NUM_HOST_CHAN 16
#define OTG_EN_PERIO_HOST 1
#define OTG20_NUM_HOST_CHAN 16
#define OTG20_EN_PERIO_HOST 1
/* 3.5 Endpoint Channel FIFO Configuration Parameters */
#define OTG_DFIFO_DEPTH 1024
#define OTG_DFIFO_DYNAMIC 1
#define OTG_RX_DFIFO_DEPTH 1024
#define OTG_TX_HNPERIO_DFIFO_DEPTH 1024
#define OTG_TX_HPERIO_DFIFO_DEPTH 1024
#define OTG_NPERIO_TX_QUEUE_DEPTH 4
#define OTG_PERIO_TX_QUEUE_DEPTH 4
#define OTG20_DFIFO_DEPTH 1024
#define OTG20_DFIFO_DYNAMIC 1
#define OTG20_RX_DFIFO_DEPTH 1024
#define OTG20_TX_HNPERIO_DFIFO_DEPTH 1024
#define OTG20_TX_HPERIO_DFIFO_DEPTH 1024
#define OTG20_NPERIO_TX_QUEUE_DEPTH 4
#define OTG20_PERIO_TX_QUEUE_DEPTH 4
/* 3.6 Additional Configuration Options Parameters */
#define OTG_TRANS_COUNT_WIDTH 17
#define OTG_PACKET_COUNT_WIDTH 8
#define OTG_RM_OPT_FEATURES 1
#define OTG_EN_PWROPT 1
#define OTG_SYNC_RESET_TYPE 0
#define OTG_EN_IDDIG_FILTER 1
#define OTG_EN_VBUSVALID_FILTER 1
#define OTG_EN_A_VALID_FILTER 1
#define OTG_EN_B_VALID_FILTER 1
#define OTG_EN_SESSIONEND_FILTER 1
#define OTG_EXCP_CNTL_XFER_FLOW 1
#define OTG_PWR_CLAMP 0
#define OTG_PWR_SWITCH_POLARITY 0
#define OTG20_TRANS_COUNT_WIDTH 17
#define OTG20_PACKET_COUNT_WIDTH 8
#define OTG20_RM_OPT_FEATURES 1
#define OTG20_EN_PWROPT 1
#define OTG20_SYNC_RESET_TYPE 0
#define OTG20_EN_IDDIG_FILTER 1
#define OTG20_EN_VBUSVALID_FILTER 1
#define OTG20_EN_A_VALID_FILTER 1
#define OTG20_EN_B_VALID_FILTER 1
#define OTG20_EN_SESSIONEND_FILTER 1
#define OTG20_EXCP_CNTL_XFER_FLOW 1
#define OTG20_PWR_CLAMP 0
#define OTG20_PWR_SWITCH_POLARITY 0
/* 3.7 Endpoint Direction Parameters */
#define OTG_EP_DIR_1 0
#define OTG_EP_DIR_2 0
#define OTG_EP_DIR_3 0
#define OTG_EP_DIR_4 0
#define OTG_EP_DIR_5 0
#define OTG_EP_DIR_6 0
#define OTG_EP_DIR_7 0
#define OTG_EP_DIR_8 0
#define OTG_EP_DIR_9 0
#define OTG_EP_DIR_10 0
#define OTG_EP_DIR_11 0
#define OTG_EP_DIR_12 0
#define OTG_EP_DIR_13 0
#define OTG_EP_DIR_14 0
#define OTG_EP_DIR_15 0
#define OTG20_EP_DIR_1 0
#define OTG20_EP_DIR_2 0
#define OTG20_EP_DIR_3 0
#define OTG20_EP_DIR_4 0
#define OTG20_EP_DIR_5 0
#define OTG20_EP_DIR_6 0
#define OTG20_EP_DIR_7 0
#define OTG20_EP_DIR_8 0
#define OTG20_EP_DIR_9 0
#define OTG20_EP_DIR_10 0
#define OTG20_EP_DIR_11 0
#define OTG20_EP_DIR_12 0
#define OTG20_EP_DIR_13 0
#define OTG20_EP_DIR_14 0
#define OTG20_EP_DIR_15 0
/* 3.8 Device Periodic FIFO Depth Parameters */
/* 3.9 Device IN Endpoint FIFO Depth Parameters */
#define OTG_TX_DINEP_DFIFO_DEPTH_0 512
#define OTG_TX_DINEP_DFIFO_DEPTH_1 512
#define OTG_TX_DINEP_DFIFO_DEPTH_2 512
#define OTG_TX_DINEP_DFIFO_DEPTH_3 512
#define OTG_TX_DINEP_DFIFO_DEPTH_4 512
#define OTG_TX_DINEP_DFIFO_DEPTH_5 512
#define OTG_TX_DINEP_DFIFO_DEPTH_6 512
#define OTG_TX_DINEP_DFIFO_DEPTH_7 512
#define OTG20_TX_DINEP_DFIFO_DEPTH_0 512
#define OTG20_TX_DINEP_DFIFO_DEPTH_1 512
#define OTG20_TX_DINEP_DFIFO_DEPTH_2 512
#define OTG20_TX_DINEP_DFIFO_DEPTH_3 512
#define OTG20_TX_DINEP_DFIFO_DEPTH_4 512
#define OTG20_TX_DINEP_DFIFO_DEPTH_5 512
#define OTG20_TX_DINEP_DFIFO_DEPTH_6 512
#define OTG20_TX_DINEP_DFIFO_DEPTH_7 512
/* 3.10 UTMI-To-UTMI Bridge Component Parameters */
#define DWC_U2UB_EN 0
#define OTG20_U2UB_EN 0
/*
FS Instance:
Configuration Set ID: 1
*/
/* 3.1 Basic Config Parameters */
#define OTG11_MODE 0
#define OTG11_ARCHITECTURE 2
#define OTG11_SINGLE_POINT 1
#define OTG11_ENABLE_LPM 0
#define OTG11_EN_DED_TX_FIFO 1
#define OTG11_EN_DESC_DMA 1
#define OTG11_MULTI_PROC_INTRPT 0
/* 3.2 USB Physical Layer Interface Parameters */
#define OTG11_HSPHY_INTERFACE 0
#define OTG11_FSPHY_INTERFACE 1
#define OTG11_ENABLE_IC_USB 0
#define OTG11_I2C_INTERFACE 0
#define OTG11_ADP_SUPPORT 0
#define OTG11_BC_SUPPORT 0
/* 3.3 Device Endpoint Configuration Parameters */
#define OTG11_NUM_EPS 6
#define OTG11_NUM_IN_EPS 5
#define OTG11_NUM_CRL_EPS 0
/* 3.4 Host Endpoint Configuration Parameters */
#define OTG11_NUM_HOST_CHAN 8
#define OTG11_EN_PERIO_HOST 1
/* 3.5 Endpoint Channel FIFO Configuration Parameters */
#define OTG11_DFIFO_DEPTH 256
#define OTG11_DFIFO_DYNAMIC 1
#define OTG11_RX_DFIFO_DEPTH 256
#define OTG11_TX_HNPERIO_DFIFO_DEPTH 256
#define OTG11_TX_NPERIO_DFIFO_DEPTH 256
#define OTG11_TX_HPERIO_DFIFO_DEPTH 256
#define OTG11_NPERIO_TX_QUEUE_DEPTH 4
#define OTG11_PERIO_TX_QUEUE_DEPTH 8
/* 3.6 Additional Configuration Options Parameters */
#define OTG11_TRANS_COUNT_WIDTH 16
#define OTG11_PACKET_COUNT_WIDTH 7
#define OTG11_RM_OPT_FEATURES 1
#define OTG11_EN_PWROPT 1
#define OTG11_SYNC_RESET_TYPE 0
#define OTG11_EN_IDDIG_FILTER 1
#define OTG11_EN_VBUSVALID_FILTER 1
#define OTG11_EN_A_VALID_FILTER 1
#define OTG11_EN_B_VALID_FILTER 1
#define OTG11_EN_SESSIONEND_FILTER 1
#define OTG11_EXCP_CNTL_XFER_FLOW 1
#define OTG11_PWR_CLAMP 0
#define OTG11_PWR_SWITCH_POLARITY 0
/* 3.7 Endpoint Direction Parameters */
#define OTG11_EP_DIR_1 0
#define OTG11_EP_DIR_2 0
#define OTG11_EP_DIR_3 0
#define OTG11_EP_DIR_4 0
#define OTG11_EP_DIR_5 0
#define OTG11_EP_DIR_6 0
/* 3.8 Device Periodic FIFO Depth Parameters */
/* 3.9 Device IN Endpoint FIFO Depth Parameters */
#define OTG11_TX_DINEP_DFIFO_DEPTH_1 256
#define OTG11_TX_DINEP_DFIFO_DEPTH_2 256
#define OTG11_TX_DINEP_DFIFO_DEPTH_3 256
#define OTG11_TX_DINEP_DFIFO_DEPTH_4 256
/* 3.10 UTMI-To-UTMI Bridge Component Parameters */
#define OTG11_U2UB_EN 0
#ifdef __cplusplus
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -13,7 +13,10 @@ extern "C" {
#endif
/*
Registers and fields were generated based on a set of configuration options.
Registers and fields were generated based on a set of USB-DWC configuration options.
ESP32-P4 contains 2 instances of USB-DWC with different configurations, the structure below corresponds to the HS instance.
The FS instance contains a subset of registers from HS instance, the user (HAL) is responsible for accessing only existing fields.
See ESP32-P4 "usb_dwc_cfg.h" for more details.
*/
@ -1368,6 +1371,7 @@ _Static_assert(sizeof(usb_dwc_dev_t) == 0xe08, "Invalid size of usb_dwc_dev_t st
#endif
extern usb_dwc_dev_t USB_DWC_HS;
extern usb_dwc_dev_t USB_DWC_FS;
#ifdef __cplusplus
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -88,7 +88,7 @@ typedef union {
struct {
uint32_t toutcal: 3;
uint32_t phyif: 1;
uint32_t reserved_4: 1;
uint32_t ulpiutmisel: 1;
uint32_t fsintf: 1;
uint32_t physel: 1;
uint32_t reserved_7: 1;

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -88,7 +88,7 @@ typedef union {
struct {
uint32_t toutcal: 3;
uint32_t phyif: 1;
uint32_t reserved_4: 1;
uint32_t ulpiutmisel: 1;
uint32_t fsintf: 1;
uint32_t physel: 1;
uint32_t reserved_7: 1;

View File

@ -1274,7 +1274,9 @@ esp_err_t hcd_port_init(int port_number, const hcd_port_config_t *port_config, h
port_obj->callback = port_config->callback;
port_obj->callback_arg = port_config->callback_arg;
port_obj->context = port_config->context;
usb_dwc_hal_init(port_obj->hal);
usb_dwc_hal_init(port_obj->hal, 0);
port_obj->hal->channels.hdls = calloc(port_obj->hal->constant_config.chan_num_total, sizeof(usb_dwc_hal_chan_t*));
HCD_CHECK_FROM_CRIT(port_obj->hal->channels.hdls != NULL, ESP_ERR_NO_MEM);
port_obj->initialized = true;
// Clear the frame list. We set the frame list register and enable periodic scheduling after a successful reset
memset(port_obj->frame_list, 0, FRAME_LIST_LEN * sizeof(uint32_t));
@ -1298,6 +1300,7 @@ esp_err_t hcd_port_deinit(hcd_port_handle_t port_hdl)
ESP_ERR_INVALID_STATE);
port->initialized = false;
esp_intr_disable(s_hcd_obj->isr_hdl);
free(port->hal->channels.hdls);
usb_dwc_hal_deinit(port->hal);
HCD_EXIT_CRITICAL();
@ -1410,14 +1413,14 @@ esp_err_t hcd_port_recover(hcd_port_handle_t port_hdl)
&& port->num_pipes_idle == 0 && port->num_pipes_queued == 0
&& port->flags.val == 0 && port->task_waiting_port_notif == NULL,
ESP_ERR_INVALID_STATE);
// We are about to do a soft reset on the peripheral. Disable the peripheral throughout
esp_intr_disable(s_hcd_obj->isr_hdl);
usb_dwc_hal_core_soft_reset(port->hal);
port->state = HCD_PORT_STATE_NOT_POWERED;
port->last_event = HCD_PORT_EVENT_NONE;
port->flags.val = 0;
// Soft reset wipes all registers so we need to reinitialize the HAL
usb_dwc_hal_init(port->hal);
// Clear the frame list. We set the frame list register and enable periodic scheduling after a successful reset
memset(port->frame_list, 0, FRAME_LIST_LEN * sizeof(uint32_t));
esp_intr_enable(s_hcd_obj->isr_hdl);

View File

@ -6,7 +6,7 @@
#include <stdio.h>
#include <string.h>
#include "soc/usb_dwc_cfg.h"
#include "hal/usb_dwc_ll.h" // For USB-DWC configuration
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "unity.h"
@ -17,7 +17,7 @@
#define NUM_URBS 3
#define NUM_PACKETS_PER_URB 3
#define POST_ENQUEUE_DELAY_US 20
#define ENQUEUE_DELAY (OTG_HSPHY_INTERFACE ? 100 : 500) // With this delay we want to enqueue the URBs at different times
#define ENQUEUE_DELAY (usb_dwc_ll_ghwcfg_get_hsphy_type(USB_DWC_LL_GET_HW(0)) ? 100 : 500) // With this delay we want to enqueue the URBs at different times
/*
Test HCD ISOC pipe URBs
@ -126,12 +126,12 @@ TEST_CASE("Test HCD isochronous pipe URBs all", "[isoc][full_speed][high_speed]"
uint8_t dev_addr = test_hcd_enum_device(default_pipe);
urb_t *urb_list[NUM_URBS];
hcd_pipe_handle_t unused_pipes[OTG_NUM_HOST_CHAN];
hcd_pipe_handle_t unused_pipes[16];
const usb_ep_desc_t *out_ep_desc = dev_isoc_get_out_ep_desc(port_speed);
const int isoc_packet_size = USB_EP_DESC_GET_MPS(out_ep_desc);
// For all channels
for (int channel = 0; channel < OTG_NUM_HOST_CHAN - 1; channel++) {
// For all channels (except channel allocated for EP0)
for (int channel = 0; channel < usb_dwc_ll_ghwcfg_get_channel_num(USB_DWC_LL_GET_HW(0)) - 1; channel++) {
// Allocate unused pipes, so the active isoc_out_pipe uses different channel index
for (int ch = 0; ch < channel; ch++) {
unused_pipes[ch] = test_hcd_pipe_alloc(port_hdl, out_ep_desc, dev_addr + 1, port_speed);