Skip to content

Commit 77f0726

Browse files
committed
fix ehci issue with portsc when enable port power and port reset
fix attached device not regconized if attached before power on
1 parent 04c7590 commit 77f0726

File tree

5 files changed

+171
-81
lines changed

5 files changed

+171
-81
lines changed

.idea/runConfigurations/rt1060_redlink.xml

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

hw/bsp/imxrt/boards/mimxrt1060_evk/board.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ set(MCU_VARIANT MIMXRT1062)
22

33
set(JLINK_DEVICE MIMXRT1062xxx6A)
44
set(PYOCD_TARGET mimxrt1060)
5+
set(NXPLS_DEVICE MIMXRT1062xxxxA:EVK-MIMXRT1060)
56

67
function(update_board TARGET)
78
target_sources(${TARGET} PUBLIC

hw/bsp/imxrt/family.cmake

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,26 @@ function(family_configure_target TARGET)
121121
# Link dependencies
122122
target_link_libraries(${TARGET} PUBLIC ${BOARD_TARGET} ${TARGET}-tinyusb)
123123

124-
# Flash Target
124+
# group target (not yet supported by clion)
125+
set_target_properties(${TARGET}-tinyusb ${TARGET}-tinyusb_config
126+
PROPERTIES FOLDER ${TARGET}_sub
127+
)
128+
129+
#---------- Flash ----------
130+
# Flash using pyocd
125131
add_custom_target(${TARGET}-pyocd
126132
COMMAND pyocd flash -t ${PYOCD_TARGET} $<TARGET_FILE:${TARGET}>
127133
)
128134

129-
# group target
130-
set_target_properties(${TARGET}-tinyusb ${TARGET}-tinyusb_config
131-
PROPERTIES FOLDER ${TARGET}_sub
135+
# Flash using NXP LinkServer (redlink)
136+
# https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/linkserver-for-microcontrollers:LINKERSERVER
137+
# LinkServer has a bug that can only execute with full path otherwise it throws:
138+
# realpath error: No such file or directory
139+
execute_process(COMMAND which LinkServer OUTPUT_VARIABLE LINKSERVER_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
140+
add_custom_target(${TARGET}-redlink
141+
COMMAND ${LINKSERVER_PATH} flash ${NXPLS_DEVICE} load $<TARGET_FILE:${TARGET}>
132142
)
143+
133144
endfunction()
134145

135146

src/portable/ehci/ehci.c

Lines changed: 56 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,35 @@ typedef struct
7979
ehci_qhd_t qhd_pool[QHD_MAX];
8080
ehci_qtd_t qtd_pool[QTD_MAX] TU_ATTR_ALIGNED(32);
8181

82-
ehci_registers_t* regs;
82+
ehci_registers_t* regs; // operational register
83+
ehci_cap_registers_t* cap_regs; // capability register
8384

8485
volatile uint32_t uframe_number;
8586
}ehci_data_t;
8687

8788
// Periodic frame list must be 4K alignment
8889
CFG_TUH_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data;
8990

91+
//--------------------------------------------------------------------+
92+
// Debug
93+
//--------------------------------------------------------------------+
94+
#if CFG_TUSB_DEBUG >= EHCI_DBG
95+
static inline void print_portsc(ehci_registers_t* regs)
96+
{
97+
TU_LOG_HEX(EHCI_DBG, regs->portsc);
98+
TU_LOG(EHCI_DBG, " Current Connect Status: %u\r\n", regs->portsc_bm.current_connect_status);
99+
TU_LOG(EHCI_DBG, " Connect Status Change : %u\r\n", regs->portsc_bm.connect_status_change);
100+
TU_LOG(EHCI_DBG, " Port Enabled : %u\r\n", regs->portsc_bm.port_enabled);
101+
TU_LOG(EHCI_DBG, " Port Enabled Change : %u\r\n", regs->portsc_bm.port_enable_change);
102+
103+
TU_LOG(EHCI_DBG, " Port Reset : %u\r\n", regs->portsc_bm.port_reset);
104+
TU_LOG(EHCI_DBG, " Port Power : %u\r\n", regs->portsc_bm.port_power);
105+
}
106+
107+
#else
108+
#define print_portsc(_reg)
109+
#endif
110+
90111
//--------------------------------------------------------------------+
91112
// PROTOTYPE
92113
//--------------------------------------------------------------------+
@@ -152,11 +173,11 @@ void hcd_port_reset(uint8_t rhport)
152173

153174
ehci_registers_t* regs = ehci_data.regs;
154175

155-
// regs->portsc_bm.port_enabled = 0; // disable port before reset
156-
// regs->portsc_bm.port_reset = 1;
157-
158-
uint32_t portsc = regs->portsc;
176+
// mask out all change bits since they are Write 1 to clear
177+
uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL;
159178

179+
// EHCI Table 2-16 PortSC
180+
// when software writes Port Reset bit to a one, it must also write a zero to the Port Enable bit.
160181
portsc &= ~(EHCI_PORTSC_MASK_PORT_EANBLED);
161182
portsc |= EHCI_PORTSC_MASK_PORT_RESET;
162183

@@ -167,9 +188,14 @@ void hcd_port_reset_end(uint8_t rhport)
167188
{
168189
(void) rhport;
169190

170-
#if 0
191+
#if 0 // TODO check if this is necessary
171192
ehci_registers_t* regs = ehci_data.regs;
172-
regs->portsc_bm.port_reset = 0;
193+
194+
// mask out all change bits since they are Write 1 to clear
195+
uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL;
196+
portsc &= ~(EHCI_PORTSC_MASK_PORT_RESET);
197+
198+
regs->portsc = portsc;
173199
#endif
174200
}
175201

@@ -240,19 +266,26 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
240266

241267
bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg)
242268
{
243-
(void) capability_reg; // not used yet
244-
245269
tu_memclr(&ehci_data, sizeof(ehci_data_t));
246270

247-
ehci_data.regs = (ehci_registers_t* ) operatial_reg;
271+
ehci_data.regs = (ehci_registers_t*) operatial_reg;
272+
ehci_data.cap_regs = (ehci_cap_registers_t*) capability_reg;
248273

249274
ehci_registers_t* regs = ehci_data.regs;
250275

276+
// EHCI 4.1 Host Controller Initialization
277+
251278
//------------- CTRLDSSEGMENT Register (skip) -------------//
279+
252280
//------------- USB INT Register -------------//
253-
regs->inten = 0; // 1. disable all the interrupt
254-
regs->status = EHCI_INT_MASK_ALL; // 2. clear all status
255281

282+
// disable all the interrupt
283+
regs->inten = 0;
284+
285+
// clear all status except port change since device maybe connected before this driver is initialized
286+
regs->status = (EHCI_INT_MASK_ALL & ~EHCI_INT_MASK_PORT_CHANGE);
287+
288+
// Enable interrupts
256289
regs->inten = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE | EHCI_INT_MASK_ASYNC_ADVANCE |
257290
EHCI_INT_MASK_NXP_PERIODIC | EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_FRAMELIST_ROLLOVER;
258291

@@ -316,7 +349,16 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg)
316349
FRAMELIST_SIZE_USBCMD_VALUE;
317350

318351
//------------- ConfigFlag Register (skip) -------------//
319-
regs->portsc_bm.port_power = 1; // enable port power
352+
353+
// enable port power bit in portsc. The function of this bit depends on the value of the Port
354+
// Power Control (PPC) field in the HCSPARAMS register.
355+
if (ehci_data.cap_regs->hcsparams_bm.port_power_control) {
356+
// mask out all change bits since they are Write 1 to clear
357+
uint32_t portsc = (regs->portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL);
358+
portsc |= ECHI_PORTSC_MASK_PORT_POWER;
359+
360+
regs->portsc = portsc;
361+
}
320362

321363
return true;
322364
}
@@ -656,26 +698,6 @@ static void xfer_error_isr(uint8_t hostid)
656698
}
657699
}
658700

659-
#if CFG_TUSB_DEBUG >= EHCI_DBG
660-
661-
static inline void print_portsc(ehci_registers_t* regs)
662-
{
663-
TU_LOG_HEX(EHCI_DBG, regs->portsc);
664-
TU_LOG(EHCI_DBG, " Current Connect Status: %u\r\n", regs->portsc_bm.current_connect_status);
665-
TU_LOG(EHCI_DBG, " Connect Status Change : %u\r\n", regs->portsc_bm.connect_status_change);
666-
TU_LOG(EHCI_DBG, " Port Enabled : %u\r\n", regs->portsc_bm.port_enabled);
667-
TU_LOG(EHCI_DBG, " Port Enabled Change : %u\r\n", regs->portsc_bm.port_enable_change);
668-
669-
TU_LOG(EHCI_DBG, " Port Reset : %u\r\n", regs->portsc_bm.port_reset);
670-
TU_LOG(EHCI_DBG, " Port Power : %u\r\n", regs->portsc_bm.port_power);
671-
}
672-
673-
#else
674-
675-
#define print_portsc(_reg)
676-
677-
#endif
678-
679701
//------------- Host Controller Driver's Interrupt Handler -------------//
680702
void hcd_int_handler(uint8_t rhport)
681703
{
@@ -695,7 +717,7 @@ void hcd_int_handler(uint8_t rhport)
695717

696718
if (int_status & EHCI_INT_MASK_PORT_CHANGE)
697719
{
698-
uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_ALL;
720+
uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_CHANGE_ALL;
699721
print_portsc(regs);
700722

701723
if (regs->portsc_bm.connect_status_change)

0 commit comments

Comments
 (0)