diff --git a/USBHost_t36.h b/USBHost_t36.h index 07bef0e..351e564 100644 --- a/USBHost_t36.h +++ b/USBHost_t36.h @@ -211,13 +211,16 @@ struct Pipe_struct { void (*callback_function)(const Transfer_t *); uint16_t periodic_interval; uint16_t periodic_offset; + uint16_t bandwidth_interval; + uint16_t bandwidth_offset; + uint16_t bandwidth_shift; + uint8_t bandwidth_stime; + uint8_t bandwidth_ctime; uint32_t unused1; uint32_t unused2; uint32_t unused3; uint32_t unused4; uint32_t unused5; - uint32_t unused6; - uint32_t unused7; }; // Transfer_t represents a single transaction on the USB bus. @@ -259,6 +262,7 @@ class USBHost { public: static void begin(); static void Task(); + static void countFree(uint32_t &devices, uint32_t &pipes, uint32_t &trans, uint32_t &strs); protected: static Pipe_t * new_Pipe(Device_t *dev, uint32_t type, uint32_t endpoint, uint32_t direction, uint32_t maxlen, uint32_t interval=0); diff --git a/ehci.cpp b/ehci.cpp index d0d5427..168b594 100644 --- a/ehci.cpp +++ b/ehci.cpp @@ -1045,6 +1045,10 @@ bool USBHost::allocate_interrupt_pipe_bandwidth(Pipe_t *pipe, uint32_t maxlen, u // a 125 us micro frame can fit 7500 bytes, or 234 of our 32-byte units // fail if the best found needs more than 80% (234 * 0.8) in any uframe if (best_bandwidth > 187) return false; + // save essential bandwidth specs, for cleanup in delete_Pipe + pipe->bandwidth_interval = interval; + pipe->bandwidth_offset = best_offset; + pipe->bandwidth_stime = stime; for (uint32_t i=best_offset; i < PERIODIC_LIST_SIZE*8; i += interval) { uframe_bandwidth[i] += stime; } @@ -1113,6 +1117,12 @@ bool USBHost::allocate_interrupt_pipe_bandwidth(Pipe_t *pipe, uint32_t maxlen, u // a 125 us micro frame can fit 7500 bytes, or 234 of our 32-byte units // fail if the best found needs more than 80% (234 * 0.8) in any uframe if (best_bandwidth > 187) return false; + // save essential bandwidth specs, for cleanup in delete_Pipe + pipe->bandwidth_interval = interval; + pipe->bandwidth_offset = best_offset; + pipe->bandwidth_shift = best_shift; + pipe->bandwidth_stime = stime; + pipe->bandwidth_ctime = ctime; for (uint32_t i=best_offset; i < PERIODIC_LIST_SIZE; i += interval) { uint32_t n = (i << 3) + best_shift; uframe_bandwidth[n+0] += stime; @@ -1299,7 +1309,28 @@ void USBHost::delete_Pipe(Pipe_t *pipe) prev = node; } } - // TODO: subtract bandwidth from uframe_bandwidth array + // subtract bandwidth from uframe_bandwidth array + if (pipe->device->speed == 2) { + uint32_t interval = pipe->bandwidth_interval; + uint32_t offset = pipe->bandwidth_offset; + uint32_t stime = pipe->bandwidth_stime; + for (uint32_t i=offset; i < PERIODIC_LIST_SIZE*8; i += interval) { + uframe_bandwidth[i] -= stime; + } + } else { + uint32_t interval = pipe->bandwidth_interval; + uint32_t offset = pipe->bandwidth_offset; + uint32_t shift = pipe->bandwidth_shift; + uint32_t stime = pipe->bandwidth_stime; + uint32_t ctime = pipe->bandwidth_ctime; + for (uint32_t i=offset; i < PERIODIC_LIST_SIZE; i += interval) { + uint32_t n = (i << 3) + shift; + uframe_bandwidth[n+0] -= stime; + uframe_bandwidth[n+2] -= ctime; + uframe_bandwidth[n+3] -= ctime; + uframe_bandwidth[n+4] -= ctime; + } + } // find & free all the transfers which completed println(" Free transfers"); diff --git a/memory.cpp b/memory.cpp index c325fb3..2851010 100644 --- a/memory.cpp +++ b/memory.cpp @@ -159,4 +159,34 @@ void USBHost::contribute_String_Buffers(strbuf_t *strbufs, uint32_t num) } } - +// for debugging, hopefully never needed... +void USBHost::countFree(uint32_t &devices, uint32_t &pipes, uint32_t &transfers, uint32_t &strs) +{ + uint32_t ndev=0, npipe=0, ntransfer=0, nstr=0; + __disable_irq(); + Device_t *dev = free_Device_list; + while (dev) { + ndev++; + dev = *(Device_t **)dev; + } + Pipe_t *pipe = free_Pipe_list; + while (pipe) { + npipe++; + pipe = *(Pipe_t **)pipe; + } + Transfer_t *transfer = free_Transfer_list; + while (transfer) { + ntransfer++; + transfer = *(Transfer_t **)transfer; + } + strbuf_t *str = free_strbuf_list; + while (str) { + nstr++; + str = *(strbuf_t **)str; + } + __enable_irq(); + devices = ndev; + pipes = npipe; + transfers = ntransfer; + strs = nstr; +}