ehci periodic

This commit is contained in:
hathach 2018-12-11 10:50:05 +07:00
parent 73e6bb6f5d
commit b0717275c8
No known key found for this signature in database
GPG Key ID: 2FA891220FBFD581
6 changed files with 19 additions and 49 deletions

View File

@ -133,7 +133,7 @@ tusb_speed_t hcd_port_speed_get(uint8_t hostid)
} }
// TODO refractor abtract later // TODO refractor abtract later
void hcd_port_unplug(uint8_t hostid) void hcd_device_remove(uint8_t rhport, uint8_t dev_addr)
{ {
ehci_data.regs->usb_cmd_bit.advance_async = 1; // Async doorbell check EHCI 4.8.2 for operational details ehci_data.regs->usb_cmd_bit.advance_async = 1; // Async doorbell check EHCI 4.8.2 for operational details
} }
@ -153,9 +153,7 @@ static bool ehci_init(uint8_t hostid)
regs->usb_sts = EHCI_INT_MASK_ALL; // 2. clear all status regs->usb_sts = EHCI_INT_MASK_ALL; // 2. clear all status
regs->usb_int_enable = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE | regs->usb_int_enable = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE |
#if EHCI_PERIODIC_LIST
EHCI_INT_MASK_NXP_PERIODIC | EHCI_INT_MASK_NXP_PERIODIC |
#endif
EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_ASYNC; EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_ASYNC;
//------------- Asynchronous List -------------// //------------- Asynchronous List -------------//
@ -170,7 +168,6 @@ static bool ehci_init(uint8_t hostid)
regs->async_list_base = (uint32_t) async_head; regs->async_list_base = (uint32_t) async_head;
#if EHCI_PERIODIC_LIST
//------------- Periodic List -------------// //------------- Periodic List -------------//
// Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only // Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only
@ -209,19 +206,13 @@ static bool ehci_init(uint8_t hostid)
period_1ms->terminate = 1; period_1ms->terminate = 1;
regs->periodic_list_base = (uint32_t) framelist; regs->periodic_list_base = (uint32_t) framelist;
#else
regs->periodic_list_base = 0;
#endif
//------------- TT Control (NXP only) -------------// //------------- TT Control (NXP only) -------------//
regs->tt_control = 0; regs->tt_control = 0;
//------------- USB CMD Register -------------// //------------- USB CMD Register -------------//
regs->usb_cmd |= BIT_(EHCI_USBCMD_POS_RUN_STOP) | BIT_(EHCI_USBCMD_POS_ASYNC_ENABLE) regs->usb_cmd |= BIT_(EHCI_USBCMD_POS_RUN_STOP) | BIT_(EHCI_USBCMD_POS_ASYNC_ENABLE)
#if EHCI_PERIODIC_LIST
| BIT_(EHCI_USBCMD_POS_PERIOD_ENABLE) // TODO enable period list only there is int/iso endpoint | BIT_(EHCI_USBCMD_POS_PERIOD_ENABLE) // TODO enable period list only there is int/iso endpoint
#endif
| ((EHCI_CFG_FRAMELIST_SIZE_BITS & BIN8(011)) << EHCI_USBCMD_POS_FRAMELIST_SZIE) | ((EHCI_CFG_FRAMELIST_SIZE_BITS & BIN8(011)) << EHCI_USBCMD_POS_FRAMELIST_SZIE)
| ((EHCI_CFG_FRAMELIST_SIZE_BITS >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB); | ((EHCI_CFG_FRAMELIST_SIZE_BITS >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB);
@ -411,11 +402,9 @@ bool hcd_pipe_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
list_head = (ehci_link_t*) get_async_head(_usbh_devices[dev_addr].rhport); list_head = (ehci_link_t*) get_async_head(_usbh_devices[dev_addr].rhport);
break; break;
#if EHCI_PERIODIC_LIST // TODO refractor/group this together
case TUSB_XFER_INTERRUPT: case TUSB_XFER_INTERRUPT:
list_head = get_period_head(_usbh_devices[dev_addr].rhport, p_qhd->interval_ms); list_head = get_period_head(_usbh_devices[dev_addr].rhport, p_qhd->interval_ms);
break; break;
#endif
case TUSB_XFER_ISOCHRONOUS: case TUSB_XFER_ISOCHRONOUS:
// TODO iso is not supported // TODO iso is not supported
@ -479,14 +468,12 @@ bool hcd_pipe_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
(ehci_link_t*) get_async_head( _usbh_devices[dev_addr].rhport ), (ehci_link_t*) get_async_head( _usbh_devices[dev_addr].rhport ),
(ehci_link_t*) p_qhd), false ); (ehci_link_t*) p_qhd), false );
} }
#if EHCI_PERIODIC_LIST // TODO refractor/group this together
else else
{ {
TU_ASSERT_ERR( list_remove_qhd( TU_ASSERT_ERR( list_remove_qhd(
get_period_head( _usbh_devices[dev_addr].rhport, p_qhd->interval_ms ), get_period_head( _usbh_devices[dev_addr].rhport, p_qhd->interval_ms ),
(ehci_link_t*) p_qhd), false ); (ehci_link_t*) p_qhd), false );
} }
#endif
return true; return true;
} }
@ -610,7 +597,6 @@ static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head)
// TODO abstract max loop guard for async // TODO abstract max loop guard for async
} }
#if EHCI_PERIODIC_LIST // TODO refractor/group this together
static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms) static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms)
{ {
uint8_t max_loop = 0; uint8_t max_loop = 0;
@ -645,7 +631,6 @@ static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms)
max_loop++; max_loop++;
} }
} }
#endif
static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd) static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
{ {
@ -699,7 +684,6 @@ static void xfer_error_isr(uint8_t hostid)
max_loop++; max_loop++;
}while(p_qhd != async_head && max_loop < HCD_MAX_ENDPOINT*CFG_TUSB_HOST_DEVICE_MAX); // async list traversal, stop if loop around }while(p_qhd != async_head && max_loop < HCD_MAX_ENDPOINT*CFG_TUSB_HOST_DEVICE_MAX); // async list traversal, stop if loop around
#if EHCI_PERIODIC_LIST
//------------- TODO refractor period list -------------// //------------- TODO refractor period list -------------//
uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1); uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1);
for (uint8_t interval_ms=1; interval_ms <= EHCI_FRAMELIST_SIZE; interval_ms *= 2) for (uint8_t interval_ms=1; interval_ms <= EHCI_FRAMELIST_SIZE; interval_ms *= 2)
@ -732,7 +716,6 @@ static void xfer_error_isr(uint8_t hostid)
period_max_loop++; period_max_loop++;
} }
} }
#endif
} }
//------------- Host Controller Driver's Interrupt Handler -------------// //------------- Host Controller Driver's Interrupt Handler -------------//
@ -770,7 +753,6 @@ void hal_hcd_isr(uint8_t hostid)
async_list_xfer_complete_isr( get_async_head(hostid) ); async_list_xfer_complete_isr( get_async_head(hostid) );
} }
#if EHCI_PERIODIC_LIST // TODO refractor/group this together
if (int_status & EHCI_INT_MASK_NXP_PERIODIC) if (int_status & EHCI_INT_MASK_NXP_PERIODIC)
{ {
for (uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2) for (uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2)
@ -778,7 +760,6 @@ void hal_hcd_isr(uint8_t hostid)
period_list_xfer_complete_isr( hostid, i ); period_list_xfer_complete_isr( hostid, i );
} }
} }
#endif
//------------- There is some removed async previously -------------// //------------- There is some removed async previously -------------//
if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) // need to place after EHCI_INT_MASK_NXP_ASYNC if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) // need to place after EHCI_INT_MASK_NXP_ASYNC
@ -801,12 +782,10 @@ static inline ehci_qhd_t* get_async_head(uint8_t hostid)
return get_control_qhd(0); return get_control_qhd(0);
} }
#if EHCI_PERIODIC_LIST // TODO refractor/group this together
static inline ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms) static inline ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms)
{ {
return (ehci_link_t*) &ehci_data.period_head_arr[ tu_log2( tu_min8(EHCI_FRAMELIST_SIZE, interval_ms) ) ]; return (ehci_link_t*) &ehci_data.period_head_arr[ tu_log2( tu_min8(EHCI_FRAMELIST_SIZE, interval_ms) ) ];
} }
#endif
static inline ehci_qhd_t* get_control_qhd(uint8_t dev_addr) static inline ehci_qhd_t* get_control_qhd(uint8_t dev_addr)
{ {

View File

@ -68,9 +68,6 @@
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// EHCI CONFIGURATION & CONSTANTS // EHCI CONFIGURATION & CONSTANTS
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
#define HOST_HCD_XFER_INTERRUPT // TODO interrupt is used widely, should always be enalbed
#define EHCI_PERIODIC_LIST (defined HOST_HCD_XFER_INTERRUPT || defined HOST_HCD_XFER_ISOCHRONOUS)
#define EHCI_CFG_FRAMELIST_SIZE_BITS 7 /// Framelist Size (NXP specific) (0:1024) - (1:512) - (2:256) - (3:128) - (4:64) - (5:32) - (6:16) - (7:8) #define EHCI_CFG_FRAMELIST_SIZE_BITS 7 /// Framelist Size (NXP specific) (0:1024) - (1:512) - (2:256) - (3:128) - (4:64) - (5:32) - (6:16) - (7:8)
#define EHCI_FRAMELIST_SIZE (1024 >> EHCI_CFG_FRAMELIST_SIZE_BITS) #define EHCI_FRAMELIST_SIZE (1024 >> EHCI_CFG_FRAMELIST_SIZE_BITS)

View File

@ -96,12 +96,21 @@ enum {
#endif #endif
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// USBH-HCD API // HCD API
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
bool hcd_init(void); bool hcd_init(void);
void hcd_int_enable (uint8_t rhport); void hcd_int_enable (uint8_t rhport);
void hcd_int_disable(uint8_t rhport); void hcd_int_disable(uint8_t rhport);
// PORT API
/// return the current connect status of roothub port
bool hcd_port_connect_status(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible
void hcd_port_reset(uint8_t hostid);
tusb_speed_t hcd_port_speed_get(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible
// Call by USBH after event device remove
void hcd_device_remove(uint8_t rhport, uint8_t dev_addr);
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
// Event function // Event function
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
@ -111,7 +120,7 @@ void hcd_event_handler(hcd_event_t const* event, bool in_isr);
void hcd_event_device_attach(uint8_t rhport); void hcd_event_device_attach(uint8_t rhport);
// Helper to send device removal event // Helper to send device removal event
void hcd_event_device_remove(uint8_t hostid); void hcd_event_device_remove(uint8_t rhport);
// Helper to send USB transfer event // Helper to send USB transfer event
void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
@ -140,15 +149,6 @@ bool hcd_pipe_clear_stall(uint8_t dev_addr, uint8_t ep_addr);
tusb_error_t hcd_pipe_cancel()ATTR_WARN_UNUSED_RESULT; tusb_error_t hcd_pipe_cancel()ATTR_WARN_UNUSED_RESULT;
#endif #endif
//--------------------------------------------------------------------+
// PORT API
//--------------------------------------------------------------------+
/// return the current connect status of roothub port
bool hcd_port_connect_status(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible
void hcd_port_reset(uint8_t hostid);
tusb_speed_t hcd_port_speed_get(uint8_t hostid) ATTR_PURE ATTR_WARN_UNUSED_RESULT; // TODO make inline if possible
void hcd_port_unplug(uint8_t hostid); // called by usbh to instruct hcd that it can execute unplug procedure
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -319,15 +319,16 @@ void hcd_event_device_remove(uint8_t hostid)
// a device unplugged on hostid, hub_addr, hub_port // a device unplugged on hostid, hub_addr, hub_port
// return true if found and unmounted device, false if cannot find // return true if found and unmounted device, false if cannot find
static void usbh_device_unplugged(uint8_t hostid, uint8_t hub_addr, uint8_t hub_port) static void usbh_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port)
{ {
bool is_found = false; bool is_found = false;
//------------- find the all devices (star-network) under port that is unplugged -------------// //------------- find the all devices (star-network) under port that is unplugged -------------//
for (uint8_t dev_addr = 0; dev_addr <= CFG_TUSB_HOST_DEVICE_MAX; dev_addr ++) for (uint8_t dev_addr = 0; dev_addr <= CFG_TUSB_HOST_DEVICE_MAX; dev_addr ++)
{ {
usbh_device_t* dev = &_usbh_devices[dev_addr]; usbh_device_t* dev = &_usbh_devices[dev_addr];
if (dev->rhport == hostid && if (dev->rhport == rhport &&
(hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr == 0 & hub_port == 0 means roothub (hub_addr == 0 || dev->hub_addr == hub_addr) && // hub_addr == 0 & hub_port == 0 means roothub
(hub_port == 0 || dev->hub_port == hub_port) && (hub_port == 0 || dev->hub_port == hub_port) &&
dev->state != TUSB_DEVICE_STATE_UNPLUG) dev->state != TUSB_DEVICE_STATE_UNPLUG)
@ -349,11 +350,14 @@ static void usbh_device_unplugged(uint8_t hostid, uint8_t hub_addr, uint8_t hub_
usbh_pipe_control_close(dev_addr); usbh_pipe_control_close(dev_addr);
// hcd_device_remove(rhport, dev_addr);
is_found = true; is_found = true;
} }
} }
if (is_found) hcd_port_unplug(_usbh_devices[0].rhport); // TODO hack // FIXME remove
if (is_found) hcd_device_remove(_usbh_devices[0].rhport, 0);
} }

View File

@ -212,9 +212,6 @@
//------------- HID CLASS -------------// //------------- HID CLASS -------------//
#define HOST_CLASS_HID ( CFG_TUH_HID_KEYBOARD + CFG_TUH_HID_MOUSE + CFG_TUSB_HOST_HID_GENERIC ) #define HOST_CLASS_HID ( CFG_TUH_HID_KEYBOARD + CFG_TUH_HID_MOUSE + CFG_TUSB_HOST_HID_GENERIC )
// #if HOST_CLASS_HID
// #define HOST_HCD_XFER_INTERRUPT
// #endif
#ifndef CFG_TUSB_HOST_ENUM_BUFFER_SIZE #ifndef CFG_TUSB_HOST_ENUM_BUFFER_SIZE
#define CFG_TUSB_HOST_ENUM_BUFFER_SIZE 256 #define CFG_TUSB_HOST_ENUM_BUFFER_SIZE 256

View File

@ -125,7 +125,6 @@ void check_qhd_endpoint_link(ehci_link_t *p_prev, ehci_qhd_t *p_qhd)
void test_hcd_init_period_list(void) void test_hcd_init_period_list(void)
{ {
#if EHCI_PERIODIC_LIST
ehci_registers_t* const regs = get_operational_register(hostid); ehci_registers_t* const regs = get_operational_register(hostid);
ehci_qhd_t * const period_head_arr = get_period_head(hostid, 1); ehci_qhd_t * const period_head_arr = get_period_head(hostid, 1);
ehci_link_t * const framelist = get_period_frame_list(hostid); ehci_link_t * const framelist = get_period_frame_list(hostid);
@ -153,7 +152,6 @@ void test_hcd_init_period_list(void)
} }
TEST_ASSERT_TRUE(period_head_arr[0].next.terminate); TEST_ASSERT_TRUE(period_head_arr[0].next.terminate);
#endif
} }
void test_hcd_init_tt_control(void) void test_hcd_init_tt_control(void)
@ -166,12 +164,7 @@ void test_hcd_init_usbcmd(void)
ehci_registers_t* const regs = get_operational_register(hostid); ehci_registers_t* const regs = get_operational_register(hostid);
TEST_ASSERT(regs->usb_cmd_bit.async_enable); TEST_ASSERT(regs->usb_cmd_bit.async_enable);
#if EHCI_PERIODIC_LIST
TEST_ASSERT(regs->usb_cmd_bit.periodic_enable); TEST_ASSERT(regs->usb_cmd_bit.periodic_enable);
#else
TEST_ASSERT_FALSE(regs->usb_cmd_bit.periodic_enable);
#endif
//------------- Framelist size (NXP specific) -------------// //------------- Framelist size (NXP specific) -------------//
TEST_ASSERT_BITS(BIN8(11), EHCI_CFG_FRAMELIST_SIZE_BITS, regs->usb_cmd_bit.framelist_size); TEST_ASSERT_BITS(BIN8(11), EHCI_CFG_FRAMELIST_SIZE_BITS, regs->usb_cmd_bit.framelist_size);