diff --git a/Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/USB_HOST_SHIELD/USB_HOST_SHIELD_INLINE.h b/Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/USB_HOST_SHIELD/USB_HOST_SHIELD_INLINE.h index 6cfc0152d0..57352a3518 100644 --- a/Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/USB_HOST_SHIELD/USB_HOST_SHIELD_INLINE.h +++ b/Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/USB_HOST_SHIELD/USB_HOST_SHIELD_INLINE.h @@ -1,270 +1,272 @@ -/* Copyright (C) 2015-2016 Andrew J. Kroll - and -Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. - -This software may be distributed and modified under the terms of the GNU -General Public License version 2 (GPL2) as publishe7d by the Free Software -Foundation and appearing in the file GPL2.TXT included in the packaging of -this file. Please note that GPL2 Section 2[b] requires that all works based -on this software must also be made publicly available under the terms of -the GPL2 ("Copyleft"). - -Contact information -------------------- - -Circuits At Home, LTD -Web : https://www.circuitsathome.com -e-mail : support@circuitsathome.com +/* + * Copyright (C) 2015-2016 Andrew J. Kroll + * and + * Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + * + * This software may be distributed and modified under the terms of the GNU + * General Public License version 2 (GPL2) as publishe7d by the Free Software + * Foundation and appearing in the file GPL2.TXT included in the packaging of + * this file. Please note that GPL2 Section 2[b] requires that all works based + * on this software must also be made publicly available under the terms of + * the GPL2 ("Copyleft"). + * + * Contact information + * ------------------- + * + * Circuits At Home, LTD + * Web : https://www.circuitsathome.com + * e-mail : support@circuitsathome.com + * */ #if defined(USB_HOST_SHIELD_H) && !defined(USB_HOST_SHIELD_LOADED) #define USB_HOST_SHIELD_LOADED + #include #ifndef digitalPinToInterrupt -#error digitalPinToInterrupt not defined, complain to your board maintainer. + #error digitalPinToInterrupt not defined, complain to your board maintainer. #endif #if USB_HOST_SHIELD_USE_ISR -// allow two slots. this makes the maximum allowed shield count TWO -// for AVRs this is limited to pins 2 and 3 ONLY -// for all other boards, one odd and one even pin number is allowed. -static MAX3421E_HOST *ISReven; -static MAX3421E_HOST *ISRodd; + // allow two slots. this makes the maximum allowed shield count TWO + // for AVRs this is limited to pins 2 and 3 ONLY + // for all other boards, one odd and one even pin number is allowed. + static MAX3421E_HOST *ISReven; + static MAX3421E_HOST *ISRodd; -static void UHS_NI call_ISReven() { - ISReven->ISRTask(); -} + static void UHS_NI call_ISReven() { + ISReven->ISRTask(); + } -static void UHS_NI call_ISRodd() { - UHS_PIN_WRITE(LED_BUILTIN, HIGH); - ISRodd->ISRTask(); -} + static void UHS_NI call_ISRodd() { + UHS_PIN_WRITE(LED_BUILTIN, HIGH); + ISRodd->ISRTask(); + } #endif void UHS_NI MAX3421E_HOST::resume_host() { - // Used on MCU that lack control of IRQ priority (AVR). - // Resumes ISRs. - // NOTE: you must track the state yourself! -#ifdef __AVR__ - noInterrupts(); - if(irq_pin & 1) { - ISRodd = this; - attachInterrupt(UHS_GET_DPI(irq_pin), call_ISRodd, IRQ_SENSE); - } else { - ISReven = this; - attachInterrupt(UHS_GET_DPI(irq_pin), call_ISReven, IRQ_SENSE); - } - interrupts(); -#endif - + // Used on MCU that lack control of IRQ priority (AVR). + // Resumes ISRs. + // NOTE: you must track the state yourself! + #ifdef __AVR__ + noInterrupts(); + if (irq_pin & 1) { + ISRodd = this; + attachInterrupt(UHS_GET_DPI(irq_pin), call_ISRodd, IRQ_SENSE); + } else { + ISReven = this; + attachInterrupt(UHS_GET_DPI(irq_pin), call_ISReven, IRQ_SENSE); + } + interrupts(); + #endif } + /* write single byte into MAX3421e register */ void UHS_NI MAX3421E_HOST::regWr(uint8_t reg, uint8_t data) { - SPIclass.beginTransaction(MAX3421E_SPI_Settings); - MARLIN_UHS_WRITE_SS(LOW); - SPIclass.transfer(reg | 0x02); - SPIclass.transfer(data); - MARLIN_UHS_WRITE_SS(HIGH); - SPIclass.endTransaction(); + SPIclass.beginTransaction(MAX3421E_SPI_Settings); + MARLIN_UHS_WRITE_SS(LOW); + SPIclass.transfer(reg | 0x02); + SPIclass.transfer(data); + MARLIN_UHS_WRITE_SS(HIGH); + SPIclass.endTransaction(); } - /* multiple-byte write */ /* returns a pointer to memory position after last written */ uint8_t* UHS_NI MAX3421E_HOST::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t *data_p) { - SPIclass.beginTransaction(MAX3421E_SPI_Settings); - MARLIN_UHS_WRITE_SS(LOW); - SPIclass.transfer(reg | 0x02); - //printf("%2.2x :", reg); + SPIclass.beginTransaction(MAX3421E_SPI_Settings); + MARLIN_UHS_WRITE_SS(LOW); + SPIclass.transfer(reg | 0x02); + //printf("%2.2x :", reg); - while(nbytes) { - SPIclass.transfer(*data_p); - //printf("%2.2x ", *data_p); - nbytes--; - data_p++; // advance data pointer - } - MARLIN_UHS_WRITE_SS(HIGH); - SPIclass.endTransaction(); - //printf("\r\n"); - return (data_p); + while (nbytes) { + SPIclass.transfer(*data_p); + //printf("%2.2x ", *data_p); + nbytes--; + data_p++; // advance data pointer + } + MARLIN_UHS_WRITE_SS(HIGH); + SPIclass.endTransaction(); + //printf("\r\n"); + return (data_p); } + /* GPIO write */ /*GPIO byte is split between 2 registers, so two writes are needed to write one byte */ /* GPOUT bits are in the low nybble. 0-3 in IOPINS1, 4-7 in IOPINS2 */ void UHS_NI MAX3421E_HOST::gpioWr(uint8_t data) { - regWr(rIOPINS1, data); - data >>= 4; - regWr(rIOPINS2, data); - return; + regWr(rIOPINS1, data); + data >>= 4; + regWr(rIOPINS2, data); + return; } /* single host register read */ uint8_t UHS_NI MAX3421E_HOST::regRd(uint8_t reg) { - SPIclass.beginTransaction(MAX3421E_SPI_Settings); - MARLIN_UHS_WRITE_SS(LOW); - SPIclass.transfer(reg); - uint8_t rv = SPIclass.transfer(0); - MARLIN_UHS_WRITE_SS(HIGH); - SPIclass.endTransaction(); - return (rv); + SPIclass.beginTransaction(MAX3421E_SPI_Settings); + MARLIN_UHS_WRITE_SS(LOW); + SPIclass.transfer(reg); + uint8_t rv = SPIclass.transfer(0); + MARLIN_UHS_WRITE_SS(HIGH); + SPIclass.endTransaction(); + return (rv); } /* multiple-byte register read */ /* returns a pointer to a memory position after last read */ uint8_t* UHS_NI MAX3421E_HOST::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t *data_p) { - SPIclass.beginTransaction(MAX3421E_SPI_Settings); - MARLIN_UHS_WRITE_SS(LOW); - SPIclass.transfer(reg); - while(nbytes) { - *data_p++ = SPIclass.transfer(0); - nbytes--; - } - MARLIN_UHS_WRITE_SS(HIGH); - SPIclass.endTransaction(); - return ( data_p); + SPIclass.beginTransaction(MAX3421E_SPI_Settings); + MARLIN_UHS_WRITE_SS(LOW); + SPIclass.transfer(reg); + while (nbytes) { + *data_p++ = SPIclass.transfer(0); + nbytes--; + } + MARLIN_UHS_WRITE_SS(HIGH); + SPIclass.endTransaction(); + return ( data_p); } /* GPIO read. See gpioWr for explanation */ /* GPIN pins are in high nybbles of IOPINS1, IOPINS2 */ uint8_t UHS_NI MAX3421E_HOST::gpioRd() { - uint8_t gpin = 0; - gpin = regRd(rIOPINS2); //pins 4-7 - gpin &= 0xF0; //clean lower nybble - gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation. - return ( gpin); + uint8_t gpin = 0; + gpin = regRd(rIOPINS2); // pins 4-7 + gpin &= 0xF0; // clean lower nybble + gpin |= (regRd(rIOPINS1) >> 4); // shift low bits and OR with upper from previous operation. + return (gpin); } /* reset MAX3421E. Returns number of microseconds it took for PLL to stabilize after reset - or zero if PLL haven't stabilized in 65535 cycles */ +or zero if PLL haven't stabilized in 65535 cycles */ uint16_t UHS_NI MAX3421E_HOST::reset() { - uint16_t i = 0; + uint16_t i = 0; - // Initiate chip reset - regWr(rUSBCTL, bmCHIPRES); - regWr(rUSBCTL, 0x00); + // Initiate chip reset + regWr(rUSBCTL, bmCHIPRES); + regWr(rUSBCTL, 0x00); - int32_t now; - uint32_t expires = micros() + 65535; + int32_t now; + uint32_t expires = micros() + 65535; - // Enable full-duplex SPI so we can read rUSBIRQ - regWr(rPINCTL, bmFDUPSPI); - while((int32_t)(micros() - expires) < 0L) { - if((regRd(rUSBIRQ) & bmOSCOKIRQ)) { - break; - } - } - now = (int32_t)(micros() - expires); - if(now < 0L) { - i = 65535 + now; // Note this subtracts, as now is negative - } - return (i); + // Enable full-duplex SPI so we can read rUSBIRQ + regWr(rPINCTL, bmFDUPSPI); + while ((int32_t)(micros() - expires) < 0L) { + if ((regRd(rUSBIRQ) & bmOSCOKIRQ)) { + break; + } + } + now = (int32_t)(micros() - expires); + if (now < 0L) { + i = 65535 + now; // Note this subtracts, as now is negative + } + return (i); } void UHS_NI MAX3421E_HOST::VBUS_changed() { - /* modify USB task state because Vbus changed or unknown */ - uint8_t speed = 1; - //printf("\r\n\r\n\r\n\r\nSTATE %2.2x -> ", usb_task_state); - switch(vbusState) { - case LSHOST: // Low speed - - speed = 0; - // Intentional fall-through - case FSHOST: // Full speed - // Start device initialization if we are not initializing - // Resets to the device cause an IRQ - // usb_task_state == UHS_USB_HOST_STATE_RESET_NOT_COMPLETE; - //if((usb_task_state & UHS_USB_HOST_STATE_MASK) != UHS_USB_HOST_STATE_DETACHED) { - ReleaseChildren(); - if(!doingreset) { - if(usb_task_state == UHS_USB_HOST_STATE_RESET_NOT_COMPLETE) { - usb_task_state = UHS_USB_HOST_STATE_WAIT_BUS_READY; - } else if(usb_task_state != UHS_USB_HOST_STATE_WAIT_BUS_READY) { - usb_task_state = UHS_USB_HOST_STATE_DEBOUNCE; - } - } - sof_countdown = 0; - break; - case SE1: //illegal state - sof_countdown = 0; - doingreset = false; - ReleaseChildren(); - usb_task_state = UHS_USB_HOST_STATE_ILLEGAL; - break; - case SE0: //disconnected - default: - sof_countdown = 0; - doingreset = false; - ReleaseChildren(); - usb_task_state = UHS_USB_HOST_STATE_IDLE; - break; + /* modify USB task state because Vbus changed or unknown */ + uint8_t speed = 1; + //printf("\r\n\r\n\r\n\r\nSTATE %2.2x -> ", usb_task_state); + switch (vbusState) { + case LSHOST: // Low speed + speed = 0; + // Intentional fall-through + case FSHOST: // Full speed + // Start device initialization if we are not initializing + // Resets to the device cause an IRQ + // usb_task_state == UHS_USB_HOST_STATE_RESET_NOT_COMPLETE; + //if ((usb_task_state & UHS_USB_HOST_STATE_MASK) != UHS_USB_HOST_STATE_DETACHED) { + ReleaseChildren(); + if (!doingreset) { + if (usb_task_state == UHS_USB_HOST_STATE_RESET_NOT_COMPLETE) { + usb_task_state = UHS_USB_HOST_STATE_WAIT_BUS_READY; + } else if (usb_task_state != UHS_USB_HOST_STATE_WAIT_BUS_READY) { + usb_task_state = UHS_USB_HOST_STATE_DEBOUNCE; } - usb_host_speed = speed; - //printf("0x%2.2x\r\n\r\n\r\n\r\n", usb_task_state); - return; -}; + } + sof_countdown = 0; + break; + case SE1: // illegal state + sof_countdown = 0; + doingreset = false; + ReleaseChildren(); + usb_task_state = UHS_USB_HOST_STATE_ILLEGAL; + break; + case SE0: // disconnected + default: + sof_countdown = 0; + doingreset = false; + ReleaseChildren(); + usb_task_state = UHS_USB_HOST_STATE_IDLE; + break; + } + usb_host_speed = speed; + //printf("0x%2.2x\r\n\r\n\r\n\r\n", usb_task_state); + return; +} /** - * Probe bus to determine device presence and speed, - * then switch host to detected speed. + * Probe bus to determine device presence and speed, + * then switch host to detected speed. */ void UHS_NI MAX3421E_HOST::busprobe() { - uint8_t bus_sample; - uint8_t tmpdata; - bus_sample = regRd(rHRSL); //Get J,K status - bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte - switch(bus_sample) { //start full-speed or low-speed host - case(bmJSTATUS): - // Serial.println("J"); - if((regRd(rMODE) & bmLOWSPEED) == 0) { - regWr(rMODE, MODE_FS_HOST); // start full-speed host - vbusState = FSHOST; - } else { - regWr(rMODE, MODE_LS_HOST); // start low-speed host - vbusState = LSHOST; - } - #ifdef USB_HOST_MANUAL_POLL - enable_frame_irq(true); - #endif - tmpdata = regRd(rMODE) | bmSOFKAENAB; // start SOF generation - regWr(rHIRQ, bmFRAMEIRQ); // see data sheet. - regWr(rMODE, tmpdata); - break; - case(bmKSTATUS): - // Serial.println("K"); - if((regRd(rMODE) & bmLOWSPEED) == 0) { - regWr(rMODE, MODE_LS_HOST); // start low-speed host - vbusState = LSHOST; - } else { - regWr(rMODE, MODE_FS_HOST); // start full-speed host - vbusState = FSHOST; - } - #ifdef USB_HOST_MANUAL_POLL - enable_frame_irq(true); - #endif - tmpdata = regRd(rMODE) | bmSOFKAENAB; // start SOF generation - regWr(rHIRQ, bmFRAMEIRQ); // see data sheet. - regWr(rMODE, tmpdata); - break; - case(bmSE1): //illegal state - // Serial.println("I"); - regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); - vbusState = SE1; - // sofevent = false; - break; - case(bmSE0): //disconnected state - // Serial.println("D"); - regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); - vbusState = SE0; - // sofevent = false; - break; - }//end switch( bus_sample ) + uint8_t bus_sample; + uint8_t tmpdata; + bus_sample = regRd(rHRSL); // Get J,K status + bus_sample &= (bmJSTATUS | bmKSTATUS); // zero the rest of the byte + switch (bus_sample) { // start full-speed or low-speed host + case bmJSTATUS: + // Serial.println("J"); + if ((regRd(rMODE) & bmLOWSPEED) == 0) { + regWr(rMODE, MODE_FS_HOST); // start full-speed host + vbusState = FSHOST; + } else { + regWr(rMODE, MODE_LS_HOST); // start low-speed host + vbusState = LSHOST; + } + #ifdef USB_HOST_MANUAL_POLL + enable_frame_irq(true); + #endif + tmpdata = regRd(rMODE) | bmSOFKAENAB; // start SOF generation + regWr(rHIRQ, bmFRAMEIRQ); // see data sheet. + regWr(rMODE, tmpdata); + break; + case bmKSTATUS: + // Serial.println("K"); + if ((regRd(rMODE) & bmLOWSPEED) == 0) { + regWr(rMODE, MODE_LS_HOST); // start low-speed host + vbusState = LSHOST; + } else { + regWr(rMODE, MODE_FS_HOST); // start full-speed host + vbusState = FSHOST; + } + #ifdef USB_HOST_MANUAL_POLL + enable_frame_irq(true); + #endif + tmpdata = regRd(rMODE) | bmSOFKAENAB; // start SOF generation + regWr(rHIRQ, bmFRAMEIRQ); // see data sheet. + regWr(rMODE, tmpdata); + break; + case bmSE1: // illegal state + // Serial.println("I"); + regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); + vbusState = SE1; + // sofevent = false; + break; + case bmSE0: // disconnected state + // Serial.println("D"); + regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); + vbusState = SE0; + // sofevent = false; + break; + } // end switch ( bus_sample ) } /** @@ -274,146 +276,145 @@ void UHS_NI MAX3421E_HOST::busprobe() { * @return 0 on success, -1 on error */ int16_t UHS_NI MAX3421E_HOST::Init(int16_t mseconds) { - usb_task_state = UHS_USB_HOST_STATE_INITIALIZE; //set up state machine - // Serial.print("MAX3421E 'this' USB Host @ 0x"); - // Serial.println((uint32_t)this, HEX); - // Serial.print("MAX3421E 'this' USB Host Address Pool @ 0x"); - // Serial.println((uint32_t)GetAddressPool(), HEX); - Init_dyn_SWI(); - UHS_printf_HELPER_init(); - noInterrupts(); -#ifdef ARDUINO_AVR_ADK - // For Mega ADK, which has a Max3421e on-board, - // set MAX_RESET to output mode, and then set it to HIGH - // PORTJ bit 2 - if(irq_pin == 54) { - DDRJ |= 0x04; // output - PORTJ |= 0x04; // HIGH + usb_task_state = UHS_USB_HOST_STATE_INITIALIZE; //set up state machine + //Serial.print("MAX3421E 'this' USB Host @ 0x"); + //Serial.println((uint32_t)this, HEX); + //Serial.print("MAX3421E 'this' USB Host Address Pool @ 0x"); + //Serial.println((uint32_t)GetAddressPool(), HEX); + Init_dyn_SWI(); + UHS_printf_HELPER_init(); + noInterrupts(); + #ifdef ARDUINO_AVR_ADK + // For Mega ADK, which has a Max3421e on-board, + // set MAX_RESET to output mode, and then set it to HIGH + // PORTJ bit 2 + if (irq_pin == 54) { + DDRJ |= 0x04; // output + PORTJ |= 0x04; // HIGH + } + #endif + SPIclass.begin(); + #ifdef ARDUINO_AVR_ADK + if (irq_pin == 54) { + DDRE &= ~0x20; // input + PORTE |= 0x20; // pullup + } else + #endif + pinMode(irq_pin, INPUT_PULLUP); + //UHS_PIN_WRITE(irq_pin, HIGH); + pinMode(ss_pin, OUTPUT); + MARLIN_UHS_WRITE_SS(HIGH); + + #ifdef USB_HOST_SHIELD_TIMING_PIN + pinMode(USB_HOST_SHIELD_TIMING_PIN, OUTPUT); + // My counter/timer can't work on an inverted gate signal + // so we gate using a high pulse -- AJK + UHS_PIN_WRITE(USB_HOST_SHIELD_TIMING_PIN, LOW); + #endif + interrupts(); + + #if USB_HOST_SHIELD_USE_ISR + int intr = digitalPinToInterrupt(irq_pin); + if (intr == NOT_AN_INTERRUPT) { + #ifdef ARDUINO_AVR_ADK + if (irq_pin == 54) + intr = 6; + else + #endif + return (-2); + } + SPIclass.usingInterrupt(intr); + #else + SPIclass.usingInterrupt(255); + #endif + #ifndef NO_AUTO_SPEED + // test to get to reset acceptance. + uint32_t spd = UHS_MAX3421E_SPD; + again: + MAX3421E_SPI_Settings = SPISettings(spd, MSBFIRST, SPI_MODE0); + if (reset() == 0) { + MAX_HOST_DEBUG(PSTR("Fail SPI speed %lu\r\n"), spd); + if (spd > 1999999) { + spd -= 1000000; + goto again; + } + return (-1); + } else { + // reset passes, does 64k? + uint8_t sample_wr = 0; + uint8_t sample_rd = 0; + uint8_t gpinpol_copy = regRd(rGPINPOL); + for (uint16_t j = 0; j < 65535; j++) { + regWr(rGPINPOL, sample_wr); + sample_rd = regRd(rGPINPOL); + if (sample_rd != sample_wr) { + MAX_HOST_DEBUG(PSTR("Fail SPI speed %lu\r\n"), spd); + if (spd > 1999999) { + spd -= 1000000; + goto again; + } + return (-1); } -#endif - SPIclass.begin(); -#ifdef ARDUINO_AVR_ADK - if(irq_pin == 54) { - DDRE &= ~0x20; // input - PORTE |= 0x20; // pullup - } else -#endif - pinMode(irq_pin, INPUT_PULLUP); - //UHS_PIN_WRITE(irq_pin, HIGH); - pinMode(ss_pin, OUTPUT); - MARLIN_UHS_WRITE_SS(HIGH); + sample_wr++; + } + regWr(rGPINPOL, gpinpol_copy); + } -#ifdef USB_HOST_SHIELD_TIMING_PIN - pinMode(USB_HOST_SHIELD_TIMING_PIN, OUTPUT); - // My counter/timer can't work on an inverted gate signal - // so we gate using a high pulse -- AJK - UHS_PIN_WRITE(USB_HOST_SHIELD_TIMING_PIN, LOW); -#endif - interrupts(); + MAX_HOST_DEBUG(PSTR("Pass SPI speed %lu\r\n"), spd); + #endif -#if USB_HOST_SHIELD_USE_ISR - int intr = digitalPinToInterrupt(irq_pin); - if(intr == NOT_AN_INTERRUPT) { -#ifdef ARDUINO_AVR_ADK - if(irq_pin == 54) - intr = 6; - else -#endif - return (-2); - } - SPIclass.usingInterrupt(intr); -#else - SPIclass.usingInterrupt(255); -#endif -#ifndef NO_AUTO_SPEED - // test to get to reset acceptance. - uint32_t spd = UHS_MAX3421E_SPD; -again: - MAX3421E_SPI_Settings = SPISettings(spd, MSBFIRST, SPI_MODE0); - if(reset() == 0) { - MAX_HOST_DEBUG(PSTR("Fail SPI speed %lu\r\n"), spd); - if(spd > 1999999) { - spd -= 1000000; - goto again; - } - return (-1); - } else { - // reset passes, does 64k? - uint8_t sample_wr = 0; - uint8_t sample_rd = 0; - uint8_t gpinpol_copy = regRd(rGPINPOL); - for(uint16_t j = 0; j < 65535; j++) { - regWr(rGPINPOL, sample_wr); - sample_rd = regRd(rGPINPOL); - if(sample_rd != sample_wr) { - MAX_HOST_DEBUG(PSTR("Fail SPI speed %lu\r\n"), spd); - if(spd > 1999999) { - spd -= 1000000; - goto again; - } - return (-1); - } - sample_wr++; - } - regWr(rGPINPOL, gpinpol_copy); - } + if (reset() == 0) { // OSCOKIRQ hasn't asserted in time + MAX_HOST_DEBUG(PSTR("OSCOKIRQ hasn't asserted in time")); + return ( -1); + } - MAX_HOST_DEBUG(PSTR("Pass SPI speed %lu\r\n"), spd); -#endif + /* MAX3421E - full-duplex SPI, interrupt kind, vbus off */ + regWr(rPINCTL, (bmFDUPSPI | bmIRQ_SENSE | GPX_VBDET)); - if(reset() == 0) { //OSCOKIRQ hasn't asserted in time - MAX_HOST_DEBUG(PSTR("OSCOKIRQ hasn't asserted in time")); - return ( -1); - } + // Delay a minimum of 1 second to ensure any capacitors are drained. + // 1 second is required to make sure we do not smoke a Microdrive! + if (mseconds != INT16_MIN) { + if (mseconds < 1000) mseconds = 1000; + delay(mseconds); // We can't depend on SOF timer here. + } - /* MAX3421E - full-duplex SPI, interrupt kind, vbus off */ - regWr(rPINCTL, (bmFDUPSPI | bmIRQ_SENSE | GPX_VBDET)); + regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host - // Delay a minimum of 1 second to ensure any capacitors are drained. - // 1 second is required to make sure we do not smoke a Microdrive! - if(mseconds != INT16_MIN) { - if(mseconds < 1000) mseconds = 1000; - delay(mseconds); // We can't depend on SOF timer here. - } + // Enable interrupts on the MAX3421e + regWr(rHIEN, IRQ_CHECK_MASK); + // Enable interrupt pin on the MAX3421e, set pulse width for edge + regWr(rCPUCTL, (bmIE | bmPULSEWIDTH)); - regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host + /* check if device is connected */ + regWr(rHCTL, bmSAMPLEBUS); // sample USB bus + while (!(regRd(rHCTL) & bmSAMPLEBUS)); // wait for sample operation to finish - // Enable interrupts on the MAX3421e - regWr(rHIEN, IRQ_CHECK_MASK); - // Enable interrupt pin on the MAX3421e, set pulse width for edge - regWr(rCPUCTL, (bmIE | bmPULSEWIDTH)); + busprobe(); // check if anything is connected + VBUS_changed(); - /* check if device is connected */ - regWr(rHCTL, bmSAMPLEBUS); // sample USB bus - while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish + // GPX pin on. This is done here so that a change is detected if we have a switch connected. + /* MAX3421E - full-duplex SPI, interrupt kind, vbus on */ + regWr(rPINCTL, (bmFDUPSPI | bmIRQ_SENSE)); + regWr(rHIRQ, bmBUSEVENTIRQ); // see data sheet. + regWr(rHCTL, bmBUSRST); // issue bus reset to force generate yet another possible IRQ - busprobe(); //check if anything is connected - VBUS_changed(); - - // GPX pin on. This is done here so that a change is detected if we have a switch connected. - /* MAX3421E - full-duplex SPI, interrupt kind, vbus on */ - regWr(rPINCTL, (bmFDUPSPI | bmIRQ_SENSE)); - regWr(rHIRQ, bmBUSEVENTIRQ); // see data sheet. - regWr(rHCTL, bmBUSRST); // issue bus reset to force generate yet another possible IRQ - - -#if USB_HOST_SHIELD_USE_ISR - // Attach ISR to service IRQ from MAX3421e - noInterrupts(); - if(irq_pin & 1) { - ISRodd = this; - attachInterrupt(UHS_GET_DPI(irq_pin), call_ISRodd, IRQ_SENSE); - } else { - ISReven = this; - attachInterrupt(UHS_GET_DPI(irq_pin), call_ISReven, IRQ_SENSE); - } - interrupts(); -#endif - //printf("\r\nrPINCTL 0x%2.2X\r\n", rPINCTL); - //printf("rCPUCTL 0x%2.2X\r\n", rCPUCTL); - //printf("rHIEN 0x%2.2X\r\n", rHIEN); - //printf("irq_pin %i\r\n", irq_pin); - return 0; + #if USB_HOST_SHIELD_USE_ISR + // Attach ISR to service IRQ from MAX3421e + noInterrupts(); + if (irq_pin & 1) { + ISRodd = this; + attachInterrupt(UHS_GET_DPI(irq_pin), call_ISRodd, IRQ_SENSE); + } else { + ISReven = this; + attachInterrupt(UHS_GET_DPI(irq_pin), call_ISReven, IRQ_SENSE); + } + interrupts(); + #endif + //printf("\r\nrPINCTL 0x%2.2X\r\n", rPINCTL); + //printf("rCPUCTL 0x%2.2X\r\n", rCPUCTL); + //printf("rHIEN 0x%2.2X\r\n", rHIEN); + //printf("irq_pin %i\r\n", irq_pin); + return 0; } /** @@ -426,41 +427,41 @@ again: * @return 0 on success */ uint8_t UHS_NI MAX3421E_HOST::SetAddress(uint8_t addr, uint8_t ep, UHS_EpInfo **ppep, uint16_t &nak_limit) { - UHS_Device *p = addrPool.GetUsbDevicePtr(addr); + UHS_Device *p = addrPool.GetUsbDevicePtr(addr); - if(!p) - return UHS_HOST_ERROR_NO_ADDRESS_IN_POOL; + if (!p) + return UHS_HOST_ERROR_NO_ADDRESS_IN_POOL; - if(!p->epinfo) - return UHS_HOST_ERROR_NULL_EPINFO; + if (!p->epinfo) + return UHS_HOST_ERROR_NULL_EPINFO; - *ppep = getEpInfoEntry(addr, ep); + *ppep = getEpInfoEntry(addr, ep); - if(!*ppep) - return UHS_HOST_ERROR_NO_ENDPOINT_IN_TABLE; + if (!*ppep) + return UHS_HOST_ERROR_NO_ENDPOINT_IN_TABLE; - nak_limit = (0x0001UL << (((*ppep)->bmNakPower > UHS_USB_NAK_MAX_POWER) ? UHS_USB_NAK_MAX_POWER : (*ppep)->bmNakPower)); - nak_limit--; - /* - USBTRACE2("\r\nAddress: ", addr); - USBTRACE2(" EP: ", ep); - USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower); - USBTRACE2(" NAK Limit: ", nak_limit); - USBTRACE("\r\n"); - */ - regWr(rPERADDR, addr); //set peripheral address + nak_limit = (0x0001UL << (((*ppep)->bmNakPower > UHS_USB_NAK_MAX_POWER) ? UHS_USB_NAK_MAX_POWER : (*ppep)->bmNakPower)); + nak_limit--; + /* + USBTRACE2("\r\nAddress: ", addr); + USBTRACE2(" EP: ", ep); + USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower); + USBTRACE2(" NAK Limit: ", nak_limit); + USBTRACE("\r\n"); + */ + regWr(rPERADDR, addr); // set peripheral address - uint8_t mode = regRd(rMODE); + uint8_t mode = regRd(rMODE); - //Serial.print("\r\nMode: "); - //Serial.println( mode, HEX); - //Serial.print("\r\nLS: "); - //Serial.println(p->speed, HEX); + //Serial.print("\r\nMode: "); + //Serial.println( mode, HEX); + //Serial.print("\r\nLS: "); + //Serial.println(p->speed, HEX); - // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise - regWr(rMODE, (p->speed) ? mode & ~(bmHUBPRE | bmLOWSPEED) : mode | bmLOWSPEED | hub_present); + // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise + regWr(rMODE, (p->speed) ? mode & ~(bmHUBPRE | bmLOWSPEED) : mode | bmLOWSPEED | hub_present); - return 0; + return 0; } /** @@ -473,71 +474,70 @@ uint8_t UHS_NI MAX3421E_HOST::SetAddress(uint8_t addr, uint8_t ep, UHS_EpInfo ** * @return 0 on success */ uint8_t UHS_NI MAX3421E_HOST::InTransfer(UHS_EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data) { - uint8_t rcode = 0; - uint8_t pktsize; + uint8_t rcode = 0; + uint8_t pktsize; - uint16_t nbytes = *nbytesptr; - MAX_HOST_DEBUG(PSTR("Requesting %i bytes "), nbytes); - uint8_t maxpktsize = pep->maxPktSize; + uint16_t nbytes = *nbytesptr; + MAX_HOST_DEBUG(PSTR("Requesting %i bytes "), nbytes); + uint8_t maxpktsize = pep->maxPktSize; - *nbytesptr = 0; - regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value + *nbytesptr = 0; + regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); // set toggle value - // use a 'break' to exit this loop - while(1) { - rcode = dispatchPkt(MAX3421E_tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS. -#if 0 - // This issue should be resolved now. - if(rcode == UHS_HOST_ERROR_TOGERR) { - //MAX_HOST_DEBUG(PSTR("toggle wrong\r\n")); - // yes, we flip it wrong here so that next time it is actually correct! - pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; - regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value - continue; - } -#endif - if(rcode) { - //MAX_HOST_DEBUG(PSTR(">>>>>>>> Problem! dispatchPkt %2.2x\r\n"), rcode); - break; //should be 0, indicating ACK. Else return error code. - } - /* check for RCVDAVIRQ and generate error if not present */ - /* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */ - if((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) { - //MAX_HOST_DEBUG(PSTR(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n")); - rcode = 0xF0; //receive error - break; - } - pktsize = regRd(rRCVBC); //number of received bytes - MAX_HOST_DEBUG(PSTR("Got %i bytes \r\n"), pktsize); + // use a 'break' to exit this loop + while (1) { + rcode = dispatchPkt(MAX3421E_tokIN, pep->epAddr, nak_limit); // IN packet to EP-'endpoint'. Function takes care of NAKS. + #if 0 + // This issue should be resolved now. + if (rcode == UHS_HOST_ERROR_TOGERR) { + //MAX_HOST_DEBUG(PSTR("toggle wrong\r\n")); + // yes, we flip it wrong here so that next time it is actually correct! + pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; + regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); // set toggle value + continue; + } + #endif + if (rcode) { + //MAX_HOST_DEBUG(PSTR(">>>>>>>> Problem! dispatchPkt %2.2x\r\n"), rcode); + break; // should be 0, indicating ACK. Else return error code. + } + /* check for RCVDAVIRQ and generate error if not present */ + /* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */ + if ((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) { + //MAX_HOST_DEBUG(PSTR(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n")); + rcode = 0xF0; // receive error + break; + } + pktsize = regRd(rRCVBC); // number of received bytes + MAX_HOST_DEBUG(PSTR("Got %i bytes \r\n"), pktsize); - if(pktsize > nbytes) { //certain devices send more than asked - //MAX_HOST_DEBUG(PSTR(">>>>>>>> Warning: wanted %i bytes but got %i.\r\n"), nbytes, pktsize); - pktsize = nbytes; - } + if (pktsize > nbytes) { // certain devices send more than asked + //MAX_HOST_DEBUG(PSTR(">>>>>>>> Warning: wanted %i bytes but got %i.\r\n"), nbytes, pktsize); + pktsize = nbytes; + } - int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); + int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr); - if(mem_left < 0) - mem_left = 0; + if (mem_left < 0) + mem_left = 0; - data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data); + data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data); - regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer - *nbytesptr += pktsize; // add this packet's byte count to total transfer length + regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer + *nbytesptr += pktsize; // add this packet's byte count to total transfer length - /* The transfer is complete under two conditions: */ - /* 1. The device sent a short packet (L.T. maxPacketSize) */ - /* 2. 'nbytes' have been transferred. */ - if((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes? - { - // Save toggle value - pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0; - //MAX_HOST_DEBUG(PSTR("\r\n")); - rcode = 0; - break; - } // if - } //while( 1 ) - return ( rcode); + /* The transfer is complete under two conditions: */ + /* 1. The device sent a short packet (L.T. maxPacketSize) */ + /* 2. 'nbytes' have been transferred. */ + if ((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) { // have we transferred 'nbytes' bytes? + // Save toggle value + pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0; + //MAX_HOST_DEBUG(PSTR("\r\n")); + rcode = 0; + break; + } // if + } // while( 1 ) + return (rcode); } /** @@ -550,72 +550,72 @@ uint8_t UHS_NI MAX3421E_HOST::InTransfer(UHS_EpInfo *pep, uint16_t nak_limit, ui * @return 0 on success */ uint8_t UHS_NI MAX3421E_HOST::OutTransfer(UHS_EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) { - uint8_t rcode = UHS_HOST_ERROR_NONE; - uint8_t retry_count; - uint8_t *data_p = data; //local copy of the data pointer - uint16_t bytes_tosend; - uint16_t nak_count; - uint16_t bytes_left = nbytes; + uint8_t rcode = UHS_HOST_ERROR_NONE; + uint8_t retry_count; + uint8_t *data_p = data; // local copy of the data pointer + uint16_t bytes_tosend; + uint16_t nak_count; + uint16_t bytes_left = nbytes; - uint8_t maxpktsize = pep->maxPktSize; + uint8_t maxpktsize = pep->maxPktSize; - if(maxpktsize < 1 || maxpktsize > 64) - return UHS_HOST_ERROR_BAD_MAX_PACKET_SIZE; + if (maxpktsize < 1 || maxpktsize > 64) + return UHS_HOST_ERROR_BAD_MAX_PACKET_SIZE; - unsigned long timeout = millis() + UHS_HOST_TRANSFER_MAX_MS; + unsigned long timeout = millis() + UHS_HOST_TRANSFER_MAX_MS; - regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value + regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); // set toggle value - while(bytes_left) { - SYSTEM_OR_SPECIAL_YIELD(); - retry_count = 0; - nak_count = 0; - bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left; - bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO - regWr(rSNDBC, bytes_tosend); //set number of bytes - regWr(rHXFR, (MAX3421E_tokOUT | pep->epAddr)); //dispatch packet - while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ - regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ - rcode = (regRd(rHRSL) & 0x0F); + while (bytes_left) { + SYSTEM_OR_SPECIAL_YIELD(); + retry_count = 0; + nak_count = 0; + bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left; + bytesWr(rSNDFIFO, bytes_tosend, data_p); // filling output FIFO + regWr(rSNDBC, bytes_tosend); // set number of bytes + regWr(rHXFR, (MAX3421E_tokOUT | pep->epAddr)); // dispatch packet + while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); // wait for the completion IRQ + regWr(rHIRQ, bmHXFRDNIRQ); // clear IRQ + rcode = (regRd(rHRSL) & 0x0F); - while(rcode && ((long)(millis() - timeout) < 0L)) { - switch(rcode) { - case UHS_HOST_ERROR_NAK: - nak_count++; - if(nak_limit && (nak_count == nak_limit)) - goto breakout; - break; - case UHS_HOST_ERROR_TIMEOUT: - retry_count++; - if(retry_count == UHS_HOST_TRANSFER_RETRY_MAXIMUM) - goto breakout; - break; - case UHS_HOST_ERROR_TOGERR: - // yes, we flip it wrong here so that next time it is actually correct! - pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; - regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value - break; - default: - goto breakout; - }//switch( rcode + while (rcode && ((long)(millis() - timeout) < 0L)) { + switch (rcode) { + case UHS_HOST_ERROR_NAK: + nak_count++; + if (nak_limit && (nak_count == nak_limit)) + goto breakout; + break; + case UHS_HOST_ERROR_TIMEOUT: + retry_count++; + if (retry_count == UHS_HOST_TRANSFER_RETRY_MAXIMUM) + goto breakout; + break; + case UHS_HOST_ERROR_TOGERR: + // yes, we flip it wrong here so that next time it is actually correct! + pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; + regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); // set toggle value + break; + default: + goto breakout; + } // switch (rcode - /* process NAK according to Host out NAK bug */ - regWr(rSNDBC, 0); - regWr(rSNDFIFO, *data_p); - regWr(rSNDBC, bytes_tosend); - regWr(rHXFR, (MAX3421E_tokOUT | pep->epAddr)); //dispatch packet - while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ - regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ - rcode = (regRd(rHRSL) & 0x0F); - SYSTEM_OR_SPECIAL_YIELD(); - }//while( rcode && .... - bytes_left -= bytes_tosend; - data_p += bytes_tosend; - }//while( bytes_left... -breakout: + /* process NAK according to Host out NAK bug */ + regWr(rSNDBC, 0); + regWr(rSNDFIFO, *data_p); + regWr(rSNDBC, bytes_tosend); + regWr(rHXFR, (MAX3421E_tokOUT | pep->epAddr)); // dispatch packet + while (!(regRd(rHIRQ) & bmHXFRDNIRQ)); // wait for the completion IRQ + regWr(rHIRQ, bmHXFRDNIRQ); // clear IRQ + rcode = (regRd(rHRSL) & 0x0F); + SYSTEM_OR_SPECIAL_YIELD(); + } // while (rcode && .... + bytes_left -= bytes_tosend; + data_p += bytes_tosend; + } // while (bytes_left... + breakout: - pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle - return ( rcode); //should be 0 in all cases + pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; // bmSNDTOG1 : bmSNDTOG0; // update toggle + return (rcode); // should be 0 in all cases } /** @@ -633,45 +633,44 @@ breakout: /* return codes 0x00-0x0F are HRSLT( 0x00 being success ), 0xFF means timeout */ uint8_t UHS_NI MAX3421E_HOST::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) { - unsigned long timeout = millis() + UHS_HOST_TRANSFER_MAX_MS; - uint8_t tmpdata; - uint8_t rcode = UHS_HOST_ERROR_NONE; - uint8_t retry_count = 0; - uint16_t nak_count = 0; + unsigned long timeout = millis() + UHS_HOST_TRANSFER_MAX_MS; + uint8_t tmpdata; + uint8_t rcode = UHS_HOST_ERROR_NONE; + uint8_t retry_count = 0; + uint16_t nak_count = 0; - for(;;) { - regWr(rHXFR, (token | ep)); //launch the transfer - while((long)(millis() - timeout) < 0L) //wait for transfer completion - { - SYSTEM_OR_SPECIAL_YIELD(); - tmpdata = regRd(rHIRQ); + for (;;) { + regWr(rHXFR, (token | ep)); // launch the transfer + while (long(millis() - timeout) < 0L) { // wait for transfer completion + SYSTEM_OR_SPECIAL_YIELD(); + tmpdata = regRd(rHIRQ); - if(tmpdata & bmHXFRDNIRQ) { - regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt - //rcode = 0x00; - break; - }//if( tmpdata & bmHXFRDNIRQ + if (tmpdata & bmHXFRDNIRQ) { + regWr(rHIRQ, bmHXFRDNIRQ); // clear the interrupt + //rcode = 0x00; + break; + } // if (tmpdata & bmHXFRDNIRQ - }//while ( millis() < timeout + } // while (millis() < timeout - rcode = (regRd(rHRSL) & 0x0F); //analyze transfer result + rcode = (regRd(rHRSL) & 0x0F); // analyze transfer result - switch(rcode) { - case UHS_HOST_ERROR_NAK: - nak_count++; - if(nak_limit && (nak_count == nak_limit)) - return (rcode); - delayMicroseconds(200); - break; - case UHS_HOST_ERROR_TIMEOUT: - retry_count++; - if(retry_count == UHS_HOST_TRANSFER_RETRY_MAXIMUM) - return (rcode); - break; - default: - return (rcode); - }//switch( rcode - } + switch (rcode) { + case UHS_HOST_ERROR_NAK: + nak_count++; + if (nak_limit && (nak_count == nak_limit)) + return (rcode); + delayMicroseconds(200); + break; + case UHS_HOST_ERROR_TIMEOUT: + retry_count++; + if (retry_count == UHS_HOST_TRANSFER_RETRY_MAXIMUM) + return (rcode); + break; + default: + return (rcode); + } // switch (rcode) + } } // @@ -679,325 +678,324 @@ uint8_t UHS_NI MAX3421E_HOST::dispatchPkt(uint8_t token, uint8_t ep, uint16_t na // UHS_EpInfo * UHS_NI MAX3421E_HOST::ctrlReqOpen(uint8_t addr, uint64_t Request, uint8_t *dataptr) { - uint8_t rcode; - UHS_EpInfo *pep = NULL; - uint16_t nak_limit = 0; - rcode = SetAddress(addr, 0, &pep, nak_limit); + uint8_t rcode; + UHS_EpInfo *pep = NULL; + uint16_t nak_limit = 0; + rcode = SetAddress(addr, 0, &pep, nak_limit); - if(!rcode) { + if (!rcode) { - bytesWr(rSUDFIFO, 8, (uint8_t*)(&Request)); //transfer to setup packet FIFO + bytesWr(rSUDFIFO, 8, (uint8_t*)(&Request)); // transfer to setup packet FIFO - rcode = dispatchPkt(MAX3421E_tokSETUP, 0, nak_limit); //dispatch packet - if(!rcode) { - if(dataptr != NULL) { - if(((Request)/* bmReqType*/ & 0x80) == 0x80) { - pep->bmRcvToggle = 1; //bmRCVTOG1; - } else { - pep->bmSndToggle = 1; //bmSNDTOG1; - } - } - } else { - pep = NULL; - } + rcode = dispatchPkt(MAX3421E_tokSETUP, 0, nak_limit); // dispatch packet + if (!rcode) { + if (dataptr != NULL) { + if (((Request)/* bmReqType*/ & 0x80) == 0x80) { + pep->bmRcvToggle = 1; //bmRCVTOG1; + } else { + pep->bmSndToggle = 1; //bmSNDTOG1; } - return pep; + } + } else { + pep = NULL; + } + } + return pep; } uint8_t UHS_NI MAX3421E_HOST::ctrlReqRead(UHS_EpInfo *pep, uint16_t *left, uint16_t *read, uint16_t nbytes, uint8_t *dataptr) { - *read = 0; - uint16_t nak_limit = 0; - MAX_HOST_DEBUG(PSTR("ctrlReqRead left: %i\r\n"), *left); - if(*left) { -again: - *read = nbytes; - uint8_t rcode = InTransfer(pep, nak_limit, read, dataptr); - if(rcode == UHS_HOST_ERROR_TOGERR) { - // yes, we flip it wrong here so that next time it is actually correct! - pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; - goto again; - } + *read = 0; + uint16_t nak_limit = 0; + MAX_HOST_DEBUG(PSTR("ctrlReqRead left: %i\r\n"), *left); + if (*left) { + again: + *read = nbytes; + uint8_t rcode = InTransfer(pep, nak_limit, read, dataptr); + if (rcode == UHS_HOST_ERROR_TOGERR) { + // yes, we flip it wrong here so that next time it is actually correct! + pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; + goto again; + } - if(rcode) { - MAX_HOST_DEBUG(PSTR("ctrlReqRead ERROR: %2.2x, left: %i, read %i\r\n"), rcode, *left, *read); - return rcode; - } - *left -= *read; - MAX_HOST_DEBUG(PSTR("ctrlReqRead left: %i, read %i\r\n"), *left, *read); - } - return 0; + if (rcode) { + MAX_HOST_DEBUG(PSTR("ctrlReqRead ERROR: %2.2x, left: %i, read %i\r\n"), rcode, *left, *read); + return rcode; + } + *left -= *read; + MAX_HOST_DEBUG(PSTR("ctrlReqRead left: %i, read %i\r\n"), *left, *read); + } + return 0; } uint8_t UHS_NI MAX3421E_HOST::ctrlReqClose(UHS_EpInfo *pep, uint8_t bmReqType, uint16_t left, uint16_t nbytes, uint8_t *dataptr) { - uint8_t rcode = 0; + uint8_t rcode = 0; - //MAX_HOST_DEBUG(PSTR("Closing")); - if(((bmReqType & 0x80) == 0x80) && pep && left && dataptr) { - MAX_HOST_DEBUG(PSTR("ctrlReqRead Sinking %i\r\n"), left); - // If reading, sink the rest of the data. - while(left) { - uint16_t read = nbytes; - rcode = InTransfer(pep, 0, &read, dataptr); - if(rcode == UHS_HOST_ERROR_TOGERR) { - // yes, we flip it wrong here so that next time it is actually correct! - pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; - continue; - } - if(rcode) break; - left -= read; - if(read < nbytes) break; - } - } - if(!rcode) { - // Serial.println("Dispatching"); - rcode = dispatchPkt(((bmReqType & 0x80) == 0x80) ? MAX3421E_tokOUTHS : MAX3421E_tokINHS, 0, 0); //GET if direction - // } else { - // Serial.println("Bypassed Dispatch"); - } - return rcode; + //MAX_HOST_DEBUG(PSTR("Closing")); + if (((bmReqType & 0x80) == 0x80) && pep && left && dataptr) { + MAX_HOST_DEBUG(PSTR("ctrlReqRead Sinking %i\r\n"), left); + // If reading, sink the rest of the data. + while (left) { + uint16_t read = nbytes; + rcode = InTransfer(pep, 0, &read, dataptr); + if (rcode == UHS_HOST_ERROR_TOGERR) { + // yes, we flip it wrong here so that next time it is actually correct! + pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1; + continue; + } + if (rcode) break; + left -= read; + if (read < nbytes) break; + } + } + if (!rcode) { + //Serial.println("Dispatching"); + rcode = dispatchPkt(((bmReqType & 0x80) == 0x80) ? MAX3421E_tokOUTHS : MAX3421E_tokINHS, 0, 0); //GET if direction + //} else { + //Serial.println("Bypassed Dispatch"); + } + return rcode; } /** * Bottom half of the ISR task */ void UHS_NI MAX3421E_HOST::ISRbottom() { - uint8_t x; - // Serial.print("Enter "); - // Serial.print((uint32_t)this,HEX); - // Serial.print(" "); - // Serial.println(usb_task_state, HEX); + uint8_t x; + // Serial.print("Enter "); + // Serial.print((uint32_t)this,HEX); + // Serial.print(" "); + // Serial.println(usb_task_state, HEX); - DDSB(); - if(condet) { - VBUS_changed(); -#if USB_HOST_SHIELD_USE_ISR - noInterrupts(); -#endif - condet = false; -#if USB_HOST_SHIELD_USE_ISR - interrupts(); -#endif + DDSB(); + if (condet) { + VBUS_changed(); + #if USB_HOST_SHIELD_USE_ISR + noInterrupts(); + #endif + condet = false; + #if USB_HOST_SHIELD_USE_ISR + interrupts(); + #endif + } + switch (usb_task_state) { + case UHS_USB_HOST_STATE_INITIALIZE: + // should never happen... + MAX_HOST_DEBUG(PSTR("UHS_USB_HOST_STATE_INITIALIZE\r\n")); + busprobe(); + VBUS_changed(); + break; + case UHS_USB_HOST_STATE_DEBOUNCE: + MAX_HOST_DEBUG(PSTR("UHS_USB_HOST_STATE_DEBOUNCE\r\n")); + // This seems to not be needed. The host controller has debounce built in. + sof_countdown = UHS_HOST_DEBOUNCE_DELAY_MS; + usb_task_state = UHS_USB_HOST_STATE_DEBOUNCE_NOT_COMPLETE; + break; + case UHS_USB_HOST_STATE_DEBOUNCE_NOT_COMPLETE: + MAX_HOST_DEBUG(PSTR("UHS_USB_HOST_STATE_DEBOUNCE_NOT_COMPLETE\r\n")); + if (!sof_countdown) usb_task_state = UHS_USB_HOST_STATE_RESET_DEVICE; + break; + case UHS_USB_HOST_STATE_RESET_DEVICE: + MAX_HOST_DEBUG(PSTR("UHS_USB_HOST_STATE_RESET_DEVICE\r\n")); + busevent = true; + usb_task_state = UHS_USB_HOST_STATE_RESET_NOT_COMPLETE; + regWr(rHIRQ, bmBUSEVENTIRQ); // see data sheet. + regWr(rHCTL, bmBUSRST); // issue bus reset + break; + case UHS_USB_HOST_STATE_RESET_NOT_COMPLETE: + MAX_HOST_DEBUG(PSTR("UHS_USB_HOST_STATE_RESET_NOT_COMPLETE\r\n")); + if (!busevent) usb_task_state = UHS_USB_HOST_STATE_WAIT_BUS_READY; + break; + case UHS_USB_HOST_STATE_WAIT_BUS_READY: + MAX_HOST_DEBUG(PSTR("UHS_USB_HOST_STATE_WAIT_BUS_READY\r\n")); + usb_task_state = UHS_USB_HOST_STATE_CONFIGURING; + break; // don't fall through + + case UHS_USB_HOST_STATE_CONFIGURING: + usb_task_state = UHS_USB_HOST_STATE_CHECK; + x = Configuring(0, 1, usb_host_speed); + usb_error = x; + if (usb_task_state == UHS_USB_HOST_STATE_CHECK) { + if (x) { + MAX_HOST_DEBUG(PSTR("Error 0x%2.2x"), x); + if (x == UHS_HOST_ERROR_JERR) { + usb_task_state = UHS_USB_HOST_STATE_IDLE; + } else if (x != UHS_HOST_ERROR_DEVICE_INIT_INCOMPLETE) { + usb_error = x; + usb_task_state = UHS_USB_HOST_STATE_ERROR; + } + } else + usb_task_state = UHS_USB_HOST_STATE_CONFIGURING_DONE; + } + break; + + case UHS_USB_HOST_STATE_CHECK: + // Serial.println((uint32_t)__builtin_return_address(0), HEX); + break; + case UHS_USB_HOST_STATE_CONFIGURING_DONE: + usb_task_state = UHS_USB_HOST_STATE_RUNNING; + break; + + #ifdef USB_HOST_MANUAL_POLL + case UHS_USB_HOST_STATE_RUNNING: + case UHS_USB_HOST_STATE_ERROR: + case UHS_USB_HOST_STATE_IDLE: + case UHS_USB_HOST_STATE_ILLEGAL: + enable_frame_irq(false); + break; + #else + case UHS_USB_HOST_STATE_RUNNING: + Poll_Others(); + for (x = 0; (usb_task_state == UHS_USB_HOST_STATE_RUNNING) && (x < UHS_HOST_MAX_INTERFACE_DRIVERS); x++) { + if (devConfig[x]) { + if (devConfig[x]->bPollEnable) devConfig[x]->Poll(); + } } - switch(usb_task_state) { - case UHS_USB_HOST_STATE_INITIALIZE: - // should never happen... - MAX_HOST_DEBUG(PSTR("UHS_USB_HOST_STATE_INITIALIZE\r\n")); - busprobe(); - VBUS_changed(); - break; - case UHS_USB_HOST_STATE_DEBOUNCE: - MAX_HOST_DEBUG(PSTR("UHS_USB_HOST_STATE_DEBOUNCE\r\n")); - // This seems to not be needed. The host controller has debounce built in. - sof_countdown = UHS_HOST_DEBOUNCE_DELAY_MS; - usb_task_state = UHS_USB_HOST_STATE_DEBOUNCE_NOT_COMPLETE; - break; - case UHS_USB_HOST_STATE_DEBOUNCE_NOT_COMPLETE: - MAX_HOST_DEBUG(PSTR("UHS_USB_HOST_STATE_DEBOUNCE_NOT_COMPLETE\r\n")); - if(!sof_countdown) usb_task_state = UHS_USB_HOST_STATE_RESET_DEVICE; - break; - case UHS_USB_HOST_STATE_RESET_DEVICE: - MAX_HOST_DEBUG(PSTR("UHS_USB_HOST_STATE_RESET_DEVICE\r\n")); - busevent = true; - usb_task_state = UHS_USB_HOST_STATE_RESET_NOT_COMPLETE; - regWr(rHIRQ, bmBUSEVENTIRQ); // see data sheet. - regWr(rHCTL, bmBUSRST); // issue bus reset - break; - case UHS_USB_HOST_STATE_RESET_NOT_COMPLETE: - MAX_HOST_DEBUG(PSTR("UHS_USB_HOST_STATE_RESET_NOT_COMPLETE\r\n")); - if(!busevent) usb_task_state = UHS_USB_HOST_STATE_WAIT_BUS_READY; - break; - case UHS_USB_HOST_STATE_WAIT_BUS_READY: - MAX_HOST_DEBUG(PSTR("UHS_USB_HOST_STATE_WAIT_BUS_READY\r\n")); - usb_task_state = UHS_USB_HOST_STATE_CONFIGURING; - break; // don't fall through - - case UHS_USB_HOST_STATE_CONFIGURING: - usb_task_state = UHS_USB_HOST_STATE_CHECK; - x = Configuring(0, 1, usb_host_speed); - usb_error = x; - if(usb_task_state == UHS_USB_HOST_STATE_CHECK) { - if(x) { - MAX_HOST_DEBUG(PSTR("Error 0x%2.2x"), x); - if(x == UHS_HOST_ERROR_JERR) { - usb_task_state = UHS_USB_HOST_STATE_IDLE; - } else if(x != UHS_HOST_ERROR_DEVICE_INIT_INCOMPLETE) { - usb_error = x; - usb_task_state = UHS_USB_HOST_STATE_ERROR; - } - } else - usb_task_state = UHS_USB_HOST_STATE_CONFIGURING_DONE; - } - break; - - case UHS_USB_HOST_STATE_CHECK: - // Serial.println((uint32_t)__builtin_return_address(0), HEX); - break; - case UHS_USB_HOST_STATE_CONFIGURING_DONE: - usb_task_state = UHS_USB_HOST_STATE_RUNNING; - break; - #ifdef USB_HOST_MANUAL_POLL - case UHS_USB_HOST_STATE_RUNNING: - case UHS_USB_HOST_STATE_ERROR: - case UHS_USB_HOST_STATE_IDLE: - case UHS_USB_HOST_STATE_ILLEGAL: - enable_frame_irq(false); - break; - #else - case UHS_USB_HOST_STATE_RUNNING: - Poll_Others(); - for(x = 0; (usb_task_state == UHS_USB_HOST_STATE_RUNNING) && (x < UHS_HOST_MAX_INTERFACE_DRIVERS); x++) { - if(devConfig[x]) { - if(devConfig[x]->bPollEnable) devConfig[x]->Poll(); - } - } - // fall thru - #endif - default: - // Do nothing - break; - } // switch( usb_task_state ) - DDSB(); -#if USB_HOST_SHIELD_USE_ISR - if(condet) { - VBUS_changed(); - noInterrupts(); - condet = false; - interrupts(); - } -#endif -#ifdef USB_HOST_SHIELD_TIMING_PIN - // My counter/timer can't work on an inverted gate signal - // so we gate using a high pulse -- AJK - UHS_PIN_WRITE(USB_HOST_SHIELD_TIMING_PIN, LOW); -#endif - //usb_task_polling_disabled--; - EnablePoll(); - DDSB(); + // fall thru + #endif + default: + // Do nothing + break; + } // switch ( usb_task_state ) + DDSB(); + #if USB_HOST_SHIELD_USE_ISR + if (condet) { + VBUS_changed(); + noInterrupts(); + condet = false; + interrupts(); + } + #endif + #ifdef USB_HOST_SHIELD_TIMING_PIN + // My counter/timer can't work on an inverted gate signal + // so we gate using a high pulse -- AJK + UHS_PIN_WRITE(USB_HOST_SHIELD_TIMING_PIN, LOW); + #endif + //usb_task_polling_disabled--; + EnablePoll(); + DDSB(); } /* USB main task. Services the MAX3421e */ #if !USB_HOST_SHIELD_USE_ISR - -void UHS_NI MAX3421E_HOST::ISRTask() { -} -void UHS_NI MAX3421E_HOST::Task() + void UHS_NI MAX3421E_HOST::ISRTask() {} + void UHS_NI MAX3421E_HOST::Task() #else + void UHS_NI MAX3421E_HOST::Task() { + #ifdef USB_HOST_MANUAL_POLL + if (usb_task_state == UHS_USB_HOST_STATE_RUNNING) { + noInterrupts(); + for (uint8_t x = 0; x < UHS_HOST_MAX_INTERFACE_DRIVERS; x++) + if (devConfig[x] && devConfig[x]->bPollEnable) + devConfig[x]->Poll(); + interrupts(); + } + #endif + } -void UHS_NI MAX3421E_HOST::Task() { -#ifdef USB_HOST_MANUAL_POLL - if(usb_task_state == UHS_USB_HOST_STATE_RUNNING) { - noInterrupts(); - for(uint8_t x = 0; x < UHS_HOST_MAX_INTERFACE_DRIVERS; x++) - if(devConfig[x] && devConfig[x]->bPollEnable) - devConfig[x]->Poll(); - interrupts(); - } -#endif -} - -void UHS_NI MAX3421E_HOST::ISRTask() + void UHS_NI MAX3421E_HOST::ISRTask() #endif { - DDSB(); + DDSB(); -#ifndef SWI_IRQ_NUM - suspend_host(); -#if USB_HOST_SHIELD_USE_ISR - // Enable interrupts - interrupts(); -#endif -#endif + #ifndef SWI_IRQ_NUM + suspend_host(); + #if USB_HOST_SHIELD_USE_ISR + // Enable interrupts + interrupts(); + #endif + #endif - counted = false; - if(!MARLIN_UHS_READ_IRQ()) { - uint8_t HIRQALL = regRd(rHIRQ); //determine interrupt source - uint8_t HIRQ = HIRQALL & IRQ_CHECK_MASK; - uint8_t HIRQ_sendback = 0x00; + counted = false; + if (!MARLIN_UHS_READ_IRQ()) { + uint8_t HIRQALL = regRd(rHIRQ); // determine interrupt source + uint8_t HIRQ = HIRQALL & IRQ_CHECK_MASK; + uint8_t HIRQ_sendback = 0x00; - if((HIRQ & bmCONDETIRQ) || (HIRQ & bmBUSEVENTIRQ)) { - MAX_HOST_DEBUG - (PSTR("\r\nBEFORE CDIRQ %s BEIRQ %s resetting %s state 0x%2.2x\r\n"), - (HIRQ & bmCONDETIRQ) ? "T" : "F", - (HIRQ & bmBUSEVENTIRQ) ? "T" : "F", - doingreset ? "T" : "F", - usb_task_state - ); - } - // ALWAYS happens BEFORE or WITH CONDETIRQ - if(HIRQ & bmBUSEVENTIRQ) { - HIRQ_sendback |= bmBUSEVENTIRQ; - if(!doingreset) condet = true; - busprobe(); - busevent = false; - } + if ((HIRQ & bmCONDETIRQ) || (HIRQ & bmBUSEVENTIRQ)) { + MAX_HOST_DEBUG + (PSTR("\r\nBEFORE CDIRQ %s BEIRQ %s resetting %s state 0x%2.2x\r\n"), + (HIRQ & bmCONDETIRQ) ? "T" : "F", + (HIRQ & bmBUSEVENTIRQ) ? "T" : "F", + doingreset ? "T" : "F", + usb_task_state + ); + } + // ALWAYS happens BEFORE or WITH CONDETIRQ + if (HIRQ & bmBUSEVENTIRQ) { + HIRQ_sendback |= bmBUSEVENTIRQ; + if (!doingreset) condet = true; + busprobe(); + busevent = false; + } - if(HIRQ & bmCONDETIRQ) { - HIRQ_sendback |= bmCONDETIRQ; - if(!doingreset) condet = true; - busprobe(); - } + if (HIRQ & bmCONDETIRQ) { + HIRQ_sendback |= bmCONDETIRQ; + if (!doingreset) condet = true; + busprobe(); + } -#if 1 - if((HIRQ & bmCONDETIRQ) || (HIRQ & bmBUSEVENTIRQ)) { - MAX_HOST_DEBUG - (PSTR("\r\nAFTER CDIRQ %s BEIRQ %s resetting %s state 0x%2.2x\r\n"), - (HIRQ & bmCONDETIRQ) ? "T" : "F", - (HIRQ & bmBUSEVENTIRQ) ? "T" : "F", - doingreset ? "T" : "F", - usb_task_state - ); - } -#endif + #if 1 + if ((HIRQ & bmCONDETIRQ) || (HIRQ & bmBUSEVENTIRQ)) { + MAX_HOST_DEBUG + (PSTR("\r\nAFTER CDIRQ %s BEIRQ %s resetting %s state 0x%2.2x\r\n"), + (HIRQ & bmCONDETIRQ) ? "T" : "F", + (HIRQ & bmBUSEVENTIRQ) ? "T" : "F", + doingreset ? "T" : "F", + usb_task_state + ); + } + #endif - if(HIRQ & bmFRAMEIRQ) { - HIRQ_sendback |= bmFRAMEIRQ; - if(sof_countdown) { - sof_countdown--; - counted = true; - } - sofevent = false; - } + if (HIRQ & bmFRAMEIRQ) { + HIRQ_sendback |= bmFRAMEIRQ; + if (sof_countdown) { + sof_countdown--; + counted = true; + } + sofevent = false; + } - //MAX_HOST_DEBUG(PSTR("\r\n%s%s%s\r\n"), - // sof_countdown ? "T" : "F", - // counted ? "T" : "F", - // usb_task_polling_disabled? "T" : "F"); - DDSB(); - regWr(rHIRQ, HIRQ_sendback); -#ifndef SWI_IRQ_NUM - resume_host(); -#if USB_HOST_SHIELD_USE_ISR + //MAX_HOST_DEBUG(PSTR("\r\n%s%s%s\r\n"), + // sof_countdown ? "T" : "F", + // counted ? "T" : "F", + // usb_task_polling_disabled? "T" : "F"); + DDSB(); + regWr(rHIRQ, HIRQ_sendback); + #ifndef SWI_IRQ_NUM + resume_host(); + #if USB_HOST_SHIELD_USE_ISR // Disable interrupts noInterrupts(); -#endif -#endif - if(!sof_countdown && !counted && !usb_task_polling_disabled) { - DisablePoll(); - //usb_task_polling_disabled++; -#ifdef USB_HOST_SHIELD_TIMING_PIN - // My counter/timer can't work on an inverted gate signal - // so we gate using a high pulse -- AJK - UHS_PIN_WRITE(USB_HOST_SHIELD_TIMING_PIN, HIGH); -#endif + #endif + #endif + if (!sof_countdown && !counted && !usb_task_polling_disabled) { + DisablePoll(); + //usb_task_polling_disabled++; + #ifdef USB_HOST_SHIELD_TIMING_PIN + // My counter/timer can't work on an inverted gate signal + // so we gate using a high pulse -- AJK + UHS_PIN_WRITE(USB_HOST_SHIELD_TIMING_PIN, HIGH); + #endif -#ifdef SWI_IRQ_NUM - // MAX_HOST_DEBUG(PSTR("--------------- Doing SWI ----------------")); - exec_SWI(this); -#else -#if USB_HOST_SHIELD_USE_ISR - // Enable interrupts - interrupts(); -#endif /* USB_HOST_SHIELD_USE_ISR */ - ISRbottom(); -#endif /* SWI_IRQ_NUM */ - } - } + #ifdef SWI_IRQ_NUM + //MAX_HOST_DEBUG(PSTR("--------------- Doing SWI ----------------")); + exec_SWI(this); + #else + #if USB_HOST_SHIELD_USE_ISR + // Enable interrupts + interrupts(); + #endif + ISRbottom(); + #endif /* SWI_IRQ_NUM */ + } + } } #if 0 -DDSB(); + DDSB(); #endif + #else -#error "Never include USB_HOST_SHIELD_INLINE.h, include UHS_host.h instead" + #error "Never include USB_HOST_SHIELD_INLINE.h, include UHS_host.h instead" #endif