From 46324071f07e6c4f51d555bbba4566668103498a Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Wed, 8 Feb 2017 06:35:56 -0800 Subject: [PATCH] Fix adding to follup lists while also processing them --- host.h | 3 +- k66_usbhost.ino | 154 ++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 131 insertions(+), 26 deletions(-) diff --git a/host.h b/host.h index c7b4d7e..ca9180d 100644 --- a/host.h +++ b/host.h @@ -92,11 +92,12 @@ struct Transfer_struct { } qtd; // linked list of queued, not-yet-completed transfers Transfer_t *next_followup; + Transfer_t *prev_followup; // data to be used by callback function Pipe_t *pipe; void *buffer; uint32_t length; - uint32_t unused[4]; + uint32_t unused[3]; }; void init_Device_Pipe_Transfer_memory(void); diff --git a/k66_usbhost.ino b/k66_usbhost.ino index c018cd7..0ebfc9f 100644 --- a/k66_usbhost.ino +++ b/k66_usbhost.ino @@ -192,6 +192,7 @@ void pulse(int usec) // PORT_STATE_RECOVERY 3 // PORT_STATE_ACTIVE 4 + void usbhs_isr(void) { uint32_t stat = USBHS_USBSTS; @@ -222,27 +223,37 @@ void usbhs_isr(void) if (stat & USBHS_USBSTS_UAI) { // completed qTD(s) from the async schedule Serial.println("Async Followup"); - Transfer_t *prev=NULL; + print(async_followup_first, async_followup_last); Transfer_t *p = async_followup_first; while (p) { - Transfer_t *next = p->next_followup; if (followup_Transfer(p)) { // transfer completed - if (prev) { - prev->next_followup = next; - } else { - async_followup_first = next; - } + Transfer_t *next = p->next_followup; + remove_from_async_followup_list(p); + free_Transfer(p); + p = next; } else { // transfer still pending - prev = p; + p = p->next_followup; } - p = next; } - async_followup_last = prev; + print(async_followup_first, async_followup_last); } if (stat & USBHS_USBSTS_UPI) { // completed qTD(s) from the periodic schedule - + Serial.println("Periodic Followup"); + Transfer_t *p = periodic_followup_first; + while (p) { + if (followup_Transfer(p)) { + // transfer completed + Transfer_t *next = p->next_followup; + remove_from_periodic_followup_list(p); + free_Transfer(p); + p = next; + } else { + // transfer still pending + p = p->next_followup; + } + } } if (stat & USBHS_USBSTS_PCI) { // port change detected @@ -338,6 +349,7 @@ void enumeration(const Transfer_t *transfer) break; case 1: // request all 18 bytes of device descriptor + Serial.println("TODO: request 18 byte device descriptor"); break; @@ -593,31 +605,25 @@ bool new_Transfer(Pipe_t *pipe, void *buffer, uint32_t len) // last points to transfer (which becomes new halt) last->qtd.next = (uint32_t)transfer; transfer->qtd.next = 1; - // link all the new qTD by next_followup + // link all the new qTD by next_followup & prev_followup + Transfer_t *prev = NULL; Transfer_t *p = halt; while (p->qtd.next != (uint32_t)transfer) { Transfer_t *n = (Transfer_t *)p->qtd.next; + p->prev_followup = prev; p->next_followup = n; + prev = p; p = n; } p->next_followup = NULL; + print(halt, p); // 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; + add_to_async_followup_list(halt, p); } else { // interrupt - if (periodic_followup_first == NULL) { - periodic_followup_first = halt; - } else { - periodic_followup_last->next_followup = halt; - } - periodic_followup_last = p; + add_to_periodic_followup_list(halt, p); } // old halt becomes new transfer, this commits all new qTDs to QH halt->qtd.token = token; @@ -640,12 +646,69 @@ bool followup_Transfer(Transfer_t *transfer) } // do callback function... Serial.println(" completed"); - free_Transfer(transfer); return true; } return false; } +static void add_to_async_followup_list(Transfer_t *first, Transfer_t *last) +{ + last->next_followup = NULL; // always add to end of list + if (async_followup_last == NULL) { + first->prev_followup = NULL; + async_followup_first = first; + } else { + first->prev_followup = async_followup_last; + async_followup_last->next_followup = first; + } + async_followup_last = last; +} + +static void remove_from_async_followup_list(Transfer_t *transfer) +{ + Transfer_t *next = transfer->next_followup; + Transfer_t *prev = transfer->prev_followup; + if (prev) { + prev->next_followup = next; + } else { + async_followup_first = next; + } + if (next) { + next->prev_followup = prev; + } else { + async_followup_last = prev; + } +} + +static void add_to_periodic_followup_list(Transfer_t *first, Transfer_t *last) +{ + last->next_followup = NULL; // always add to end of list + if (periodic_followup_last == NULL) { + first->prev_followup = NULL; + periodic_followup_first = first; + } else { + first->prev_followup = periodic_followup_last; + periodic_followup_last->next_followup = first; + } + periodic_followup_last = last; +} + +static void remove_from_periodic_followup_list(Transfer_t *transfer) +{ + Transfer_t *next = transfer->next_followup; + Transfer_t *prev = transfer->prev_followup; + if (prev) { + prev->next_followup = next; + } else { + periodic_followup_first = next; + } + if (next) { + next->prev_followup = prev; + } else { + periodic_followup_last = prev; + } +} + void print(const Transfer_t *transfer) { if (!((uint32_t)transfer & 0xFFFFFFE0)) return; @@ -665,6 +728,47 @@ void print(const Transfer_t *transfer) Serial.println(); } +void print(const Transfer_t *first, const Transfer_t *last) +{ + Serial.print("Transfer Followup List "); + Serial.print((uint32_t)first, HEX); + Serial.print(" to "); + Serial.println((uint32_t)last, HEX); + Serial.println(" forward:"); + while (first) { + Serial.print(" "); + Serial.print((uint32_t)first, HEX); + print_token(first->qtd.token); + first = first->next_followup; + } + Serial.println(" backward:"); + while (last) { + Serial.print(" "); + Serial.print((uint32_t)last, HEX); + print_token(last->qtd.token); + last = last->prev_followup; + } +} + +void print_token(uint32_t token) +{ + switch ((token >> 8) & 3) { + case 0: + Serial.print(" OUT "); + Serial.println((token >> 16) & 0x7FFF); + break; + case 1: + Serial.print(" IN "); + Serial.println((token >> 16) & 0x7FFF); + break; + case 2: + Serial.println(" SETUP"); + break; + default: + Serial.println(" unknown"); + } +} + void print(const Pipe_t *pipe) { if (!((uint32_t)pipe & 0xFFFFFFE0)) return;