mirror of
https://github.com/gdsports/USBHost_t36
synced 2024-11-25 10:32:16 -05:00
Add qTD followup lists
This commit is contained in:
parent
897cf23bf3
commit
33151ad6cf
3
host.h
3
host.h
@ -66,7 +66,8 @@ struct Transfer_struct {
|
|||||||
Pipe_t *pipe;
|
Pipe_t *pipe;
|
||||||
void *callback;
|
void *callback;
|
||||||
void *callback_arg;
|
void *callback_arg;
|
||||||
uint32_t unused[5];
|
Transfer_t *next_followup;
|
||||||
|
uint32_t unused[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
Device_t * allocate_Device(void);
|
Device_t * allocate_Device(void);
|
||||||
|
@ -10,6 +10,10 @@ uint8_t port_state;
|
|||||||
#define PORT_STATE_RECOVERY 3
|
#define PORT_STATE_RECOVERY 3
|
||||||
#define PORT_STATE_ACTIVE 4
|
#define PORT_STATE_ACTIVE 4
|
||||||
Device_t *rootdev=NULL;
|
Device_t *rootdev=NULL;
|
||||||
|
Transfer_t *async_followup_first=NULL;
|
||||||
|
Transfer_t *async_followup_last=NULL;
|
||||||
|
Transfer_t *periodic_followup_first=NULL;
|
||||||
|
Transfer_t *periodic_followup_last=NULL;
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
@ -110,9 +114,10 @@ void setup()
|
|||||||
Serial.println((uint32_t)periodictable, HEX);
|
Serial.println((uint32_t)periodictable, HEX);
|
||||||
|
|
||||||
NVIC_ENABLE_IRQ(IRQ_USBHS);
|
NVIC_ENABLE_IRQ(IRQ_USBHS);
|
||||||
USBHS_USBINTR = USBHS_USBINTR_UE | USBHS_USBINTR_PCE | USBHS_USBINTR_TIE0;
|
USBHS_USBINTR = USBHS_USBINTR_PCE | USBHS_USBINTR_TIE0;
|
||||||
USBHS_USBINTR |= USBHS_USBINTR_UEE | USBHS_USBINTR_SEE;
|
USBHS_USBINTR |= USBHS_USBINTR_UEE | USBHS_USBINTR_SEE;
|
||||||
USBHS_USBINTR |= USBHS_USBINTR_AAE;
|
USBHS_USBINTR |= USBHS_USBINTR_AAE;
|
||||||
|
USBHS_USBINTR |= USBHS_USBINTR_UPIE | USBHS_USBINTR_UAIE;
|
||||||
|
|
||||||
delay(25);
|
delay(25);
|
||||||
Serial.println("Plug in device...");
|
Serial.println("Plug in device...");
|
||||||
@ -185,6 +190,35 @@ void usbhs_isr(void)
|
|||||||
if (stat & USBHS_USBSTS_TI0) Serial.println(" Timer0");
|
if (stat & USBHS_USBSTS_TI0) Serial.println(" Timer0");
|
||||||
if (stat & USBHS_USBSTS_TI1) Serial.println(" Timer1");
|
if (stat & USBHS_USBSTS_TI1) Serial.println(" Timer1");
|
||||||
|
|
||||||
|
if (stat & USBHS_USBSTS_UAI) {
|
||||||
|
Serial.println("Async Followup");
|
||||||
|
|
||||||
|
Transfer_t *p, *prev=NULL, *next;
|
||||||
|
|
||||||
|
p = async_followup_first;
|
||||||
|
while (p) {
|
||||||
|
|
||||||
|
next = p->next_followup;
|
||||||
|
if (followup_Transfer(p)) {
|
||||||
|
// transfer completed
|
||||||
|
if (prev) {
|
||||||
|
prev->next_followup = next;
|
||||||
|
} else {
|
||||||
|
async_followup_first = next;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// transfer still pending
|
||||||
|
prev = p;
|
||||||
|
}
|
||||||
|
p = next;
|
||||||
|
}
|
||||||
|
async_followup_last = prev;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (stat & USBHS_USBSTS_UPI) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (stat & USBHS_USBSTS_PCI) { // port change detected
|
if (stat & USBHS_USBSTS_PCI) { // port change detected
|
||||||
const uint32_t portstat = USBHS_PORTSC1;
|
const uint32_t portstat = USBHS_PORTSC1;
|
||||||
Serial.print("port change: ");
|
Serial.print("port change: ");
|
||||||
@ -388,6 +422,7 @@ void init_qTD(volatile Transfer_t *t, void *buf, uint32_t len,
|
|||||||
t->qtd.buffer[4] = addr + 0x4000;
|
t->qtd.buffer[4] = addr + 0x4000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create a Transfer and queue it
|
// Create a Transfer and queue it
|
||||||
//
|
//
|
||||||
bool new_Transfer(Pipe_t *pipe, void *buffer, uint32_t len)
|
bool new_Transfer(Pipe_t *pipe, void *buffer, uint32_t len)
|
||||||
@ -436,10 +471,14 @@ bool new_Transfer(Pipe_t *pipe, void *buffer, uint32_t len)
|
|||||||
free_Transfer(transfer);
|
free_Transfer(transfer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// find halt qTD
|
||||||
Transfer_t *halt = (Transfer_t *)(pipe->qh.next);
|
Transfer_t *halt = (Transfer_t *)(pipe->qh.next);
|
||||||
while (!(halt->qtd.token & 0x40)) halt = (Transfer_t *)(halt->qtd.next);
|
while (!(halt->qtd.token & 0x40)) halt = (Transfer_t *)(halt->qtd.next);
|
||||||
|
// transfer's token
|
||||||
uint32_t token = transfer->qtd.token;
|
uint32_t token = transfer->qtd.token;
|
||||||
transfer->qtd.token = 0x40; // transfer becomes new halt qTD
|
// transfer becomes new halt qTD
|
||||||
|
transfer->qtd.token = 0x40;
|
||||||
|
// copy transfer non-token fields to halt
|
||||||
halt->qtd.next = transfer->qtd.next;
|
halt->qtd.next = transfer->qtd.next;
|
||||||
halt->qtd.alt_next = transfer->qtd.alt_next;
|
halt->qtd.alt_next = transfer->qtd.alt_next;
|
||||||
halt->qtd.buffer[0] = transfer->qtd.buffer[0];
|
halt->qtd.buffer[0] = transfer->qtd.buffer[0];
|
||||||
@ -448,14 +487,58 @@ bool new_Transfer(Pipe_t *pipe, void *buffer, uint32_t len)
|
|||||||
halt->qtd.buffer[3] = transfer->qtd.buffer[3];
|
halt->qtd.buffer[3] = transfer->qtd.buffer[3];
|
||||||
halt->qtd.buffer[4] = transfer->qtd.buffer[4];
|
halt->qtd.buffer[4] = transfer->qtd.buffer[4];
|
||||||
halt->pipe = pipe;
|
halt->pipe = pipe;
|
||||||
Transfer_t *last = transfer;
|
// find the last qTD we're adding
|
||||||
|
Transfer_t *last = halt;
|
||||||
while ((uint32_t)(last->qtd.next) != 1) last = (Transfer_t *)(last->qtd.next);
|
while ((uint32_t)(last->qtd.next) != 1) last = (Transfer_t *)(last->qtd.next);
|
||||||
|
// last points to transfer (which becomes new halt)
|
||||||
last->qtd.next = (uint32_t)transfer;
|
last->qtd.next = (uint32_t)transfer;
|
||||||
transfer->qtd.next = 1;
|
transfer->qtd.next = 1;
|
||||||
halt->qtd.token = token; // old halt becomes new transfer
|
// link all the new qTD by next_followup
|
||||||
|
Transfer_t *p = halt;
|
||||||
|
while (p->qtd.next != (uint32_t)transfer) {
|
||||||
|
Transfer_t *n = (Transfer_t *)p->qtd.next;
|
||||||
|
p->next_followup = n;
|
||||||
|
p = n;
|
||||||
|
}
|
||||||
|
p->next_followup = NULL;
|
||||||
|
// add them to a followup list
|
||||||
|
if (pipe->type == 0 || pipe->type == 2) {
|
||||||
|
// control or bulk
|
||||||
|
if (async_followup_first == NULL) {
|
||||||
|
async_followup_first = halt;
|
||||||
|
} else {
|
||||||
|
async_followup_last->next_followup = halt;
|
||||||
|
}
|
||||||
|
async_followup_last = p;
|
||||||
|
} else {
|
||||||
|
// interrupt
|
||||||
|
if (periodic_followup_first == NULL) {
|
||||||
|
periodic_followup_first = halt;
|
||||||
|
} else {
|
||||||
|
periodic_followup_last->next_followup = halt;
|
||||||
|
}
|
||||||
|
periodic_followup_last = p;
|
||||||
|
}
|
||||||
|
// old halt becomes new transfer, this commits all new qTDs to QH
|
||||||
|
halt->qtd.token = token;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool followup_Transfer(Transfer_t *transfer)
|
||||||
|
{
|
||||||
|
Serial.print(" Followup ");
|
||||||
|
Serial.println((uint32_t)transfer, HEX);
|
||||||
|
|
||||||
|
if (!(transfer->qtd.token & 0x80)) {
|
||||||
|
// TODO: check error status
|
||||||
|
// do callback function...
|
||||||
|
Serial.println(" completed");
|
||||||
|
free_Transfer(transfer);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void print(const Transfer_t *transfer)
|
void print(const Transfer_t *transfer)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user