fix(usb/host): Set SCHED_INFO for all channels

Although the hardware documentation suggests that SCHED_INFO is only used
for periodic channels, empirical evidence shows that omitting this configuration
on non-periodic channels can cause them to freeze.
Therefore, we set this field for all channels to ensure reliable operation.
This commit is contained in:
Tomas Rezucha 2025-02-04 11:02:29 +01:00
parent b26d933e08
commit 4e4c9dc726
4 changed files with 55 additions and 4 deletions

View File

@ -764,6 +764,23 @@ static inline void usb_dwc_ll_hcintmsk_set_intr_mask(volatile usb_dwc_host_chan_
// ---------------------------- HCTSIZi Register -------------------------------
static inline void usb_dwc_ll_hctsiz_init(volatile usb_dwc_host_chan_regs_t *chan)
{
usb_dwc_hctsiz_reg_t hctsiz;
hctsiz.val = chan->hctsiz_reg.val;
hctsiz.dopng = 0; // Don't do ping
hctsiz.pid = 0; // Set PID to DATA0
/*
* Set SCHED_INFO which occupies xfersize[7:0]
*
* Although the hardware documentation suggests that SCHED_INFO is only used for periodic channels,
* empirical evidence shows that omitting this configuration on non-periodic channels can cause them to freeze.
* Therefore, we set this field for all channels to ensure reliable operation.
*/
hctsiz.xfersize |= 0xFF;
chan->hctsiz_reg.val = hctsiz.val;
}
static inline void usb_dwc_ll_hctsiz_set_pid(volatile usb_dwc_host_chan_regs_t *chan, uint32_t data_pid)
{
if (data_pid == 0) {

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -763,6 +763,23 @@ static inline void usb_dwc_ll_hcintmsk_set_intr_mask(volatile usb_dwc_host_chan_
// ---------------------------- HCTSIZi Register -------------------------------
static inline void usb_dwc_ll_hctsiz_init(volatile usb_dwc_host_chan_regs_t *chan)
{
usb_dwc_hctsiz_reg_t hctsiz;
hctsiz.val = chan->hctsiz_reg.val;
hctsiz.dopng = 0; // Don't do ping
hctsiz.pid = 0; // Set PID to DATA0
/*
* Set SCHED_INFO which occupies xfersize[7:0]
*
* Although the hardware documentation suggests that SCHED_INFO is only used for periodic channels,
* empirical evidence shows that omitting this configuration on non-periodic channels can cause them to freeze.
* Therefore, we set this field for all channels to ensure reliable operation.
*/
hctsiz.xfersize |= 0xFF;
chan->hctsiz_reg.val = hctsiz.val;
}
static inline void usb_dwc_ll_hctsiz_set_pid(volatile usb_dwc_host_chan_regs_t *chan, uint32_t data_pid)
{
if (data_pid == 0) {

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -763,6 +763,23 @@ static inline void usb_dwc_ll_hcintmsk_set_intr_mask(volatile usb_dwc_host_chan_
// ---------------------------- HCTSIZi Register -------------------------------
static inline void usb_dwc_ll_hctsiz_init(volatile usb_dwc_host_chan_regs_t *chan)
{
usb_dwc_hctsiz_reg_t hctsiz;
hctsiz.val = chan->hctsiz_reg.val;
hctsiz.dopng = 0; // Don't do ping
hctsiz.pid = 0; // Set PID to DATA0
/*
* Set SCHED_INFO which occupies xfersize[7:0]
*
* Although the hardware documentation suggests that SCHED_INFO is only used for periodic channels,
* empirical evidence shows that omitting this configuration on non-periodic channels can cause them to freeze.
* Therefore, we set this field for all channels to ensure reliable operation.
*/
hctsiz.xfersize |= 0xFF;
chan->hctsiz_reg.val = hctsiz.val;
}
static inline void usb_dwc_ll_hctsiz_set_pid(volatile usb_dwc_host_chan_regs_t *chan, uint32_t data_pid)
{
if (data_pid == 0) {

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -311,7 +311,7 @@ bool usb_dwc_hal_chan_alloc(usb_dwc_hal_context_t *hal, usb_dwc_hal_chan_t *chan
usb_dwc_ll_hcint_read_and_clear_intrs(chan_obj->regs); //Clear the interrupt bits for that channel
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);
return true;
}