소스 검색

Implement driver timers

main
PaulStoffregen 8 년 전
부모
커밋
8ee6d28432
3개의 변경된 파일83개의 추가작업 그리고 40개의 파일을 삭제
  1. +4
    -1
      USBHost.h
  2. +60
    -39
      ehci.cpp
  3. +19
    -0
      hub.cpp

+ 4
- 1
USBHost.h 파일 보기



// When any of the USBDriverTimer objects a driver creates generates // When any of the USBDriverTimer objects a driver creates generates
// a timer event, this function is called. // 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. // When a device disconnects from the USB, this function is called.
// The driver must free all resources it allocated and update any // The driver must free all resources it allocated and update any
void start(uint32_t microseconds); void start(uint32_t microseconds);
void *pointer; void *pointer;
uint32_t integer; uint32_t integer;
uint32_t started_micros; // testing only
private: private:
USBDriver *driver; USBDriver *driver;
uint32_t usec; uint32_t usec;
protected: protected:
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len); virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len);
virtual void control(const Transfer_t *transfer); virtual void control(const Transfer_t *transfer);
virtual void timer_event(USBDriverTimer *whichTimer);
virtual void disconnect(); virtual void disconnect();
void poweron(uint32_t port); void poweron(uint32_t port);
void getstatus(uint32_t port); void getstatus(uint32_t port);
void update_status(); void update_status();
USBDriverTimer mytimer; USBDriverTimer mytimer;
USBDriverTimer othertimer; USBDriverTimer othertimer;
USBDriverTimer mytimers[7];
setup_t setup; setup_t setup;
uint8_t hub_desc[16]; uint8_t hub_desc[16];
uint8_t endpoint; uint8_t endpoint;

+ 60
- 39
ehci.cpp 파일 보기

} }
if (stat & USBHS_USBSTS_TI1) { // timer 1 - used for USBDriverTimer if (stat & USBHS_USBSTS_TI1) { // timer 1 - used for USBDriverTimer
println("timer1"); 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) 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(", driver = ");
Serial.print((uint32_t)driver, HEX); Serial.print((uint32_t)driver, HEX);
Serial.print(", this = "); Serial.print(", this = ");
Serial.println((uint32_t)this, HEX); Serial.println((uint32_t)this, HEX);
#if 1
if (!driver) return; if (!driver) return;
if (microseconds < 100) return; // minimum timer duration if (microseconds < 100) return; // minimum timer duration
started_micros = micros();
if (active_timers == NULL) { if (active_timers == NULL) {
// schedule is empty, just add this timer
usec = microseconds; usec = microseconds;
next = NULL; next = NULL;
prev = NULL; prev = NULL;
USBHS_GPTIMER1CTL = USBHS_GPTIMERCTL_RST | USBHS_GPTIMERCTL_RUN; USBHS_GPTIMER1CTL = USBHS_GPTIMERCTL_RST | USBHS_GPTIMERCTL_RUN;
return; 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;
} }




} }
} }
#endif #endif
#if 0
println("Periodic Schedule:"); println("Periodic Schedule:");
for (uint32_t i=0; i < PERIODIC_LIST_SIZE; i++) { for (uint32_t i=0; i < PERIODIC_LIST_SIZE; i++) {
if (i < 10) print(" "); if (i < 10) print(" ");
print(": "); print(": ");
print_qh_list((Pipe_t *)(periodictable[i] & 0xFFFFFFE0)); print_qh_list((Pipe_t *)(periodictable[i] & 0xFFFFFFE0));
} }
#endif
} }




} }





































+ 19
- 0
hub.cpp 파일 보기



// timer testing TODO: remove this later // timer testing TODO: remove this later
mytimer.init(this); mytimer.init(this);
mytimer.pointer = (void *)"This is mytimer";
mytimer.start(99129); mytimer.start(99129);
othertimer.pointer = (void *)"Hello, I'm othertimer";
othertimer.start(12345); othertimer.start(12345);
for (int i=0; i < 7; i++) {
mytimers[i].init(this);
//mytimers[i].start((i + 1) * 10000);
}


// check for HUB type // check for HUB type
if (dev->bDeviceClass != 9 || dev->bDeviceSubClass != 0) return false; if (dev->bDeviceClass != 9 || dev->bDeviceSubClass != 0) return false;
return true; 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) void USBHub::poweron(uint32_t port)
{ {
mk_setup(setup, 0x23, 3, 8, port, 0); mk_setup(setup, 0x23, 3, 8, port, 0);

Loading…
취소
저장