separate fake ehci's run async & period list

refractor list_find_previous_item & list_remove_qhd to act on ehci_link_t* instead of ehci_qhd_t*
fully support 1ms, 2ms, 4ms, 8ms for period list (each list has a dummy queue head)
- change period list structure
limit the maximum polling interval to 256 ms
add max_loop static MAX number of iteration for list_find_previous_item
add test for close 256ms polling interrupt
This commit is contained in:
hathach
2013-04-21 15:09:54 +07:00
parent 357888a5e5
commit a493fab753
7 changed files with 153 additions and 117 deletions
+11 -10
View File
@@ -107,7 +107,7 @@ void test_hcd_init_async_list(void)
TEST_ASSERT_EQUAL_HEX(async_head, regs->async_list_base);
TEST_ASSERT_EQUAL_HEX(async_head, align32(async_head) );
TEST_ASSERT_EQUAL_HEX(async_head, align32( (uint32_t) async_head) );
TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, async_head->next.type);
TEST_ASSERT_FALSE(async_head->next.terminate);
@@ -136,20 +136,21 @@ void test_hcd_init_period_list(void)
TEST_ASSERT_EQUAL_HEX( (uint32_t) framelist, regs->periodic_list_base);
check_qhd_endpoint_link( framelist+1, period_head_arr+1);
check_qhd_endpoint_link( framelist+3, period_head_arr+1);
check_qhd_endpoint_link( framelist+5, period_head_arr+1);
check_qhd_endpoint_link( framelist+7, period_head_arr+1);
check_qhd_endpoint_link( framelist+0, period_head_arr+1);
check_qhd_endpoint_link( framelist+2, period_head_arr+1);
check_qhd_endpoint_link( framelist+4, period_head_arr+1);
check_qhd_endpoint_link( framelist+6, period_head_arr+1);
check_qhd_endpoint_link( framelist+2, period_head_arr+2);
check_qhd_endpoint_link( framelist+6, period_head_arr+2);
check_qhd_endpoint_link( framelist+1, period_head_arr+2);
check_qhd_endpoint_link( framelist+5, period_head_arr+2);
check_qhd_endpoint_link( framelist, period_head_arr);
check_qhd_endpoint_link( framelist+4, period_head_arr);
check_qhd_endpoint_link( framelist+3, period_head_arr+3);
check_qhd_endpoint_link( framelist+7, period_head_arr);
check_qhd_endpoint_link( (ehci_link_t*) (period_head_arr+1), period_head_arr);
check_qhd_endpoint_link( (ehci_link_t*) (period_head_arr+2), period_head_arr);
check_qhd_endpoint_link( (ehci_link_t*) (period_head_arr+3), period_head_arr);
for(uint32_t i=0; i<3; i++)
for(uint32_t i=0; i<4; i++)
{
TEST_ASSERT(period_head_arr[i].interrupt_smask);
TEST_ASSERT(period_head_arr[i].qtd_overlay.halted);
@@ -263,7 +263,7 @@ void test_open_interrupt_hs_interval_7(void)
void test_open_interrupt_hs_interval_8(void)
{
tusb_descriptor_endpoint_t int_edp_interval = desc_ept_interrupt_out;
int_edp_interval.bInterval = 8;
int_edp_interval.bInterval = 16;
//------------- Code Under TEST -------------//
pipe_hdl = hcd_pipe_open(dev_addr, &int_edp_interval, TUSB_CLASS_HID);
@@ -327,6 +327,23 @@ void test_interrupt_close(void)
TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, p_int_qhd->next.type);
}
void test_interrupt_256ms_close(void)
{
tusb_descriptor_endpoint_t int_edp_interval = desc_ept_interrupt_out;
int_edp_interval.bInterval = 9;
pipe_hdl = hcd_pipe_open(dev_addr, &int_edp_interval, TUSB_CLASS_HID);
p_int_qhd = qhd_get_from_pipe_handle(pipe_hdl);
//------------- Code Under TEST -------------//
hcd_pipe_close(pipe_hdl);
TEST_ASSERT(p_int_qhd->is_removing);
TEST_ASSERT( align32(get_period_head(hostid, 8)->address) != (uint32_t) p_int_qhd );
TEST_ASSERT_EQUAL_HEX( (uint32_t) get_period_head(hostid, 8), align32(p_int_qhd->next.address ) );
TEST_ASSERT_EQUAL(EHCI_QUEUE_ELEMENT_QHD, p_int_qhd->next.type);
}
uint8_t count_set_bits(uint8_t x)
{
uint8_t result = 0;
+36 -20
View File
@@ -88,42 +88,58 @@ void ehci_controller_control_xfer_proceed(uint8_t dev_addr, uint8_t p_data[])
hcd_isr( usbh_devices[dev_addr].core_id );
}
bool complete_all_qtd_in_list(ehci_qhd_t *head)
void complete_qtd_in_qhd(ehci_qhd_t *p_qhd)
{
if ( !p_qhd->qtd_overlay.halted )
{
while(!p_qhd->qtd_overlay.next.terminate)
{
ehci_qtd_t* p_qtd = (ehci_qtd_t*) align32(p_qhd->qtd_overlay.next.address);
p_qtd->active = 0;
p_qhd->qtd_overlay = *p_qtd;
}
}
}
bool complete_all_qtd_in_async(ehci_qhd_t *head)
{
ehci_qhd_t *p_qhd = head;
do
{
if ( !p_qhd->qtd_overlay.halted )
{
while(!p_qhd->qtd_overlay.next.terminate)
{
ehci_qtd_t* p_qtd = (ehci_qtd_t*) align32(p_qhd->qtd_overlay.next.address);
p_qtd->active = 0;
p_qhd->qtd_overlay = *p_qtd;
}
}
if (!p_qhd->next.terminate)
{
p_qhd = (ehci_qhd_t*) align32(p_qhd->next.address);
}
else
{
break;
}
complete_qtd_in_qhd(p_qhd);
p_qhd = (ehci_qhd_t*) align32(p_qhd->next.address);
}while(p_qhd != head); // stop if loop around
return true;
}
bool complete_all_qtd_in_period(ehci_link_t *head)
{
while(!head->terminate)
{
uint32_t queue_type = head->type;
head = (ehci_link_t*) align32(head->address);
if ( queue_type == EHCI_QUEUE_ELEMENT_QHD)
{
complete_qtd_in_qhd( (ehci_qhd_t*) head );
}
}
return true;
}
void ehci_controller_run(uint8_t hostid)
{
//------------- Async List -------------//
ehci_registers_t* const regs = get_operational_register(hostid);
complete_all_qtd_in_list((ehci_qhd_t*) regs->async_list_base);
complete_all_qtd_in_async((ehci_qhd_t*) regs->async_list_base);
//------------- Period List -------------//
complete_all_qtd_in_list( get_period_head(hostid, 1) );
for(uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2)
{
complete_all_qtd_in_period( get_period_head(hostid, i) );
}
regs->usb_sts = EHCI_INT_MASK_NXP_ASYNC | EHCI_INT_MASK_NXP_PERIODIC;
hcd_isr(hostid);
+1 -1
View File
@@ -66,7 +66,7 @@ void ehci_controller_device_unplug(uint8_t hostid);
ehci_registers_t* get_operational_register(uint8_t hostid);
ehci_link_t* get_period_frame_list(uint8_t hostid);
ehci_qhd_t* get_async_head(uint8_t hostid);
ehci_qhd_t* get_period_head(uint8_t hostid, uint8_t interval_ms);
ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms);
ehci_qhd_t* get_control_qhd(uint8_t dev_addr);
ehci_qtd_t* get_control_qtds(uint8_t dev_addr);
ehci_qhd_t* qhd_get_from_pipe_handle(pipe_handle_t pipe_hdl);