mirror of
https://github.com/gdsports/USBHost_t36
synced 2024-11-22 00:52:19 -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;
|
Device_t *device;
|
||||||
uint8_t type; // 0=control, 1=isochronous, 2=bulk, 3=interrupt
|
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 direction; // 0=out, 1=in (changes for control, others fixed)
|
||||||
uint8_t start_mask;
|
uint8_t start_mask; // TODO: is this redundant?
|
||||||
uint8_t complete_mask;
|
uint8_t complete_mask; // TODO: is this redundant?
|
||||||
Pipe_t *next;
|
Pipe_t *next;
|
||||||
void (*callback_function)(const Transfer_t *);
|
void (*callback_function)(const Transfer_t *);
|
||||||
uint16_t periodic_interval;
|
uint16_t periodic_interval;
|
||||||
uint16_t periodic_offset;
|
uint16_t periodic_offset; // TODO: is this redundant?
|
||||||
uint32_t unused1;
|
uint32_t unused1;
|
||||||
uint32_t unused2;
|
uint32_t unused2;
|
||||||
uint32_t unused3;
|
uint32_t unused3;
|
||||||
@ -174,12 +174,14 @@ private:
|
|||||||
static void free_Transfer(Transfer_t *q);
|
static void free_Transfer(Transfer_t *q);
|
||||||
static bool allocate_interrupt_pipe_bandwidth(Pipe_t *pipe,
|
static bool allocate_interrupt_pipe_bandwidth(Pipe_t *pipe,
|
||||||
uint32_t maxlen, uint32_t interval);
|
uint32_t maxlen, uint32_t interval);
|
||||||
|
static void add_qh_to_periodic_schedule(Pipe_t *pipe);
|
||||||
protected:
|
protected:
|
||||||
static void print(const Transfer_t *transfer);
|
static void print(const Transfer_t *transfer);
|
||||||
static void print(const Transfer_t *first, const Transfer_t *last);
|
static void print(const Transfer_t *first, const Transfer_t *last);
|
||||||
static void print_token(uint32_t token);
|
static void print_token(uint32_t token);
|
||||||
static void print(const Pipe_t *pipe);
|
static void print(const Pipe_t *pipe);
|
||||||
static void print_driverlist(const char *name, const USBDriver *driver);
|
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_hexbytes(const void *ptr, uint32_t len);
|
||||||
static void print(const char *s) { Serial.print(s); }
|
static void print(const char *s) { Serial.print(s); }
|
||||||
static void print(int n) { Serial.print(n); }
|
static void print(int n) { Serial.print(n); }
|
||||||
|
67
ehci.cpp
67
ehci.cpp
@ -24,6 +24,10 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "USBHost.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
|
#define PERIODIC_LIST_SIZE 32
|
||||||
|
|
||||||
static uint32_t periodictable[PERIODIC_LIST_SIZE] __attribute__ ((aligned(4096), used));
|
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) {
|
} else if (type == 3) {
|
||||||
// interrupt: add to periodic schedule
|
// interrupt: add to periodic schedule
|
||||||
// TODO: link it into the periodic table
|
add_qh_to_periodic_schedule(pipe);
|
||||||
|
|
||||||
|
|
||||||
//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);
|
|
||||||
}
|
}
|
||||||
return pipe;
|
return pipe;
|
||||||
}
|
}
|
||||||
@ -867,6 +857,53 @@ bool USBHost::allocate_interrupt_pipe_bandwidth(Pipe_t *pipe, uint32_t maxlen, u
|
|||||||
return true;
|
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)
|
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) {
|
} else if (state == numports) {
|
||||||
println("power turned on to all ports");
|
println("power turned on to all ports");
|
||||||
println("device addr = ", device->address);
|
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);
|
println("pipe cap1 = ", changepipe->qh.capabilities[0], HEX);
|
||||||
changepipe->callback_function = callback;
|
changepipe->callback_function = callback;
|
||||||
queue_Data_Transfer(changepipe, &changebits, 1, this);
|
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
|
if (size != 8) return false; // must be 8 bytes for Keyboard Boot Protocol
|
||||||
uint32_t interval = descriptors[24];
|
uint32_t interval = descriptors[24];
|
||||||
println("polling interval = ", interval);
|
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;
|
datapipe->callback_function = callback;
|
||||||
queue_Data_Transfer(datapipe, report, 8, this);
|
queue_Data_Transfer(datapipe, report, 8, this);
|
||||||
return true;
|
return true;
|
||||||
|
19
print.cpp
19
print.cpp
@ -146,6 +146,25 @@ void USBHost::print_driverlist(const char *name, const USBDriver *driver)
|
|||||||
Serial.println();
|
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)
|
void USBHost::print_hexbytes(const void *ptr, uint32_t len)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user