Browse Source

FTDI transmit, add partial packet output

main
PaulStoffregen 7 years ago
parent
commit
5575f9fcae
3 changed files with 96 additions and 26 deletions
  1. +4
    -1
      USBHost_t36.h
  2. +33
    -0
      ehci.cpp
  3. +59
    -25
      serial.cpp

+ 4
- 1
USBHost_t36.h View File

@@ -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];

+ 33
- 0
ehci.cpp View File

@@ -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,

+ 59
- 25
serial.cpp View File

@@ -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;
}


























Loading…
Cancel
Save