From c98ba51e6d6206b65e622635ab6babac3dc2f72f Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Mon, 23 Jan 2017 04:47:54 -0800 Subject: [PATCH] Use interrupts instead of polling --- k66_usbhost.ino | 134 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 121 insertions(+), 13 deletions(-) diff --git a/k66_usbhost.ino b/k66_usbhost.ino index 2d3d349..682b210 100644 --- a/k66_usbhost.ino +++ b/k66_usbhost.ino @@ -9,13 +9,20 @@ uint32_t qtd_in[8] __attribute__ ((aligned(32))); uint32_t qtd_outack[8] __attribute__ ((aligned(32))); uint32_t setupbuf[2] __attribute__ ((aligned(8))); uint32_t inbuf[16] __attribute__ ((aligned(64))); - +uint8_t port_state; +#define PORT_STATE_DISCONNECTED 0 +#define PORT_STATE_DEBOUNCE 1 +#define PORT_STATE_RESET 2 +#define PORT_STATE_RECOVERY 3 +#define PORT_STATE_ACTIVE 4 void setup() { // Test board has a USB data mux (this won't be on final Teensy 3.6) pinMode(32, OUTPUT); // pin 32 = USB switch, high=connect device digitalWrite(32, LOW); + pinMode(30, OUTPUT); // pin 30 = debug info - use oscilloscope + digitalWrite(30, LOW); // Teensy 3.6 has USB host power controlled by PTE6 PORTE_PCR6 = PORT_PCR_MUX(1); GPIOE_PDDR |= (1<<6); @@ -60,17 +67,6 @@ void setup() //SIM_SOPT2 = SIM_SOPT2 & (~SIM_SOPT2_CLKOUTSEL(7)) | SIM_SOPT2_CLKOUTSEL(4); // MCGIRCLK //CORE_PIN9_CONFIG = PORT_PCR_MUX(5); // CLKOUT on PTC3 Alt5 (Arduino pin 9) -// EHCI registers page default -// -------------- ---- ------- -// USBHS_USBCMD 1599 00080000 -// USBHS_USBSTS 1602 00000000 -// USBHS_USBINTR 1606 00000000 -// USBHS_FRINDEX 1609 00000000 -// USBHS_PERIODICLISTBASE 1610 undefine -// USBHS_ASYNCLISTADDR 1612 undefine -// USBHS_PORTSC 1619 00002000 -// USBHS_USBMODE 1629 00005000 - print("begin ehci reset"); USBHS_USBCMD |= USBHS_USBCMD_RST; count = 0; @@ -102,6 +98,7 @@ void setup() qtd_dummy[5] = 0; qtd_dummy[6] = 0; qtd_dummy[7] = 0; + port_state = PORT_STATE_DISCONNECTED; // turn on the USBHS controller USBHS_USBMODE = USBHS_USBMODE_TXHSD(5) | USBHS_USBMODE_CM(3); // host mode @@ -113,6 +110,8 @@ void setup() USBHS_USBCMD_FS2 | USBHS_USBCMD_FS(0) | // periodic table is 64 pointers // USBHS_USBCMD_PSE | USBHS_USBCMD_ASE; + + //USBHS_PORTSC1 = USBHS_PORTSC_PP; USBHS_PORTSC1 |= USBHS_PORTSC_PP; //USBHS_PORTSC1 |= USBHS_PORTSC_PFSC; // force 12 Mbit/sec //USBHS_PORTSC1 |= USBHS_PORTSC_PHCD; // phy off @@ -123,8 +122,114 @@ void setup() Serial.println(USBHS_PERIODICLISTBASE, HEX); Serial.print("periodictable = "); Serial.println((uint32_t)periodictable, HEX); + + NVIC_ENABLE_IRQ(IRQ_USBHS); + USBHS_USBINTR = USBHS_USBINTR_UE | USBHS_USBINTR_PCE | USBHS_USBINTR_TIE0; + + delay(25); + Serial.println("Plug in device..."); + digitalWrite(32, HIGH); // connect device } +void pulse(int usec) +{ + // connect oscilloscope to see these pulses.... + digitalWriteFast(30, HIGH); + delayMicroseconds(usec); + digitalWriteFast(30, LOW); +} + +// EHCI registers page default +// -------------- ---- ------- +// USBHS_USBCMD 1599 00080000 USB Command +// USBHS_USBSTS 1602 00000000 USB Status +// USBHS_USBINTR 1606 00000000 USB Interrupt Enable +// USBHS_FRINDEX 1609 00000000 Frame Index Register +// USBHS_PERIODICLISTBASE 1610 undefine Periodic Frame List Base Address +// USBHS_ASYNCLISTADDR 1612 undefine Asynchronous List Address +// USBHS_PORTSC1 1619 00002000 Port Status and Control +// USBHS_USBMODE 1629 00005000 USB Mode +// USBHS_GPTIMERnCTL 1591 00000000 General Purpose Timer n Control + +// PORT_STATE_DISCONNECTED 0 +// PORT_STATE_DEBOUNCE 1 +// PORT_STATE_RESET 2 +// PORT_STATE_RECOVERY 3 +// PORT_STATE_ACTIVE 4 + +void usbhs_isr(void) // USBHS_ISR_HOST +{ + uint32_t stat = USBHS_USBSTS; + USBHS_USBSTS = stat; // clear pending interrupts + //stat &= USBHS_USBINTR; // mask away unwanted interrupts + Serial.print("isr:"); + Serial.print(stat, HEX); + Serial.println(); + + if (stat & USBHS_USBSTS_PCI) { // port change detected + const uint32_t portstat = USBHS_PORTSC1; + Serial.print("port change: "); + Serial.print(portstat, HEX); + Serial.println(); + USBHS_PORTSC1 = portstat | (USBHS_PORTSC_OCC|USBHS_PORTSC_PEC|USBHS_PORTSC_CSC); + if (portstat & USBHS_PORTSC_OCC) { + Serial.println(" overcurrent change"); + } + if (portstat & USBHS_PORTSC_CSC) { + if (portstat & USBHS_PORTSC_CCS) { + Serial.println(" connect"); + if (port_state == PORT_STATE_DISCONNECTED + || port_state == PORT_STATE_DEBOUNCE) { + // 100 ms debounce (USB 2.0: TATTDB, page 150 & 188) + port_state = PORT_STATE_DEBOUNCE; + USBHS_GPTIMER0LD = 100000; // microseconds + USBHS_GPTIMER0CTL = + USBHS_GPTIMERCTL_RST | USBHS_GPTIMERCTL_RUN; + stat &= ~USBHS_USBSTS_TI0; + } + } else { + Serial.println(" disconnect"); + port_state = PORT_STATE_DISCONNECTED; + // TODO: delete & clean up device state... + } + } + if (portstat & USBHS_PORTSC_PEC) { + // PEC bit only detects disable + Serial.println(" disable"); + } else if (port_state == PORT_STATE_RESET && portstat & USBHS_PORTSC_PE) { + Serial.println(" port enabled"); + port_state = PORT_STATE_RECOVERY; + // 10 ms reset recover (USB 2.0: TRSTRCY, page 151 & 188) + USBHS_GPTIMER0LD = 10000; // microseconds + USBHS_GPTIMER0CTL = USBHS_GPTIMERCTL_RST | USBHS_GPTIMERCTL_RUN; + + } + if (portstat & USBHS_PORTSC_FPR) { + Serial.println(" force resume"); + + } + + pulse(1); + } + if (stat & USBHS_USBSTS_TI0) { // timer 0 + Serial.println("timer"); + pulse(2); + if (port_state == PORT_STATE_DEBOUNCE) { + port_state = PORT_STATE_RESET; + USBHS_PORTSC1 |= USBHS_PORTSC_PR; // begin reset sequence + Serial.println(" begin reset"); + } else if (port_state == PORT_STATE_RECOVERY) { + port_state = PORT_STATE_ACTIVE; + Serial.println(" end recovery"); + + } + } + +} + + + + void port_status() { uint32_t n; @@ -240,11 +345,13 @@ void read_descriptor(uint16_t value, uint16_t index, uint32_t len) Serial.println(qtd_in[2], HEX); Serial.println(qtd_outack[2], HEX); Serial.println(qtd_setup[2], HEX); + } void loop() { +/* static unsigned int count=0; port_status(); @@ -265,9 +372,10 @@ void loop() if (count == 22) { read_descriptor(1, 0, 8); // device descriptor } - if (count > 5000) { + if (count > 500) { while (1) ; // stop here } +*/ } void print(const char *s)