From 8ee6d28432a1d7e0dddfe094cd986cf32708f4a6 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Mon, 27 Feb 2017 04:17:43 -0800 Subject: [PATCH] Implement driver timers --- USBHost.h | 5 ++- ehci.cpp | 99 +++++++++++++++++++++++++++++++++---------------------- hub.cpp | 19 +++++++++++ 3 files changed, 83 insertions(+), 40 deletions(-) diff --git a/USBHost.h b/USBHost.h index 9482b9e..00437fd 100644 --- a/USBHost.h +++ b/USBHost.h @@ -258,7 +258,7 @@ protected: // When any of the USBDriverTimer objects a driver creates generates // a timer event, this function is called. - virtual void timer(USBDriverTimer &whichTimer) { } + virtual void timer_event(USBDriverTimer *whichTimer) { } // When a device disconnects from the USB, this function is called. // The driver must free all resources it allocated and update any @@ -291,6 +291,7 @@ public: void start(uint32_t microseconds); void *pointer; uint32_t integer; + uint32_t started_micros; // testing only private: USBDriver *driver; uint32_t usec; @@ -309,6 +310,7 @@ public: protected: virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len); virtual void control(const Transfer_t *transfer); + virtual void timer_event(USBDriverTimer *whichTimer); virtual void disconnect(); void poweron(uint32_t port); void getstatus(uint32_t port); @@ -320,6 +322,7 @@ protected: void update_status(); USBDriverTimer mytimer; USBDriverTimer othertimer; + USBDriverTimer mytimers[7]; setup_t setup; uint8_t hub_desc[16]; uint8_t endpoint; diff --git a/ehci.cpp b/ehci.cpp index e984923..425a431 100644 --- a/ehci.cpp +++ b/ehci.cpp @@ -324,21 +324,35 @@ void USBHost::isr() } if (stat & USBHS_USBSTS_TI1) { // timer 1 - used for USBDriverTimer println("timer1"); + USBDriverTimer *timer = active_timers; + if (timer) { + USBDriverTimer *next = timer->next; + active_timers = next; + if (next) { + // more timers scheduled + next->prev = NULL; + USBHS_GPTIMER1LD = next->usec - 1; + USBHS_GPTIMER1CTL = USBHS_GPTIMERCTL_RST | USBHS_GPTIMERCTL_RUN; + } + // TODO: call multiple timers if 0 elapsed between them? + timer->driver->timer_event(timer); // call driver's timer() + } } } void USBDriverTimer::start(uint32_t microseconds) { - Serial.print("start_timer, usec = "); - Serial.print(usec); + Serial.print("start_timer, us = "); + Serial.print(microseconds); Serial.print(", driver = "); Serial.print((uint32_t)driver, HEX); Serial.print(", this = "); Serial.println((uint32_t)this, HEX); -#if 1 if (!driver) return; if (microseconds < 100) return; // minimum timer duration + started_micros = micros(); if (active_timers == NULL) { + // schedule is empty, just add this timer usec = microseconds; next = NULL; prev = NULL; @@ -347,10 +361,47 @@ void USBDriverTimer::start(uint32_t microseconds) USBHS_GPTIMER1CTL = USBHS_GPTIMERCTL_RST | USBHS_GPTIMERCTL_RUN; return; } -#endif - // TODO, add to active_timers list - //uint32_t remain = USBHS_GPTIMER1CTL & 0xFFFFFF; - + uint32_t remain = USBHS_GPTIMER1CTL & 0xFFFFFF; + Serial.print("remain = "); + Serial.println(remain); + if (microseconds < remain) { + // this timer event is before any on the schedule + __disable_irq(); + USBHS_GPTIMER1CTL = 0; + USBHS_USBSTS = USBHS_USBSTS_TI1; // TODO: UPI & UAI safety?! + usec = microseconds; + next = active_timers; + prev = NULL; + active_timers->usec = remain - microseconds; + active_timers->prev = this; + active_timers = this; + USBHS_GPTIMER1LD = microseconds - 1; + USBHS_GPTIMER1CTL = USBHS_GPTIMERCTL_RST | USBHS_GPTIMERCTL_RUN; + __enable_irq(); + return; + } + // add this timer to the schedule, somewhere after the first timer + microseconds -= remain; + USBDriverTimer *list = active_timers; + while (list->next) { + list = list->next; + if (microseconds < list->usec) { + // add timer into middle of list + list->usec -= microseconds; + usec = microseconds; + next = list; + prev = list->prev; + list->prev = this; + prev->next = this; + return; + } + microseconds -= list->usec; + } + // add timer to the end of the schedule + usec = microseconds; + next = NULL; + prev = list; + list->next = this; } @@ -925,6 +976,7 @@ void USBHost::add_qh_to_periodic_schedule(Pipe_t *pipe) } } #endif +#if 0 println("Periodic Schedule:"); for (uint32_t i=0; i < PERIODIC_LIST_SIZE; i++) { if (i < 10) print(" "); @@ -932,6 +984,7 @@ void USBHost::add_qh_to_periodic_schedule(Pipe_t *pipe) print(": "); print_qh_list((Pipe_t *)(periodictable[i] & 0xFFFFFFE0)); } +#endif } @@ -1046,35 +1099,3 @@ void USBHost::delete_Pipe(Pipe_t *pipe) } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/hub.cpp b/hub.cpp index daf46b6..8b19302 100644 --- a/hub.cpp +++ b/hub.cpp @@ -39,8 +39,14 @@ bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t // timer testing TODO: remove this later mytimer.init(this); + mytimer.pointer = (void *)"This is mytimer"; mytimer.start(99129); + othertimer.pointer = (void *)"Hello, I'm othertimer"; othertimer.start(12345); + for (int i=0; i < 7; i++) { + mytimers[i].init(this); + //mytimers[i].start((i + 1) * 10000); + } // check for HUB type if (dev->bDeviceClass != 9 || dev->bDeviceSubClass != 0) return false; @@ -84,6 +90,19 @@ bool USBHub::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t return true; } +void USBHub::timer_event(USBDriverTimer *timer) +{ + uint32_t us = micros() - timer->started_micros; + print("timer event ("); + print(us); + print(" us): "); + print((char *)timer->pointer); + print(", this = "); + print((uint32_t)this, HEX); + println(", timer = ", (uint32_t)timer, HEX); +} + + void USBHub::poweron(uint32_t port) { mk_setup(setup, 0x23, 3, 8, port, 0);