|
@@ -138,20 +138,25 @@ static void __tusb_irq_path_func(hw_handle_buff_status)(void)
|
|
|
_handle_buff_status_bit(bit, ep);
|
|
_handle_buff_status_bit(bit, ep);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Check interrupt endpoints
|
|
|
|
|
|
|
+ // Check "interrupt" (asynchronous) endpoints for both IN and OUT
|
|
|
for (uint i = 1; i <= USB_HOST_INTERRUPT_ENDPOINTS && remaining_buffers; i++)
|
|
for (uint i = 1; i <= USB_HOST_INTERRUPT_ENDPOINTS && remaining_buffers; i++)
|
|
|
{
|
|
{
|
|
|
- // EPX is bit 0
|
|
|
|
|
- // IEP1 is bit 2
|
|
|
|
|
- // IEP2 is bit 4
|
|
|
|
|
- // IEP3 is bit 6
|
|
|
|
|
|
|
+ // EPX is bit 0 & 1
|
|
|
|
|
+ // IEP1 IN is bit 2
|
|
|
|
|
+ // IEP1 OUT is bit 3
|
|
|
|
|
+ // IEP2 IN is bit 4
|
|
|
|
|
+ // IEP2 OUT is bit 5
|
|
|
|
|
+ // IEP3 IN is bit 6
|
|
|
|
|
+ // IEP3 OUT is bit 7
|
|
|
// etc
|
|
// etc
|
|
|
- bit = 1 << (i*2);
|
|
|
|
|
-
|
|
|
|
|
- if (remaining_buffers & bit)
|
|
|
|
|
|
|
+ for(uint j = 0; j < 2; j++)
|
|
|
{
|
|
{
|
|
|
- remaining_buffers &= ~bit;
|
|
|
|
|
- _handle_buff_status_bit(bit, &ep_pool[i]);
|
|
|
|
|
|
|
+ bit = 1 << (i*2+j);
|
|
|
|
|
+ if (remaining_buffers & bit)
|
|
|
|
|
+ {
|
|
|
|
|
+ remaining_buffers &= ~bit;
|
|
|
|
|
+ _handle_buff_status_bit(bit, &ep_pool[i]);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -273,10 +278,12 @@ static struct hw_endpoint *_hw_endpoint_allocate(uint8_t transfer_type)
|
|
|
{
|
|
{
|
|
|
struct hw_endpoint *ep = NULL;
|
|
struct hw_endpoint *ep = NULL;
|
|
|
|
|
|
|
|
- if (transfer_type == TUSB_XFER_INTERRUPT)
|
|
|
|
|
|
|
+ if (transfer_type != TUSB_XFER_CONTROL)
|
|
|
{
|
|
{
|
|
|
|
|
+ // Note: even though datasheet name these "Interrupt" endpoints. These are actually
|
|
|
|
|
+ // "Asynchronous" endpoints and can be used for other type such as: Bulk (ISO need confirmation)
|
|
|
ep = _next_free_interrupt_ep();
|
|
ep = _next_free_interrupt_ep();
|
|
|
- pico_info("Allocate interrupt ep %d\n", ep->interrupt_num);
|
|
|
|
|
|
|
+ pico_info("Allocate %s ep %d\n", tu_edpt_type_str(transfer_type), ep->interrupt_num);
|
|
|
assert(ep);
|
|
assert(ep);
|
|
|
ep->buffer_control = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl;
|
|
ep->buffer_control = &usbh_dpram->int_ep_buffer_ctrl[ep->interrupt_num].ctrl;
|
|
|
ep->endpoint_control = &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl;
|
|
ep->endpoint_control = &usbh_dpram->int_ep_ctrl[ep->interrupt_num].ctrl;
|
|
@@ -337,13 +344,13 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t
|
|
|
pico_trace("endpoint control (0x%p) <- 0x%x\n", ep->endpoint_control, ep_reg);
|
|
pico_trace("endpoint control (0x%p) <- 0x%x\n", ep->endpoint_control, ep_reg);
|
|
|
ep->configured = true;
|
|
ep->configured = true;
|
|
|
|
|
|
|
|
- if (bmInterval)
|
|
|
|
|
|
|
+ if (ep != &epx)
|
|
|
{
|
|
{
|
|
|
- // This is an interrupt endpoint
|
|
|
|
|
- // so need to set up interrupt endpoint address control register with:
|
|
|
|
|
- // device address
|
|
|
|
|
- // endpoint number / direction
|
|
|
|
|
- // preamble
|
|
|
|
|
|
|
+ // Endpoint has its own addr_endp and interrupt bits to be setup!
|
|
|
|
|
+ // This is an interrupt/async endpoint. so need to set up ADDR_ENDP register with:
|
|
|
|
|
+ // - device address
|
|
|
|
|
+ // - endpoint number / direction
|
|
|
|
|
+ // - preamble
|
|
|
uint32_t reg = (uint32_t) (dev_addr | (num << USB_ADDR_ENDP1_ENDPOINT_LSB));
|
|
uint32_t reg = (uint32_t) (dev_addr | (num << USB_ADDR_ENDP1_ENDPOINT_LSB));
|
|
|
|
|
|
|
|
if (dir == TUSB_DIR_OUT)
|
|
if (dir == TUSB_DIR_OUT)
|
|
@@ -523,6 +530,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
|
|
|
|
|
|
|
|
// Get appropriate ep. Either EPX or interrupt endpoint
|
|
// Get appropriate ep. Either EPX or interrupt endpoint
|
|
|
struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr);
|
|
struct hw_endpoint *ep = get_dev_ep(dev_addr, ep_addr);
|
|
|
|
|
+
|
|
|
TU_ASSERT(ep);
|
|
TU_ASSERT(ep);
|
|
|
|
|
|
|
|
// EP should be inactive
|
|
// EP should be inactive
|