Skip to content

Commit a9aa0e3

Browse files
committed
fix error on EHCI causes xfer error in non-queued qhd which cause memory fault
1 parent 1e998ce commit a9aa0e3

File tree

4 files changed

+37
-19
lines changed

4 files changed

+37
-19
lines changed

.idea/cmake.xml

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/dual/host_hid_to_device_cdc/src/tusb_config.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,6 @@
8484
#define CFG_TUH_RPI_PIO_USB 1
8585
#endif
8686

87-
88-
// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
89-
// #define CFG_TUSB_DEBUG 0
90-
9187
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
9288
* Tinyusb use follows macros to declare transferring memory so that they can be put
9389
* into those specific section.
@@ -133,7 +129,7 @@
133129
#endif
134130

135131
#ifndef CFG_TUH_MEM_ALIGN
136-
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
132+
#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
137133
#endif
138134

139135
#define CFG_TUH_HUB 1

src/portable/ehci/ehci.c

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,16 +93,30 @@ CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data;
9393
// Debug
9494
//--------------------------------------------------------------------+
9595
#if CFG_TUSB_DEBUG >= EHCI_DBG
96-
static inline void print_portsc(ehci_registers_t* regs)
97-
{
96+
static inline void print_portsc(ehci_registers_t* regs) {
9897
TU_LOG_HEX(EHCI_DBG, regs->portsc);
99-
TU_LOG(EHCI_DBG, " Current Connect Status: %u\r\n", regs->portsc_bm.current_connect_status);
100-
TU_LOG(EHCI_DBG, " Connect Status Change : %u\r\n", regs->portsc_bm.connect_status_change);
101-
TU_LOG(EHCI_DBG, " Port Enabled : %u\r\n", regs->portsc_bm.port_enabled);
102-
TU_LOG(EHCI_DBG, " Port Enabled Change : %u\r\n", regs->portsc_bm.port_enable_change);
103-
104-
TU_LOG(EHCI_DBG, " Port Reset : %u\r\n", regs->portsc_bm.port_reset);
105-
TU_LOG(EHCI_DBG, " Port Power : %u\r\n", regs->portsc_bm.port_power);
98+
TU_LOG(EHCI_DBG, " Connect Status : %u\r\n", regs->portsc_bm.current_connect_status);
99+
TU_LOG(EHCI_DBG, " Connect Change : %u\r\n", regs->portsc_bm.connect_status_change);
100+
TU_LOG(EHCI_DBG, " Enabled : %u\r\n", regs->portsc_bm.port_enabled);
101+
TU_LOG(EHCI_DBG, " Enabled Change : %u\r\n", regs->portsc_bm.port_enable_change);
102+
103+
TU_LOG(EHCI_DBG, " OverCurr Change: %u\r\n", regs->portsc_bm.over_current_change);
104+
TU_LOG(EHCI_DBG, " Force Resume : %u\r\n", regs->portsc_bm.force_port_resume);
105+
TU_LOG(EHCI_DBG, " Suspend : %u\r\n", regs->portsc_bm.suspend);
106+
TU_LOG(EHCI_DBG, " Reset : %u\r\n", regs->portsc_bm.port_reset);
107+
TU_LOG(EHCI_DBG, " Power : %u\r\n", regs->portsc_bm.port_power);
108+
}
109+
110+
static inline void print_intr(uint32_t intr) {
111+
TU_LOG_HEX(EHCI_DBG, intr);
112+
TU_LOG(EHCI_DBG, " USB Interrupt : %u\r\n", (intr & EHCI_INT_MASK_USB) ? 1 : 0);
113+
TU_LOG(EHCI_DBG, " USB Error : %u\r\n", (intr & EHCI_INT_MASK_ERROR) ? 1 : 0);
114+
TU_LOG(EHCI_DBG, " Port Change Detect : %u\r\n", (intr & EHCI_INT_MASK_PORT_CHANGE) ? 1 : 0);
115+
TU_LOG(EHCI_DBG, " Frame List Rollover: %u\r\n", (intr & EHCI_INT_MASK_FRAMELIST_ROLLOVER) ? 1 : 0);
116+
TU_LOG(EHCI_DBG, " Host System Error : %u\r\n", (intr & EHCI_INT_MASK_PCI_HOST_SYSTEM_ERROR) ? 1 : 0);
117+
TU_LOG(EHCI_DBG, " Async Advance : %u\r\n", (intr & EHCI_INT_MASK_ASYNC_ADVANCE) ? 1 : 0);
118+
// TU_LOG(EHCI_DBG, " Interrupt on Async: %u\r\n", (intr & EHCI_INT_MASK_NXP_ASYNC));
119+
// TU_LOG(EHCI_DBG, " Periodic Schedule : %u\r\n", (intr & EHCI_INT_MASK_NXP_PERIODIC));
106120
}
107121

108122
#else
@@ -166,8 +180,8 @@ void hcd_port_reset(uint8_t rhport)
166180

167181
ehci_registers_t* regs = ehci_data.regs;
168182

169-
// mask out all change bits since they are Write 1 to clear
170-
uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL;
183+
// mask out Write-1-to-Clear bits
184+
uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C;
171185

172186
// EHCI Table 2-16 PortSC
173187
// when software writes Port Reset bit to a one, it must also write a zero to the Port Enable bit.
@@ -347,7 +361,7 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg)
347361
// Power Control (PPC) field in the HCSPARAMS register.
348362
if (ehci_data.cap_regs->hcsparams_bm.port_power_control) {
349363
// mask out all change bits since they are Write 1 to clear
350-
uint32_t portsc = (regs->portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL);
364+
uint32_t portsc = (regs->portsc & ~EHCI_PORTSC_MASK_W1C);
351365
portsc |= ECHI_PORTSC_MASK_PORT_POWER;
352366

353367
regs->portsc = portsc;
@@ -621,9 +635,14 @@ static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
621635
p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes;
622636

623637
// if (XFER_RESULT_FAILED == xfer_result ) {
638+
// TU_LOG1(" QHD xfer err count: %d\n", qtd_overlay->err_count);
624639
// TU_BREAKPOINT(); // TODO skip unplugged device
640+
// while(1){}
625641
// }
626642

643+
// No TD, probably an signal noise ?
644+
TU_VERIFY(p_qhd->p_qtd_list_head, );
645+
627646
p_qhd->p_qtd_list_head->used = 0; // free QTD
628647
qtd_remove_1st_from_qhd(p_qhd);
629648

@@ -710,7 +729,8 @@ void hcd_int_handler(uint8_t rhport)
710729

711730
if (int_status & EHCI_INT_MASK_PORT_CHANGE)
712731
{
713-
uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_CHANGE_ALL;
732+
// Including: Force port resume, over-current change, enable/disable change and connect status change.
733+
uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_W1C;
714734
print_portsc(regs);
715735

716736
if (regs->portsc_bm.connect_status_change)

src/portable/ehci/ehci.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ enum {
306306
EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8),
307307
ECHI_PORTSC_MASK_PORT_POWER = TU_BIT(12),
308308

309-
EHCI_PORTSC_MASK_CHANGE_ALL =
309+
EHCI_PORTSC_MASK_W1C =
310310
EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE |
311311
EHCI_PORTSC_MASK_PORT_ENABLE_CHANGE |
312312
EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE

0 commit comments

Comments
 (0)