mirror of
https://github.com/gdsports/USBHost_t36
synced 2024-11-24 18:12:16 -05:00
Add to periodic sched using interval+offset & binary tree
This commit is contained in:
parent
1c5d403aba
commit
80225dfe22
@ -95,12 +95,12 @@ struct Pipe_struct {
|
||||
Device_t *device;
|
||||
uint8_t type; // 0=control, 1=isochronous, 2=bulk, 3=interrupt
|
||||
uint8_t direction; // 0=out, 1=in (changes for control, others fixed)
|
||||
uint8_t start_mask;
|
||||
uint8_t complete_mask;
|
||||
uint8_t start_mask; // TODO: is this redundant?
|
||||
uint8_t complete_mask; // TODO: is this redundant?
|
||||
Pipe_t *next;
|
||||
void (*callback_function)(const Transfer_t *);
|
||||
uint16_t periodic_interval;
|
||||
uint16_t periodic_offset;
|
||||
uint16_t periodic_offset; // TODO: is this redundant?
|
||||
uint32_t unused1;
|
||||
uint32_t unused2;
|
||||
uint32_t unused3;
|
||||
@ -174,12 +174,14 @@ private:
|
||||
static void free_Transfer(Transfer_t *q);
|
||||
static bool allocate_interrupt_pipe_bandwidth(Pipe_t *pipe,
|
||||
uint32_t maxlen, uint32_t interval);
|
||||
static void add_qh_to_periodic_schedule(Pipe_t *pipe);
|
||||
protected:
|
||||
static void print(const Transfer_t *transfer);
|
||||
static void print(const Transfer_t *first, const Transfer_t *last);
|
||||
static void print_token(uint32_t token);
|
||||
static void print(const Pipe_t *pipe);
|
||||
static void print_driverlist(const char *name, const USBDriver *driver);
|
||||
static void print_qh_list(const Pipe_t *list);
|
||||
static void print_hexbytes(const void *ptr, uint32_t len);
|
||||
static void print(const char *s) { Serial.print(s); }
|
||||
static void print(int n) { Serial.print(n); }
|
||||
|
67
ehci.cpp
67
ehci.cpp
@ -24,6 +24,10 @@
|
||||
#include <Arduino.h>
|
||||
#include "USBHost.h"
|
||||
|
||||
// Size of the periodic list, in milliseconds. This determines the
|
||||
// slowest rate we can poll interrupt endpoints. Each entry uses
|
||||
// 12 bytes (4 for a pointer, 8 for bandwidth management).
|
||||
// may be 8, 16, 32, 64, 128, 256, 512, 1024
|
||||
#define PERIODIC_LIST_SIZE 32
|
||||
|
||||
static uint32_t periodictable[PERIODIC_LIST_SIZE] __attribute__ ((aligned(4096), used));
|
||||
@ -422,21 +426,7 @@ Pipe_t * USBHost::new_Pipe(Device_t *dev, uint32_t type, uint32_t endpoint,
|
||||
}
|
||||
} else if (type == 3) {
|
||||
// interrupt: add to periodic schedule
|
||||
// TODO: link it into the periodic table
|
||||
|
||||
|
||||
//add_qh_to_periodic_schedule(pipe);
|
||||
|
||||
// TODO: built tree...
|
||||
//uint32_t finterval = interval >> 3;
|
||||
//for (uint32_t i=offset; i < PERIODIC_LIST_SIZE; i += finterval) {
|
||||
// uint32_t list = periodictable[i];
|
||||
//}
|
||||
|
||||
// quick hack for testing, just put it into the first table entry
|
||||
pipe->qh.horizontal_link = periodictable[0];
|
||||
periodictable[0] = (uint32_t)&(pipe->qh) | 2; // 2=QH
|
||||
println("init periodictable with ", periodictable[0], HEX);
|
||||
add_qh_to_periodic_schedule(pipe);
|
||||
}
|
||||
return pipe;
|
||||
}
|
||||
@ -867,6 +857,53 @@ bool USBHost::allocate_interrupt_pipe_bandwidth(Pipe_t *pipe, uint32_t maxlen, u
|
||||
return true;
|
||||
}
|
||||
|
||||
// put a new pipe into the periodic schedule tree
|
||||
// according to periodic_interval and periodic_offset
|
||||
//
|
||||
void USBHost::add_qh_to_periodic_schedule(Pipe_t *pipe)
|
||||
{
|
||||
// quick hack for testing, just put it into the first table entry
|
||||
println("add_qh_to_periodic_schedule:");
|
||||
#if 0
|
||||
pipe->qh.horizontal_link = periodictable[0];
|
||||
periodictable[0] = (uint32_t)&(pipe->qh) | 2; // 2=QH
|
||||
println("init periodictable with ", periodictable[0], HEX);
|
||||
#else
|
||||
uint32_t interval = pipe->periodic_interval;
|
||||
uint32_t offset = pipe->periodic_offset;
|
||||
println(" interval = ", interval);
|
||||
println(" offset = ", offset);
|
||||
|
||||
// TODO: does this really make an inverted tree like EHCI figure 4-18, page 93
|
||||
for (uint32_t i=offset; i < PERIODIC_LIST_SIZE; i += interval) {
|
||||
uint32_t num = periodictable[i];
|
||||
Pipe_t *node = (Pipe_t *)(num & 0xFFFFFFE0);
|
||||
if ((num & 1) || ((num & 6) == 2 && node->periodic_interval < interval)) {
|
||||
println(" add to slot ", i);
|
||||
pipe->qh.horizontal_link = num;
|
||||
periodictable[i] = (uint32_t)&(pipe->qh) | 2; // 2=QH
|
||||
} else {
|
||||
println(" traverse list ", i);
|
||||
// TODO: skip past iTD, siTD when/if we support isochronous
|
||||
while (node->periodic_interval >= interval) {
|
||||
if (node->qh.horizontal_link & 1) break;
|
||||
num = node->qh.horizontal_link;
|
||||
node = (Pipe_t *)(num & 0xFFFFFFE0);
|
||||
}
|
||||
pipe->qh.horizontal_link = num;
|
||||
node->qh.horizontal_link = (uint32_t)pipe | 2; // 2=QH
|
||||
}
|
||||
}
|
||||
#endif
|
||||
println("Periodic Schedule:");
|
||||
for (uint32_t i=0; i < PERIODIC_LIST_SIZE; i++) {
|
||||
if (i < 10) print(" ");
|
||||
print(i);
|
||||
print(": ");
|
||||
print_qh_list((Pipe_t *)(periodictable[i] & 0xFFFFFFE0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void USBHost::delete_Pipe(Pipe_t *pipe)
|
||||
{
|
||||
|
3
hub.cpp
3
hub.cpp
@ -138,7 +138,8 @@ void USBHub::control(const Transfer_t *transfer)
|
||||
} else if (state == numports) {
|
||||
println("power turned on to all ports");
|
||||
println("device addr = ", device->address);
|
||||
changepipe = new_Pipe(device, 3, endpoint, 1, 1, 512);
|
||||
// TODO: use hub's interrupt endpoint interval
|
||||
changepipe = new_Pipe(device, 3, endpoint, 1, 1, 64);
|
||||
println("pipe cap1 = ", changepipe->qh.capabilities[0], HEX);
|
||||
changepipe->callback_function = callback;
|
||||
queue_Data_Transfer(changepipe, &changebits, 1, this);
|
||||
|
@ -59,7 +59,7 @@ bool KeyboardController::claim(Device_t *dev, int type, const uint8_t *descripto
|
||||
if (size != 8) return false; // must be 8 bytes for Keyboard Boot Protocol
|
||||
uint32_t interval = descriptors[24];
|
||||
println("polling interval = ", interval);
|
||||
datapipe = new_Pipe(dev, 3, endpoint, 1, 8, 64);
|
||||
datapipe = new_Pipe(dev, 3, endpoint, 1, 8, interval);
|
||||
datapipe->callback_function = callback;
|
||||
queue_Data_Transfer(datapipe, report, 8, this);
|
||||
return true;
|
||||
|
19
print.cpp
19
print.cpp
@ -146,6 +146,25 @@ void USBHost::print_driverlist(const char *name, const USBDriver *driver)
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void USBHost::print_qh_list(const Pipe_t *list)
|
||||
{
|
||||
if (!list) {
|
||||
Serial.println("(empty)");
|
||||
return;
|
||||
}
|
||||
const Pipe_t *node = list;
|
||||
while (1) {
|
||||
Serial.print((uint32_t)node, HEX);
|
||||
node = (const Pipe_t *)(node->qh.horizontal_link & 0xFFFFFFE0);
|
||||
if (!node) break;
|
||||
if (node == list) {
|
||||
Serial.print(" (loops)");
|
||||
break;
|
||||
}
|
||||
Serial.print(" -> ");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void USBHost::print_hexbytes(const void *ptr, uint32_t len)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user