mirror of
https://github.com/espressif/esp-idf
synced 2025-03-10 01:29:21 -04:00
Merge branch 'refactor/cleanup_usb_phy_backport_v5.4' into 'release/v5.4'
fix(usb/host): Fix reaction on High-Speed NYET packet (backport v5.4) See merge request espressif/esp-idf!36119
This commit is contained in:
commit
cfc878a650
@ -790,23 +790,33 @@ static inline void usb_dwc_ll_hctsiz_set_qtd_list_len(volatile usb_dwc_host_chan
|
||||
chan->hctsiz_reg.val = hctsiz.val;
|
||||
}
|
||||
|
||||
static inline void usb_dwc_ll_hctsiz_init(volatile usb_dwc_host_chan_regs_t *chan)
|
||||
/**
|
||||
* @brief Perform PING protocol
|
||||
*
|
||||
* PING protocol is automatically enabled if High-Speed device responds with NYET in Scatter-Gather DMA mode.
|
||||
* The application must disable PING for next transfer.
|
||||
* Relevant only for OUT transfers.
|
||||
*
|
||||
* @param[in] chan Channel registers
|
||||
* @param[in] enable true: Enable PING, false: Disable PING
|
||||
*/
|
||||
static inline void usb_dwc_ll_hctsiz_set_dopng(volatile usb_dwc_host_chan_regs_t *chan, bool enable)
|
||||
{
|
||||
usb_dwc_hctsiz_reg_t hctsiz;
|
||||
hctsiz.val = chan->hctsiz_reg.val;
|
||||
hctsiz.dopng = 0; //Don't do ping
|
||||
/*
|
||||
Set SCHED_INFO which occupies xfersize[7:0]
|
||||
It is always set to 0xFF for full speed and not used in Bulk/Ctrl channels
|
||||
*/
|
||||
hctsiz.xfersize |= 0xFF;
|
||||
chan->hctsiz_reg.val = hctsiz.val;
|
||||
chan->hctsiz_reg.dopng = (uint32_t)(enable && !chan->hcchar_reg.epdir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set scheduling info for Periodic channel
|
||||
*
|
||||
* @attention This function must be called for each periodic channel!
|
||||
* @see USB-OTG databook: Table 5-47
|
||||
*
|
||||
* @param[in] chan Channel registers
|
||||
* @param[in] tokens_per_frame HS: Number of tokens per frame FS: Must be set 8
|
||||
* @param[in] offset Offset of the channel
|
||||
*/
|
||||
static inline void usb_dwc_ll_hctsiz_set_sched_info(volatile usb_dwc_host_chan_regs_t *chan, int tokens_per_frame, int offset)
|
||||
{
|
||||
// @see USB-OTG databook: Table 5-47
|
||||
// This function is relevant only for HS
|
||||
usb_dwc_hctsiz_reg_t hctsiz;
|
||||
hctsiz.val = chan->hctsiz_reg.val;
|
||||
uint8_t sched_info_val;
|
||||
|
@ -791,50 +791,33 @@ static inline void usb_dwc_ll_hctsiz_set_qtd_list_len(volatile usb_dwc_host_chan
|
||||
chan->hctsiz_reg.val = hctsiz.val;
|
||||
}
|
||||
|
||||
static inline void usb_dwc_ll_hctsiz_init(volatile usb_dwc_host_chan_regs_t *chan)
|
||||
/**
|
||||
* @brief Perform PING protocol
|
||||
*
|
||||
* @note This function is here only for compatibility reasons. PING is not relevant on FS only targets
|
||||
* @param[in] chan Channel registers
|
||||
* @param[in] enable true: Enable PING, false: Disable PING
|
||||
*/
|
||||
static inline void usb_dwc_ll_hctsiz_set_dopng(volatile usb_dwc_host_chan_regs_t *chan, bool enable)
|
||||
{
|
||||
usb_dwc_hctsiz_reg_t hctsiz;
|
||||
hctsiz.val = chan->hctsiz_reg.val;
|
||||
hctsiz.dopng = 0; //Don't do ping
|
||||
/*
|
||||
Set SCHED_INFO which occupies xfersize[7:0]
|
||||
It is always set to 0xFF for full speed and not used in Bulk/Ctrl channels
|
||||
*/
|
||||
hctsiz.xfersize |= 0xFF;
|
||||
chan->hctsiz_reg.val = hctsiz.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set scheduling info for Periodic channel
|
||||
*
|
||||
* @note ESP32-S2 is Full-Speed only, so SCHED_INFO is always set to 0xFF
|
||||
* @attention This function must be called for each periodic channel!
|
||||
* @see USB-OTG databook: Table 5-47
|
||||
*
|
||||
* @param[in] chan Channel registers
|
||||
* @param[in] tokens_per_frame Ignored
|
||||
* @param[in] offset Ignored
|
||||
*/
|
||||
static inline void usb_dwc_ll_hctsiz_set_sched_info(volatile usb_dwc_host_chan_regs_t *chan, int tokens_per_frame, int offset)
|
||||
{
|
||||
// @see USB-OTG databook: Table 5-47
|
||||
// This function is relevant only for HS
|
||||
usb_dwc_hctsiz_reg_t hctsiz;
|
||||
hctsiz.val = chan->hctsiz_reg.val;
|
||||
uint8_t sched_info_val;
|
||||
switch (tokens_per_frame) {
|
||||
case 1:
|
||||
offset %= 8; // If the required offset > 8, we must wrap around to SCHED_INFO size = 8
|
||||
sched_info_val = 0b00000001;
|
||||
break;
|
||||
case 2:
|
||||
offset %= 4;
|
||||
sched_info_val = 0b00010001;
|
||||
break;
|
||||
case 4:
|
||||
offset %= 2;
|
||||
sched_info_val = 0b01010101;
|
||||
break;
|
||||
case 8:
|
||||
offset = 0;
|
||||
sched_info_val = 0b11111111;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
sched_info_val <<= offset;
|
||||
hctsiz.xfersize &= ~(0xFF);
|
||||
hctsiz.xfersize |= sched_info_val;
|
||||
hctsiz.xfersize |= 0xFF;
|
||||
chan->hctsiz_reg.val = hctsiz.val;
|
||||
}
|
||||
|
||||
|
@ -791,50 +791,33 @@ static inline void usb_dwc_ll_hctsiz_set_qtd_list_len(volatile usb_dwc_host_chan
|
||||
chan->hctsiz_reg.val = hctsiz.val;
|
||||
}
|
||||
|
||||
static inline void usb_dwc_ll_hctsiz_init(volatile usb_dwc_host_chan_regs_t *chan)
|
||||
/**
|
||||
* @brief Perform PING protocol
|
||||
*
|
||||
* @note This function is here only for compatibility reasons. PING is not relevant on FS only targets
|
||||
* @param[in] chan Channel registers
|
||||
* @param[in] enable true: Enable PING, false: Disable PING
|
||||
*/
|
||||
static inline void usb_dwc_ll_hctsiz_set_dopng(volatile usb_dwc_host_chan_regs_t *chan, bool enable)
|
||||
{
|
||||
usb_dwc_hctsiz_reg_t hctsiz;
|
||||
hctsiz.val = chan->hctsiz_reg.val;
|
||||
hctsiz.dopng = 0; //Don't do ping
|
||||
/*
|
||||
Set SCHED_INFO which occupies xfersize[7:0]
|
||||
It is always set to 0xFF for full speed and not used in Bulk/Ctrl channels
|
||||
*/
|
||||
hctsiz.xfersize |= 0xFF;
|
||||
chan->hctsiz_reg.val = hctsiz.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set scheduling info for Periodic channel
|
||||
*
|
||||
* @note ESP32-S3 is Full-Speed only, so SCHED_INFO is always set to 0xFF
|
||||
* @attention This function must be called for each periodic channel!
|
||||
* @see USB-OTG databook: Table 5-47
|
||||
*
|
||||
* @param[in] chan Channel registers
|
||||
* @param[in] tokens_per_frame Ignored
|
||||
* @param[in] offset Ignored
|
||||
*/
|
||||
static inline void usb_dwc_ll_hctsiz_set_sched_info(volatile usb_dwc_host_chan_regs_t *chan, int tokens_per_frame, int offset)
|
||||
{
|
||||
// @see USB-OTG databook: Table 5-47
|
||||
// This function is relevant only for HS
|
||||
usb_dwc_hctsiz_reg_t hctsiz;
|
||||
hctsiz.val = chan->hctsiz_reg.val;
|
||||
uint8_t sched_info_val;
|
||||
switch (tokens_per_frame) {
|
||||
case 1:
|
||||
offset %= 8; // If the required offset > 8, we must wrap around to SCHED_INFO size = 8
|
||||
sched_info_val = 0b00000001;
|
||||
break;
|
||||
case 2:
|
||||
offset %= 4;
|
||||
sched_info_val = 0b00010001;
|
||||
break;
|
||||
case 4:
|
||||
offset %= 2;
|
||||
sched_info_val = 0b01010101;
|
||||
break;
|
||||
case 8:
|
||||
offset = 0;
|
||||
sched_info_val = 0b11111111;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
break;
|
||||
}
|
||||
sched_info_val <<= offset;
|
||||
hctsiz.xfersize &= ~(0xFF);
|
||||
hctsiz.xfersize |= sched_info_val;
|
||||
hctsiz.xfersize |= 0xFF;
|
||||
chan->hctsiz_reg.val = hctsiz.val;
|
||||
}
|
||||
|
||||
|
@ -312,7 +312,6 @@ bool usb_dwc_hal_chan_alloc(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan
|
||||
usb_dwc_ll_haintmsk_en_chan_intr(hal->dev, 1 << chan_obj->flags.chan_idx);
|
||||
usb_dwc_ll_hcintmsk_set_intr_mask(chan_obj->regs, CHAN_INTRS_EN_MSK); //Unmask interrupts for this channel
|
||||
usb_dwc_ll_hctsiz_set_pid(chan_obj->regs, 0); //Set the initial PID to zero
|
||||
usb_dwc_ll_hctsiz_init(chan_obj->regs); //Set the non changing parts of the HCTSIZ registers (e.g., do_ping and sched info)
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -383,8 +382,10 @@ void usb_dwc_hal_chan_set_ep_char(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t
|
||||
hal->periodic_frame_list[index] |= 1 << chan_obj->flags.chan_idx;
|
||||
}
|
||||
// For HS endpoints we must write to sched_info field of HCTSIZ register to schedule microframes
|
||||
// For FS endpoints sched_info is always 0xFF
|
||||
// LS endpoints do not support periodic transfers
|
||||
unsigned int tokens_per_frame = 0;
|
||||
if (ep_char->periodic.is_hs) {
|
||||
unsigned int tokens_per_frame;
|
||||
if (ep_char->periodic.interval >= 8) {
|
||||
tokens_per_frame = 1; // 1 token every 8 microframes
|
||||
} else if (ep_char->periodic.interval >= 4) {
|
||||
@ -394,8 +395,8 @@ void usb_dwc_hal_chan_set_ep_char(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t
|
||||
} else {
|
||||
tokens_per_frame = 8; // 1 token every microframe
|
||||
}
|
||||
usb_dwc_ll_hctsiz_set_sched_info(chan_obj->regs, tokens_per_frame, ep_char->periodic.offset);
|
||||
}
|
||||
usb_dwc_ll_hctsiz_set_sched_info(chan_obj->regs, tokens_per_frame, ep_char->periodic.offset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -403,12 +404,14 @@ void usb_dwc_hal_chan_set_ep_char(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t
|
||||
|
||||
void usb_dwc_hal_chan_activate(usb_dwc_hal_chan_t *chan_obj, void *xfer_desc_list, int desc_list_len, int start_idx)
|
||||
{
|
||||
//Cannot activate a channel that has already been enabled or is pending error handling
|
||||
// Cannot activate a channel that has already been enabled or is pending error handling
|
||||
HAL_ASSERT(!chan_obj->flags.active);
|
||||
//Set start address of the QTD list and starting QTD index
|
||||
// Make sure that PING is not enabled from previous transaction
|
||||
usb_dwc_ll_hctsiz_set_dopng(chan_obj->regs, false);
|
||||
// Set start address of the QTD list and starting QTD index
|
||||
usb_dwc_ll_hcdma_set_qtd_list_addr(chan_obj->regs, xfer_desc_list, start_idx);
|
||||
usb_dwc_ll_hctsiz_set_qtd_list_len(chan_obj->regs, desc_list_len);
|
||||
usb_dwc_ll_hcchar_enable_chan(chan_obj->regs); //Start the channel
|
||||
usb_dwc_ll_hcchar_enable_chan(chan_obj->regs); // Start the channel
|
||||
chan_obj->flags.active = 1;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user