From 5575f9fcae5ae593c7593801ab5f98debfd8f152 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Sun, 15 Oct 2017 04:28:07 -0700 Subject: [PATCH] FTDI transmit, add partial packet output --- USBHost_t36.h | 5 ++- ehci.cpp | 33 +++++++++++++++++++ serial.cpp | 88 +++++++++++++++++++++++++++++++++++---------------- 3 files changed, 98 insertions(+), 28 deletions(-) diff --git a/USBHost_t36.h b/USBHost_t36.h index c127cdb..816af86 100644 --- a/USBHost_t36.h +++ b/USBHost_t36.h @@ -391,6 +391,7 @@ public: USBDriverTimer(USBDriver *d) : driver(d) { } void init(USBDriver *d) { driver = d; }; void start(uint32_t microseconds); + void stop(); void *pointer; uint32_t integer; uint32_t started_micros; // testing only @@ -747,7 +748,7 @@ private: class USBSerial: public USBDriver, public Stream { public: enum { BUFFER_SIZE = 390 }; // must hold at least 6 max size packets, plus 2 extra bytes - USBSerial(USBHost &host) { init(); } + USBSerial(USBHost &host) : txtimer(this) { init(); } void begin(uint32_t baud, uint32_t format=0); void end(void); virtual int available(void); @@ -760,6 +761,7 @@ 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 disconnect(); + virtual void timer_event(USBDriverTimer *whichTimer); private: static void rx_callback(const Transfer_t *transfer); static void tx_callback(const Transfer_t *transfer); @@ -772,6 +774,7 @@ private: private: Pipe_t mypipes[3] __attribute__ ((aligned(32))); Transfer_t mytransfers[7] __attribute__ ((aligned(32))); + USBDriverTimer txtimer; uint32_t bigbuffer[(BUFFER_SIZE+3)/4]; setup_t setup; uint8_t setupdata[8]; diff --git a/ehci.cpp b/ehci.cpp index 153e819..8ce74d8 100644 --- a/ehci.cpp +++ b/ehci.cpp @@ -457,6 +457,39 @@ void USBDriverTimer::start(uint32_t microseconds) list->next = this; } +void USBDriverTimer::stop() +{ + __disable_irq(); + if (active_timers) { + if (active_timers == this) { + USBHS_GPTIMER1CTL = 0; + if (next) { + uint32_t usec_til_next = USBHS_GPTIMER1CTL & 0xFFFFFF; + usec_til_next += next->usec; + next->usec = usec_til_next; + USBHS_GPTIMER1LD = usec_til_next; + USBHS_GPTIMER1CTL = USBHS_GPTIMERCTL_RST | USBHS_GPTIMERCTL_RUN; + next->prev = NULL; + active_timers = next; + } else { + active_timers = NULL; + } + } else { + for (USBDriverTimer *t = active_timers->next; t; t = t->next) { + if (t == this) { + t->prev->next = t->next; + if (t->next) { + t->next->usec += t->usec; + t->next->prev = t->prev; + } + break; + } + } + } + } + __enable_irq(); +} + static uint32_t QH_capabilities1(uint32_t nak_count_reload, uint32_t control_endpoint_flag, uint32_t max_packet_length, uint32_t head_of_list, uint32_t data_toggle_control, diff --git a/serial.cpp b/serial.cpp index 3d12567..075c19e 100644 --- a/serial.cpp +++ b/serial.cpp @@ -28,6 +28,11 @@ #define print USBHost::print #define println USBHost::println + +/************************************************************/ +// Initialization and claiming of devices & interfaces +/************************************************************/ + void USBSerial::init() { contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); @@ -135,6 +140,9 @@ void USBSerial::disconnect() } +/************************************************************/ +// Control Transfer For Configuration +/************************************************************/ void USBSerial::control(const Transfer_t *transfer) @@ -177,6 +185,11 @@ void USBSerial::control(const Transfer_t *transfer) } } + +/************************************************************/ +// Interrupt-based Data Movement +/************************************************************/ + void USBSerial::rx_callback(const Transfer_t *transfer) { if (!transfer->driver) return; @@ -281,14 +294,54 @@ void USBSerial::tx_data(const Transfer_t *transfer) println("tx2:"); txstate &= 0xFD; } - // TODO: anything need to be done with latency timeout? +} + + +void USBSerial::timer_event(USBDriverTimer *whichTimer) +{ + println("txtimer"); + uint32_t count; + uint32_t head = txhead; + uint32_t tail = txtail; + if (head == tail) { + return; // nothing to transmit + } else if (head > tail) { + count = head - tail; + } else { + count = txsize + head - tail; + } + uint8_t *p; + if ((txstate & 0x01) == 0) { + p = tx1; + txstate |= 0x01; + } else if ((txstate & 0x02) == 0) { + p = tx2; + txstate |= 0x02; + } else { + txtimer.start(1200); + return; // no outgoing buffers available, try again later + } + if (++tail >= txsize) tail = 0; + uint32_t n = txsize - tail; + if (n > count) n = count; + memcpy(p, txbuf + tail, n); + if (n >= count) { + tail += n - 1; + if (tail >= txsize) tail = 0; + } else { + uint32_t len = count - n; + memcpy(p + n, txbuf, len); + tail = len - 1; + } + txtail = tail; + queue_Data_Transfer(txpipe, p, count, this); } - - - +/************************************************************/ +// User Functions - must disable USBHQ IRQ for EHCI access +/************************************************************/ void USBSerial::begin(uint32_t baud, uint32_t format) { @@ -301,6 +354,7 @@ void USBSerial::begin(uint32_t baud, uint32_t format) void USBSerial::end(void) { + // TODO: lower DTR } int USBSerial::available(void) @@ -407,32 +461,12 @@ size_t USBSerial::write(uint8_t c) return 1; } } - // TODO: otherwise set a latency timer to transmit partial packet + // otherwise, set a latency timer to later transmit partial packet + txtimer.stop(); + txtimer.start(3500); NVIC_ENABLE_IRQ(IRQ_USBHS); return 1; } - - - - - - - - - - - - - - - - - - - - - -