diff --git a/tests/test/host/ehci/test_ehci.h b/tests/test/host/ehci/test_ehci.h deleted file mode 100644 index d6801de69..000000000 --- a/tests/test/host/ehci/test_ehci.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * test_ehci.h - * - * Created on: Mar 5, 2013 - * Author: hathach - */ - -/* - * Software License Agreement (BSD License) - * Copyright (c) 2012, hathach (tinyusb.net) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the tiny usb stack. - */ - -/** \file - * \brief TBD - * - * \note TBD - */ - -/** \ingroup TBD - * \defgroup TBD - * \brief TBD - * - * @{ - */ - -#ifndef _TUSB_TEST_EHCI_H_ -#define _TUSB_TEST_EHCI_H_ - -#ifdef __cplusplus - extern "C" { -#endif - -#include - -ehci_registers_t* const get_operational_register(uint8_t hostid); -ehci_link_t* const get_period_frame_list(uint8_t list_idx); -ehci_qhd_t* const get_async_head(uint8_t hostid); -ehci_qhd_t* const get_period_head(uint8_t hostid); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_TEST_EHCI_H_ */ - -/** @} */ diff --git a/tests/test/host/ehci/test_ehci_init.c b/tests/test/host/ehci/test_ehci_init.c index 4a6088cff..487df4678 100644 --- a/tests/test/host/ehci/test_ehci_init.c +++ b/tests/test/host/ehci/test_ehci_init.c @@ -45,13 +45,10 @@ #include "hcd.h" #include "mock_usbh_hcd.h" #include "ehci.h" +#include "ehci_controller.h" -extern ehci_data_t ehci_data; usbh_device_info_t usbh_device_info_pool[TUSB_CFG_HOST_DEVICE_MAX+1]; -LPC_USB0_Type lpc_usb0; -LPC_USB1_Type lpc_usb1; - //--------------------------------------------------------------------+ // Setup/Teardown + helper declare //--------------------------------------------------------------------+ diff --git a/tests/test/host/ehci/test_ehci_isr.c b/tests/test/host/ehci/test_ehci_isr.c index 95cbbcb5b..f6b9a09e5 100644 --- a/tests/test/host/ehci/test_ehci_isr.c +++ b/tests/test/host/ehci/test_ehci_isr.c @@ -47,9 +47,6 @@ #include "ehci.h" #include "ehci_controller.h" -LPC_USB0_Type lpc_usb0; -LPC_USB1_Type lpc_usb1; - usbh_device_info_t usbh_device_info_pool[TUSB_CFG_HOST_DEVICE_MAX+1]; uint8_t hostid; @@ -106,4 +103,44 @@ void test_isr_device_disconnect(void) //------------- Code Under Test -------------// hcd_isr(hostid); + ehci_registers_t * const regs = get_operational_register(hostid); + TEST_ASSERT(regs->usb_cmd_bit.advacne_async); +} + +void test_isr_disconnect_then_async_advance(void) +{ + uint8_t dev_addr = 1; + uint8_t hostid = 0; + ehci_registers_t * const regs = get_operational_register(hostid); + +// usbh_device_info_pool[dev_addr].status = TUSB_DEVICE_STATUS_READY; + usbh_device_info_pool[dev_addr].core_id = hostid; + usbh_device_info_pool[dev_addr].hub_addr = 0; + usbh_device_info_pool[dev_addr].hub_port = 0; + + hcd_pipe_control_open(dev_addr, 64); + hcd_pipe_control_xfer(dev_addr, + &(tusb_std_request_t) { + .bmRequestType = { .direction = TUSB_DIR_HOST_TO_DEV, .type = TUSB_REQUEST_TYPE_STANDARD, .recipient = TUSB_REQUEST_RECIPIENT_DEVICE }, + .bRequest = TUSB_REQUEST_SET_ADDRESS, + .wValue = 3 }, + NULL); + + ehci_qhd_t *p_qhd = &ehci_data.device[dev_addr].control.qhd; + ehci_qtd_t *p_qtd_head = p_qhd->p_qtd_list_head; + ehci_qtd_t *p_qtd_tail = p_qhd->p_qtd_list_tail; + + ehci_controller_device_unplug(hostid); + usbh_device_unplugged_isr_Expect(hostid); + + //------------- Code Under Test -------------// + hcd_isr(hostid); // port change detect + regs->usb_sts_bit.port_change_detect = 0; // clear port change detect + hcd_isr(hostid); // async advance + + TEST_ASSERT( align32(get_async_head(hostid)->next.address) != (uint32_t) p_qhd ); + TEST_ASSERT_FALSE(p_qhd->used); + TEST_ASSERT_FALSE(p_qtd_head->used); + TEST_ASSERT_FALSE(p_qtd_tail->used); + } diff --git a/tests/test/host/ehci/test_ehci_pipe_bulk_xfer.c b/tests/test/host/ehci/test_ehci_pipe_bulk_xfer.c index 97c9e88fd..1f6221abf 100644 --- a/tests/test/host/ehci/test_ehci_pipe_bulk_xfer.c +++ b/tests/test/host/ehci/test_ehci_pipe_bulk_xfer.c @@ -45,15 +45,10 @@ #include "hcd.h" #include "mock_usbh_hcd.h" #include "ehci.h" -#include "test_ehci.h" #include "ehci_controller.h" -extern ehci_data_t ehci_data; usbh_device_info_t usbh_device_info_pool[TUSB_CFG_HOST_DEVICE_MAX+1]; -LPC_USB0_Type lpc_usb0; -LPC_USB1_Type lpc_usb1; - uint8_t const control_max_packet_size = 64; uint8_t const hub_addr = 2; uint8_t const hub_port = 2; diff --git a/tests/test/host/ehci/test_ehci_pipe_open.c b/tests/test/host/ehci/test_ehci_pipe_open.c index 9e928d9fb..bea3709f3 100644 --- a/tests/test/host/ehci/test_ehci_pipe_open.c +++ b/tests/test/host/ehci/test_ehci_pipe_open.c @@ -45,14 +45,10 @@ #include "hcd.h" #include "mock_usbh_hcd.h" #include "ehci.h" -#include "test_ehci.h" +#include "ehci_controller.h" -extern ehci_data_t ehci_data; usbh_device_info_t usbh_device_info_pool[TUSB_CFG_HOST_DEVICE_MAX+1]; -LPC_USB0_Type lpc_usb0; -LPC_USB1_Type lpc_usb1; - uint8_t const control_max_packet_size = 64; uint8_t const hub_addr = 2; uint8_t const hub_port = 2; diff --git a/tests/test/host/ehci/test_ehci_pipe_xfer_control.c b/tests/test/host/ehci/test_ehci_pipe_xfer_control.c index 2c54d95cd..b264994f4 100644 --- a/tests/test/host/ehci/test_ehci_pipe_xfer_control.c +++ b/tests/test/host/ehci/test_ehci_pipe_xfer_control.c @@ -45,15 +45,10 @@ #include "hcd.h" #include "mock_usbh_hcd.h" #include "ehci.h" -#include "test_ehci.h" #include "ehci_controller.h" -extern ehci_data_t ehci_data; usbh_device_info_t usbh_device_info_pool[TUSB_CFG_HOST_DEVICE_MAX+1]; -LPC_USB0_Type lpc_usb0; -LPC_USB1_Type lpc_usb1; - uint8_t const control_max_packet_size = 64; uint8_t const hub_addr = 2; uint8_t const hub_port = 2; diff --git a/tests/test/host/ehci/test_ehci_structure.c b/tests/test/host/ehci/test_ehci_structure.c index 5b07f2720..88f56b688 100644 --- a/tests/test/host/ehci/test_ehci_structure.c +++ b/tests/test/host/ehci/test_ehci_structure.c @@ -45,13 +45,10 @@ #include "hcd.h" #include "mock_usbh_hcd.h" #include "ehci.h" +#include "ehci_controller.h" -extern ehci_data_t ehci_data; usbh_device_info_t usbh_device_info_pool[TUSB_CFG_HOST_DEVICE_MAX+1]; -LPC_USB0_Type lpc_usb0; -LPC_USB1_Type lpc_usb1; - //--------------------------------------------------------------------+ // Setup/Teardown + helper declare //--------------------------------------------------------------------+ diff --git a/tests/test/support/ehci_controller.c b/tests/test/support/ehci_controller.c index 484348566..4c3ab33ff 100644 --- a/tests/test/support/ehci_controller.c +++ b/tests/test/support/ehci_controller.c @@ -48,7 +48,9 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -extern ehci_data_t ehci_data; +ehci_data_t ehci_data; +LPC_USB0_Type lpc_usb0; +LPC_USB1_Type lpc_usb1; //--------------------------------------------------------------------+ // IMPLEMENTATION diff --git a/tests/test/support/ehci_controller.h b/tests/test/support/ehci_controller.h index cb5c69313..7191b1294 100644 --- a/tests/test/support/ehci_controller.h +++ b/tests/test/support/ehci_controller.h @@ -55,10 +55,17 @@ extern "C" { #endif +extern ehci_data_t ehci_data; + void ehci_controller_run(uint8_t hostid); void ehci_controller_device_plug(uint8_t hostid, tusb_speed_t speed); void ehci_controller_device_unplug(uint8_t hostid); +ehci_registers_t* const get_operational_register(uint8_t hostid); +ehci_link_t* const get_period_frame_list(uint8_t list_idx); +ehci_qhd_t* const get_async_head(uint8_t hostid); +ehci_qhd_t* const get_period_head(uint8_t hostid); + #ifdef __cplusplus } #endif diff --git a/tinyusb/host/ehci/ehci.c b/tinyusb/host/ehci/ehci.c index f79b478e6..20750316c 100644 --- a/tinyusb/host/ehci/ehci.c +++ b/tinyusb/host/ehci/ehci.c @@ -165,8 +165,17 @@ static inline uint8_t get_qhd_index(ehci_qhd_t * p_qhd) return p_qhd - ehci_data.device[p_qhd->device_address].qhd; } +void async_advance_isr(ehci_qhd_t * const async_head) +{ + ehci_qhd_t *p_qhd = async_head; + do + { -void port_connect_status_isr(uint8_t hostid) + p_qhd = (ehci_qhd_t*) align32(p_qhd->next.address); + }while(p_qhd != async_head); // stop if loop around +} + +void port_connect_status_change_isr(uint8_t hostid) { ehci_registers_t* const regs = get_operational_register(hostid); @@ -177,6 +186,8 @@ void port_connect_status_isr(uint8_t hostid) }else // device unplugged { usbh_device_unplugged_isr(hostid); + + regs->usb_cmd_bit.advacne_async = 1; // Async doorbell check EHCI 4.8.2 for operational details } } @@ -186,10 +197,7 @@ void async_list_process_isr(ehci_qhd_t * const async_head, ehci_registers_t * co ehci_qhd_t *p_qhd = async_head; do { - if ( p_qhd->qtd_overlay.halted ) - { - // TODO invoke some error callback if not async head - } else + if ( !p_qhd->qtd_overlay.halted ) { // free all TDs from the head td to the first active TD while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active) @@ -217,7 +225,7 @@ void async_list_process_isr(ehci_qhd_t * const async_head, ehci_registers_t * co } } p_qhd = (ehci_qhd_t*) align32(p_qhd->next.address); - }while(p_qhd != async_head); // stop if loop around + }while(p_qhd != async_head); // async list traversal, stop if loop around } //------------- Host Controller Driver's Interrupt Handler -------------// @@ -232,7 +240,8 @@ void hcd_isr(uint8_t hostid) if (int_status & EHCI_INT_MASK_ERROR) { - // TODO something going wrong + // TODO handle Queue Head halted + // TODO invoke some error callback if not async head ASM_BREAKPOINT; } @@ -251,7 +260,7 @@ void hcd_isr(uint8_t hostid) { if (regs->portsc_bit.connect_status_change) { - port_connect_status_isr(hostid); + port_connect_status_change_isr(hostid); } regs->portsc |= EHCI_PORTSC_MASK_ALL; // Acknowledge all the change bit in portsc @@ -259,7 +268,7 @@ void hcd_isr(uint8_t hostid) if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) { - + async_advance_isr( get_async_head(hostid) ); } regs->usb_sts |= regs->usb_sts; // Acknowledge interrupt & clear it @@ -276,12 +285,11 @@ tusb_error_t hcd_controller_init(uint8_t hostid) //------------- USB INT Register -------------// regs->usb_int_enable = 0; // 1. disable all the interrupt 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 -------------// ehci_qhd_t * const async_head = get_async_head(hostid);