diff --git a/tests/test/host/ehci/test_ehci.c b/tests/test/host/ehci/test_ehci.c index 35e068d7..81d2e226 100644 --- a/tests/test/host/ehci/test_ehci.c +++ b/tests/test/host/ehci/test_ehci.c @@ -359,10 +359,10 @@ void test_hcd_init_async_list(void) for(uint32_t i=0; iasync_list_base); @@ -378,6 +378,34 @@ void test_hcd_init_async_list(void) } +void test_hcd_init_period_list(void) +{ +#if EHCI_PERIODIC_LIST + hcd_init(); + + for(uint32_t i=0; iperiodic_list_base); + for(uint32_t list_idx=0; list_idx < EHCI_FRAMELIST_SIZE; list_idx++) + { + TEST_ASSERT_EQUAL_HEX( (uint32_t) period_head, align32((uint32_t)framelist[list_idx].address) ); + TEST_ASSERT_FALSE(framelist[list_idx].terminate); + TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, framelist[list_idx].type); + } + + TEST_ASSERT(period_head->smask) + TEST_ASSERT_TRUE(period_head->next.terminate); + TEST_ASSERT(period_head->qtd_overlay.next.terminate); + TEST_ASSERT(period_head->qtd_overlay.alternate.terminate); + TEST_ASSERT(period_head->qtd_overlay.halted); + } +#endif +} //--------------------------------------------------------------------+ // Helper //--------------------------------------------------------------------+ diff --git a/tinyusb/host/ehci/ehci.c b/tinyusb/host/ehci/ehci.c index b34fcd63..5e6d0a58 100644 --- a/tinyusb/host/ehci/ehci.c +++ b/tinyusb/host/ehci/ehci.c @@ -62,29 +62,33 @@ STATIC_ ehci_link_t period_frame_list1[EHCI_FRAMELIST_SIZE] ATTR_ALIGNED(4096) T //--------------------------------------------------------------------+ // IMPLEMENTATION //--------------------------------------------------------------------+ -STATIC_ INLINE_ ehci_registers_t* get_operational_register(uint8_t hostid) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; -STATIC_ INLINE_ ehci_registers_t* get_operational_register(uint8_t hostid) +STATIC_ INLINE_ ehci_registers_t* const get_operational_register(uint8_t hostid) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; +STATIC_ INLINE_ ehci_registers_t* const get_operational_register(uint8_t hostid) { - return (ehci_registers_t*) (hostid ? (&LPC_USB1->USBCMD_H) : (&LPC_USB0->USBCMD_H) ); + return (ehci_registers_t* const) (hostid ? (&LPC_USB1->USBCMD_H) : (&LPC_USB0->USBCMD_H) ); } -STATIC_ INLINE_ ehci_link_t* get_period_frame_list(uint8_t list_idx) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; -STATIC_ INLINE_ ehci_link_t* get_period_frame_list(uint8_t list_idx) +STATIC_ INLINE_ ehci_link_t* const get_period_frame_list(uint8_t list_idx) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; +STATIC_ INLINE_ ehci_link_t* const get_period_frame_list(uint8_t list_idx) { #if TUSB_CFG_HOST_CONTROLLER_NUM > 1 return list_idx ? period_frame_list1 : period_frame_list0; // TODO more than 2 controller #else return period_frame_list0; #endif - } STATIC_ INLINE_ ehci_qhd_t* const get_async_head(uint8_t hostid) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT; STATIC_ INLINE_ ehci_qhd_t* const get_async_head(uint8_t hostid) { - return &ehci_data.addr0.qhd[hostid-TUSB_CFG_HOST_CONTROLLER_START_INDEX]; + return &ehci_data.controller.async_head[hostid-TUSB_CFG_HOST_CONTROLLER_START_INDEX]; } +STATIC_ INLINE_ ehci_qhd_t* const get_period_head(uint8_t hostid) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT; +STATIC_ INLINE_ ehci_qhd_t* const get_period_head(uint8_t hostid) +{ + return &ehci_data.controller.period_head[hostid-TUSB_CFG_HOST_CONTROLLER_START_INDEX]; +} tusb_error_t hcd_controller_init(uint8_t hostid) ATTR_WARN_UNUSED_RESULT; @@ -111,7 +115,7 @@ tusb_error_t hcd_init(void) //--------------------------------------------------------------------+ tusb_error_t hcd_controller_init(uint8_t hostid) { - ehci_registers_t* regs = get_operational_register(hostid); + ehci_registers_t* const regs = get_operational_register(hostid); //------------- CTRLDSSEGMENT Register (skip) -------------// //------------- USB INT Register -------------// @@ -139,7 +143,27 @@ tusb_error_t hcd_controller_init(uint8_t hostid) regs->async_list_base = (uint32_t) async_head; //------------- Periodic List -------------// +#if EHCI_PERIODIC_LIST + ehci_link_t * const framelist = get_period_frame_list(hostid); + ehci_qhd_t * const period_head = get_period_head(hostid); + uint32_t i; + for(i=0; ismask = 1; // queue head in period list must have smask non-zero + period_head->next.terminate = 1; + period_head->qtd_overlay.next.terminate = 1; + period_head->qtd_overlay.alternate.terminate = 1; + period_head->qtd_overlay.halted = 1; + + regs->periodic_list_base = (uint32_t) framelist; +#else + regs->periodic_list_base = 0; +#endif //------------- USB CMD Register -------------// //------------- ConfigFlag Register (skip) -------------// @@ -150,7 +174,7 @@ tusb_error_t hcd_controller_init(uint8_t hostid) tusb_error_t hcd_controller_stop(uint8_t hostid) ATTR_WARN_UNUSED_RESULT; tusb_error_t hcd_controller_stop(uint8_t hostid) { - ehci_registers_t* regs = get_operational_register(hostid); + ehci_registers_t* const regs = get_operational_register(hostid); timeout_timer_t timeout; regs->usb_cmd_bit.run_stop = 0; @@ -164,7 +188,7 @@ tusb_error_t hcd_controller_stop(uint8_t hostid) tusb_error_t hcd_controller_reset(uint8_t hostid) ATTR_WARN_UNUSED_RESULT; tusb_error_t hcd_controller_reset(uint8_t hostid) { - ehci_registers_t* regs = get_operational_register(hostid); + ehci_registers_t* const regs = get_operational_register(hostid); timeout_timer_t timeout; if (regs->usb_sts_bit.hc_halted == 0) // need to stop before reset diff --git a/tinyusb/host/ehci/ehci.h b/tinyusb/host/ehci/ehci.h index a91e7a6d..9b184c59 100644 --- a/tinyusb/host/ehci/ehci.h +++ b/tinyusb/host/ehci/ehci.h @@ -417,16 +417,16 @@ typedef struct { // ehci_itd_t itd[EHCI_MAX_ITD] ; ///< Iso Transfer Pool struct { - ehci_qhd_t qhd[TUSB_CFG_HOST_CONTROLLER_NUM]; - ehci_qtd_t qtd[3]; - }addr0; + ehci_qhd_t async_head[TUSB_CFG_HOST_CONTROLLER_NUM]; /// head qhd of async list, also is used as control endpoint for address 0 + ehci_qhd_t period_head[TUSB_CFG_HOST_CONTROLLER_NUM]; + ehci_qtd_t addr0_qtd[3]; + }controller; ///< Static Interrupt Queue Head struct { struct { ehci_qhd_t qhd; ehci_qtd_t qtd[3]; }control; - ehci_qhd_t int_head ; ///< Static Interrupt Queue Head ehci_qhd_t qhd[EHCI_MAX_QHD] ; ///< Queue Head Pool ehci_qtd_t qtd[EHCI_MAX_QTD] ; ///< Queue Element Transfer Pool // ehci_sitd_t sitd[EHCI_MAX_SITD] ; ///< Split (FS) Isochronous Transfer Pool