diff --git a/hardware/sam/cores/sam/USBAPI.h b/hardware/sam/cores/sam/USBAPI.h index 26a203227..fdf4cd4fd 100644 --- a/hardware/sam/cores/sam/USBAPI.h +++ b/hardware/sam/cores/sam/USBAPI.h @@ -35,7 +35,7 @@ public: virtual int peek(void); virtual int read(void); virtual void flush(void); - virtual size_t write(uint8_t); + virtual void write(uint8_t); }; extern Serial_ Serial; @@ -101,7 +101,7 @@ private: void setKeyMap(KeyMap* keyMap); public: Keyboard_(); - virtual size_t write(uint8_t); + virtual void write(uint8_t); }; extern Keyboard_ Keyboard; @@ -163,4 +163,4 @@ void USB_Flush(uint8_t ep); #endif -#endif /* if defined(USBCON) */ \ No newline at end of file +#endif /* if defined(USBCON) */ diff --git a/hardware/sam/cores/sam/USBCore.cpp b/hardware/sam/cores/sam/USBCore.cpp index 398bc73ee..49cfe1d4c 100644 --- a/hardware/sam/cores/sam/USBCore.cpp +++ b/hardware/sam/cores/sam/USBCore.cpp @@ -1,34 +1,88 @@ -/* Copyright (c) 2010, Peter Barrett -** -** Permission to use, copy, modify, and/or distribute this software for -** any purpose with or without fee is hereby granted, provided that the -** above copyright notice and this permission notice appear in all copies. -** -** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR -** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES -** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -** SOFTWARE. +/* Copyright (c) 2010, Peter Barrett +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +** SOFTWARE. */ - +#define USBCON #include "Platform.h" #include "USBAPI.h" #include "USBDesc.h" +#include "USBCore.h" + +#if 0 #if defined(USBCON) -#define EP_TYPE_CONTROL 0x00 -#define EP_TYPE_BULK_IN 0x81 -#define EP_TYPE_BULK_OUT 0x80 -#define EP_TYPE_INTERRUPT_IN 0xC1 -#define EP_TYPE_INTERRUPT_OUT 0xC0 -#define EP_TYPE_ISOCHRONOUS_IN 0x41 -#define EP_TYPE_ISOCHRONOUS_OUT 0x40 +#define NUM_IT_MAX 3 + +#define EP_SINGLE_64 0x32 // EP0 +#define EP_DOUBLE_64 0x36 // Other endpoints + + +// Endpoiont 0: +#define EP_TYPE_CONTROL UDPHS_EPTCFG_EPT_SIZE_64 \ + | UDPHS_EPTCFG_EPT_TYPE_CTRL8 \ + | UDPHS_EPTCFG_BK_NUMBER_1 +#ifdef CDC_ENABLED +#define EP_TYPE_BULK_IN UDPHS_EPTCFG_EPT_SIZE_512 \ + | UDPHS_EPTCFG_EPT_DIR \ + | UDPHS_EPTCFG_EPT_TYPE_BULK \ + | UDPHS_EPTCFG_BK_NUMBER_2 +#define EP_TYPE_BULK_OUT UDPHS_EPTCFG_EPT_SIZE_512 \ + | UDPHS_EPTCFG_EPT_TYPE_BULK \ + | UDPHS_EPTCFG_BK_NUMBER_2 +#define EP_TYPE_INTERRUPT_IN UDPHS_EPTCFG_EPT_SIZE_64 \ + | UDPHS_EPTCFG_EPT_DIR \ + | UDPHS_EPTCFG_EPT_TYPE_INT \ + | UDPHS_EPTCFG_BK_NUMBER_2 +#endif + +#ifdef HID_ENABLED +#define EP_TYPE_INTERRUPT_IN_HID UDPHS_EPTCFG_EPT_SIZE_64 \ + | UDPHS_EPTCFG_EPT_DIR \ + | UDPHS_EPTCFG_EPT_TYPE_INT \ + | UDPHS_EPTCFG_BK_NUMBER_2 +#endif + +#define EP_TYPE_INTERRUPT_OUT UDPHS_EPTCFG_EPT_SIZE_64 \ + | UDPHS_EPTCFG_EPT_TYPE_INT \ + | UDPHS_EPTCFG_EPT_TYPE_INT \ + | UDPHS_EPTCFG_BK_NUMBER_1 +#define EP_TYPE_ISOCHRONOUS_IN UDPHS_EPTCFG_EPT_SIZE_1024 \ + | UDPHS_EPTCFG_EPT_DIR \ + | UDPHS_EPTCFG_EPT_TYPE_ISO \ + | UDPHS_EPTCFG_BK_NUMBER_3 +#define EP_TYPE_ISOCHRONOUS_OUT UDPHS_EPTCFG_EPT_SIZE_1024 \ + | UDPHS_EPTCFG_EPT_TYPE_ISO \ + | UDPHS_EPTCFG_BK_NUMBER_3 + +extern const u8 _initEndpoints[] ; +const u8 _initEndpoints[] = +{ + 0, + +#ifdef CDC_ENABLED + EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN + EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT + EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM +#endif + +#ifdef HID_ENABLED + EP_TYPE_INTERRUPT_IN // HID_ENDPOINT_INT +#endif +}; /** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */ #define TX_RX_LED_PULSE_MS 100 @@ -38,11 +92,11 @@ volatile u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ //================================================================== //================================================================== -extern const u16 STRING_LANGUAGE[] PROGMEM; -extern const u16 STRING_IPRODUCT[] PROGMEM; -extern const u16 STRING_IMANUFACTURER[] PROGMEM; -extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM; -extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM; +extern const u16 STRING_LANGUAGE[] ; +extern const u16 STRING_IPRODUCT[] ; +extern const u16 STRING_IMANUFACTURER[] ; +extern const DeviceDescriptor USB_DeviceDescriptor ; +extern const DeviceDescriptor USB_DeviceDescriptorA ; const u16 STRING_LANGUAGE[2] = { (3<<8) | (2+2), @@ -51,10 +105,14 @@ const u16 STRING_LANGUAGE[2] = { const u16 STRING_IPRODUCT[17] = { (3<<8) | (2+2*16), -#if USB_PID == USB_PID_LEONARDO +#if USB_PID == USB_PID_LEONARDO 'A','r','d','u','i','n','o',' ','L','e','o','n','a','r','d','o' #elif USB_PID == USB_PID_MICRO 'A','r','d','u','i','n','o',' ','M','i','c','r','o',' ',' ',' ' +#elif USB_PID == ARDUINO_MODEL_USB_PID + 'A','r','d','u','i','n','o',' ','D','u','e',' ',' ',' ',' ',' ' +#else +#error "Need an USB PID" #endif }; @@ -80,106 +138,165 @@ const DeviceDescriptor USB_DeviceDescriptorA = //================================================================== volatile u8 _usbConfiguration = 0; +// Global variable for endpoint number +unsigned int NumEndpoint=0; + + +#include "../../../system/libsam/cmsis/sam3u/include/sam3u.h" + +#ifndef TXLED1 +#define TXLED0 +#define RXLED0 +#define TXLED1 +#define RXLED1 +#endif + + +/// Max size of the FMA FIFO +#define EPT_VIRTUAL_SIZE 16384 +#define SHIFT_INTERUPT 8 static inline void WaitIN(void) { - while (!(UEINTX & (1<UDPHS_EPT[0].UDPHS_EPTSTA & UDPHS_EPTSTA_TX_PK_RDY)); } static inline void ClearIN(void) { - UEINTX = ~(1<UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TX_COMPLT; } static inline void WaitOUT(void) { - while (!(UEINTX & (1<UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_RX_BK_RDY)); } static inline u8 WaitForINOrOUT() { - while (!(UEINTX & ((1<UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & (UDPHS_EPTSTA_RX_BK_RDY | UDPHS_EPTSTA_TX_PK_RDY))); + return (UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_RX_BK_RDY) == 0; } static inline void ClearOUT(void) { - UEINTX = ~(1<UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_BK_RDY; } -void Recv(volatile u8* data, u8 count) +/* +static void UDPHS_ClearRxFlag( unsigned char bEndpoint ) { - while (count--) - *data++ = UEDATX; - - RXLED1; // light the RX LED - RxLEDPulse = TX_RX_LED_PULSE_MS; + UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_BK_RDY; } +*/ + +#define UDPHS_EPTFIFO (0x20180000) // (UDPHS_EPTFIFO) Base Address + +static void Recv(volatile u8* data, u8 count) +{ + u8 *pFifo; + + pFifo = (u8*)((u32 *)UDPHS_EPTFIFO + (EPT_VIRTUAL_SIZE * NumEndpoint)); + + while (count--) + *data++ = pFifo[0]; // UEDATX; + + RXLED1; // light the RX LED + RxLEDPulse = TX_RX_LED_PULSE_MS; +} + static inline u8 Recv8() { + u8 *pFifo; + RXLED1; // light the RX LED RxLEDPulse = TX_RX_LED_PULSE_MS; - return UEDATX; + pFifo = (u8*)((u32 *)UDPHS_EPTFIFO + (EPT_VIRTUAL_SIZE * NumEndpoint)); + +// return UEDATX; + return (pFifo[0]); } static inline void Send8(u8 d) { - UEDATX = d; + u8 *pFifo; + pFifo = (u8*)((u32 *)UDPHS_EPTFIFO + (EPT_VIRTUAL_SIZE * NumEndpoint)); +// UEDATX = d; + pFifo[0] =d; } static inline void SetEP(u8 ep) { - UENUM = ep; +// UENUM = ep; + NumEndpoint = ep & 7; } -static inline u8 FifoByteCount() +static inline u16 FifoByteCount() { - return UEBCLX; +// return UEBCLX; + // SAM3X + //return ((UOTGHS->UOTGHS_DEVEPTISR[ep] & UOTGHS_DEVEPTISR_BYCT_Msk) >> UOTGHS_DEVEPTISR_BYCT_Pos); + // SAM3U //AT91C_UDPHS_BYTE_COUNT (0x7FF << 20) + return ((UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & (0x7FF << 20)) >> 20); } static inline u8 ReceivedSetupInt() { - return UEINTX & (1<UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_RX_SETUP) ); } static inline void ClearSetupInt() { - UEINTX = ~((1<UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTSTA_RX_SETUP | UDPHS_EPTCLRSTA_RX_BK_RDY | UDPHS_EPTCLRSTA_TX_COMPLT; } static inline void Stall() { - UECONX = (1<UDPHS_EPT[NumEndpoint].UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_FRCESTALL; } static inline u8 ReadWriteAllowed() { - return UEINTX & (1<UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_FRCESTALL)); } static inline u8 FifoFree() { - return UEINTX & (1<UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_TX_PK_RDY )); } -static inline void ReleaseRX() -{ - UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1 -} +//static inline void ReleaseRX() +//{ +// UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1 +//} -static inline void ReleaseTX() -{ - UEINTX = 0x3A; // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0 -} +//static inline void ReleaseTX() +//{ +// UEINTX = 0x3A; // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0 +//} +#define UDFNUML ((UDPHS->UDPHS_FNUM & UDPHS_FNUM_FRAME_NUMBER_Msk)>>3) static inline u8 FrameNumber() { @@ -195,25 +312,11 @@ u8 USBGetConfiguration(void) } #define USB_RECV_TIMEOUT -class LockEP -{ - u8 _sreg; -public: - LockEP(u8 ep) : _sreg(SREG) - { - cli(); - SetEP(ep & 7); - } - ~LockEP() - { - SREG = _sreg; - } -}; // Number of bytes, assumes a rx endpoint u8 USB_Available(u8 ep) { - LockEP lock(ep); + SetEP(ep); return FifoByteCount(); } @@ -223,17 +326,17 @@ int USB_Recv(u8 ep, void* d, int len) { if (!_usbConfiguration || len < 0) return -1; - - LockEP lock(ep); + + SetEP(ep); u8 n = FifoByteCount(); len = min(n,len); n = len; u8* dst = (u8*)d; while (n--) *dst++ = Recv8(); - if (len && !FifoByteCount()) // release empty buffer - ReleaseRX(); - +// if (len && !FifoByteCount()) // release empty buffer +// ReleaseRX(); + return len; } @@ -249,7 +352,7 @@ int USB_Recv(u8 ep) // Space in send EP u8 USB_SendSpace(u8 ep) { - LockEP lock(ep); + SetEP(ep); if (!ReadWriteAllowed()) return 0; return 64 - FifoByteCount(); @@ -280,7 +383,7 @@ int USB_Send(u8 ep, const void* d, int len) n = len; len -= n; { - LockEP lock(ep); + SetEP(ep); if (ep & TRANSFER_ZERO) { while (n--) @@ -289,15 +392,15 @@ int USB_Send(u8 ep, const void* d, int len) else if (ep & TRANSFER_PGM) { while (n--) - Send8(pgm_read_byte(data++)); + Send8(*data++); } else { while (n--) Send8(*data++); } - if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE))) // Release full buffer - ReleaseTX(); +// if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE))) // Release full buffer +// ReleaseTX(); } } TXLED1; // light the TX LED @@ -305,46 +408,38 @@ int USB_Send(u8 ep, const void* d, int len) return r; } -extern const u8 _initEndpoints[] PROGMEM; -const u8 _initEndpoints[] = -{ - 0, - -#ifdef CDC_ENABLED - EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM - EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT - EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN -#endif -#ifdef HID_ENABLED - EP_TYPE_INTERRUPT_IN // HID_ENDPOINT_INT -#endif -}; +//static +//void InitEP(u8 index, u8 type, u8 size) +//{ +// UENUM = index; +// UECONX = 1; +// UECFG0X = type; +// UECFG1X = size; +//} -#define EP_SINGLE_64 0x32 // EP0 -#define EP_DOUBLE_64 0x36 // Other endpoints - -static -void InitEP(u8 index, u8 type, u8 size) -{ - UENUM = index; - UECONX = 1; - UECFG0X = type; - UECFG1X = size; -} static void InitEndpoints() { for (u8 i = 1; i < sizeof(_initEndpoints); i++) { - UENUM = i; - UECONX = 1; - UECFG0X = pgm_read_byte(_initEndpoints+i); - UECFG1X = EP_DOUBLE_64; + // Reset Endpoint Fifos + UDPHS->UDPHS_EPT[i].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TOGGLESQ | UDPHS_EPTCLRSTA_FRCESTALL; + UDPHS->UDPHS_EPTRST = 1<UDPHS_EPT[i].UDPHS_EPTCFG = _initEndpoints[i]; + + while( (signed int)UDPHS_EPTCFG_EPT_MAPD != (signed int)((UDPHS->UDPHS_EPT[i].UDPHS_EPTCFG) & (unsigned int)UDPHS_EPTCFG_EPT_MAPD) ) + ; + UDPHS->UDPHS_EPT[i].UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_EPT_ENABL; + + // UECFG1X = EP_DOUBLE_64; } - UERST = 0x7E; // And reset them - UERST = 0; +///\// UERST = 0x7E; // And reset them +///\// UERST = 0; } // Handle CLASS_INTERFACE requests @@ -370,6 +465,13 @@ int _cend; void InitControl(int end) { SetEP(0); + UDPHS->UDPHS_EPT[0].UDPHS_EPTCFG = _initEndpoints[0]; + while( (signed int)UDPHS_EPTCFG_EPT_MAPD != (signed int)((UDPHS->UDPHS_EPT[0].UDPHS_EPTCFG) & (unsigned int)UDPHS_EPTCFG_EPT_MAPD) ) + ; + UDPHS->UDPHS_EPT[0].UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_RX_BK_RDY + | UDPHS_EPTCTLENB_RX_SETUP + | UDPHS_EPTCTLENB_EPT_ENABL; + _cmark = 0; _cend = end; } @@ -397,7 +499,7 @@ int USB_SendControl(u8 flags, const void* d, int len) bool pgm = flags & TRANSFER_PGM; while (len--) { - u8 c = pgm ? pgm_read_byte(data++) : *data++; + u8 c = pgm ? *data++ : *data++; if (!SendControl(c)) return -1; } @@ -438,7 +540,7 @@ static bool SendConfiguration(int maxlen) { // Count and measure interfaces - InitControl(0); + InitControl(0); int interfaces = SendInterfaces(); ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces); @@ -476,7 +578,7 @@ bool SendDescriptor(Setup& setup) { if (setup.wValueL == 0) desc_addr = (const u8*)&STRING_LANGUAGE; - else if (setup.wValueL == IPRODUCT) + else if (setup.wValueL == IPRODUCT) desc_addr = (const u8*)&STRING_IPRODUCT; else if (setup.wValueL == IMANUFACTURER) desc_addr = (const u8*)&STRING_IMANUFACTURER; @@ -487,14 +589,15 @@ bool SendDescriptor(Setup& setup) if (desc_addr == 0) return false; if (desc_length == 0) - desc_length = pgm_read_byte(desc_addr); + desc_length = *desc_addr; USB_SendControl(TRANSFER_PGM,desc_addr,desc_length); return true; } // Endpoint 0 interrupt -ISR(USB_COM_vect) +//ISR(USB_COM_vect) +void USB_ISR() { SetEP(0); if (!ReceivedSetupInt()) @@ -529,7 +632,7 @@ ISR(USB_COM_vect) else if (SET_ADDRESS == r) { WaitIN(); - UDADDR = setup.wValueL | (1<UDPHS_CTRL |= UDPHS_CTRL_DEV_ADDR(setup.wValueL) | UDPHS_CTRL_FADDR_EN; } else if (GET_DESCRIPTOR == r) { @@ -576,37 +679,150 @@ ISR(USB_COM_vect) void USB_Flush(u8 ep) { SetEP(ep); - if (FifoByteCount()) - ReleaseTX(); +// if (FifoByteCount()) +// ReleaseTX(); } // General interrupt +// USB device interrupt handler +/* +// Manages device resume, suspend, end of bus reset. +// Forwards endpoint interrupts to the appropriate handler. +// General interrupt ISR(USB_GEN_vect) { - u8 udint = UDINT; - UDINT = 0; + u8 udint = UDINT; + UDINT = 0; - // End of Reset - if (udint & (1<UDPHS_INTSTA & UDPHS->UDPHS_IEN; + + // Handle all UDPHS interrupts + while (status != 0) { + + // Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too + if ((status & UDPHS_IEN_INT_SOF) != 0) { + +#ifdef CDC_ENABLED + USB_Flush(CDC_TX); // Send a tx frame if found +#endif + + // check whether the one-shot period has elapsed. if so, turn off the LED + if (TxLEDPulse && !(--TxLEDPulse)) + TXLED0; + if (RxLEDPulse && !(--RxLEDPulse)) + RXLED0; + + // Acknowledge interrupt + UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_INT_SOF; + status &= ~UDPHS_IEN_INT_SOF; + } + // Suspend + // This interrupt is always treated last (hence the '==') + else if (status == UDPHS_IEN_DET_SUSPD) { + + //UDPHS_DisableBIAS(); + + // Enable wakeup + UDPHS->UDPHS_IEN |= UDPHS_IEN_WAKE_UP | UDPHS_IEN_ENDOFRSM; + UDPHS->UDPHS_IEN &= ~UDPHS_IEN_DET_SUSPD; + + // Acknowledge interrupt + UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_DET_SUSPD | UDPHS_CLRINT_WAKE_UP; + + //UDPHS_DisableUsbClock(); + + } + // Resume + else if( ((status & UDPHS_IEN_WAKE_UP) != 0) // line activity + || ((status & UDPHS_IEN_ENDOFRSM) != 0)) { // pc wakeup + { + + //UDPHS_EnableUsbClock(); + //UDPHS_EnableBIAS(); + + UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_WAKE_UP | UDPHS_CLRINT_ENDOFRSM + | UDPHS_CLRINT_DET_SUSPD; + + UDPHS->UDPHS_IEN |= UDPHS_IEN_ENDOFRSM | UDPHS_IEN_DET_SUSPD; + UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_WAKE_UP | UDPHS_CLRINT_ENDOFRSM; + UDPHS->UDPHS_IEN &= ~UDPHS_IEN_WAKE_UP; + } + } + // End of Reset + else if ((status & UDPHS_IEN_ENDRESET) == UDPHS_IEN_ENDRESET) { + + InitControl(0); // init ep0 + _usbConfiguration = 0; // not configured yet + //UEIENX = 1 << RXSTPE; // Enable interrupts for ep0 + + //UDPHS_ResetEndpoints(); + //UDPHS_DisableEndpoints(); + //USBD_ConfigureEndpoint(0); + UDPHS->UDPHS_IEN |= (1<UDPHS_CLRINT = UDPHS_CLRINT_WAKE_UP | UDPHS_CLRINT_DET_SUSPD; + + //// Enable the Start Of Frame (SOF) interrupt if needed + UDPHS->UDPHS_IEN |= UDPHS_IEN_INT_SOF; + + // Acknowledge end of bus reset interrupt + UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_ENDRESET; + + UDPHS->UDPHS_IEN |= UDPHS_IEN_DET_SUSPD; + } + // Handle upstream resume interrupt + else if (status & UDPHS_IEN_UPSTR_RES) { + + // - Acknowledge the IT + UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_UPSTR_RES; + } + // Endpoint interrupts + else { + // Handle endpoint interrupts + for (numIT = 0; numIT < NUM_IT_MAX; numIT++) { + + if ((status & (1 << SHIFT_INTERUPT << numIT)) != 0) { + USB_ISR(); + //EndpointHandler(numIT); // TODO: interrupt for bulk + } + } + } + // Retrieve new interrupt status + status = UDPHS->UDPHS_INTSTA & UDPHS->UDPHS_IEN; + } } // VBUS or counting frames @@ -618,6 +834,7 @@ u8 USBConnected() return f != UDFNUML; } + //======================================================================= //======================================================================= @@ -628,22 +845,53 @@ USB_::USB_() } void USB_::attach() -{ +{/* _usbConfiguration = 0; - UHWCON = 0x01; // power internal reg - USBCON = (1<PMC_PCER = (1 << ID_UDPHS); + // Enable 480MHZ + //AT91C_BASE_CKGR->CKGR_UCKR |= (AT91C_CKGR_PLLCOUNT & (3 << 20)) | AT91C_CKGR_UPLLEN; + CKGR->CKGR_UCKR |= ((0xf << 20) & (3 << 20)) | AT91C_CKGR_UPLLEN; + // Wait until UTMI PLL is locked + while ((PMC->PMC_SR & PMC_LOCKU) == 0); + + // Reset and enable IP UDPHS + UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_EN_UDPHS; + UDPHS->UDPHS_CTRL |= UDPHS_CTRL_EN_UDPHS; + + //USBCON = ((1<UDPHS_IEN = 0; + UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_UPSTR_RES + | UDPHS_CLRINT_ENDOFRSM + | UDPHS_CLRINT_WAKE_UP + | UDPHS_CLRINT_ENDRESET + | UDPHS_CLRINT_INT_SOF + | UDPHS_CLRINT_MICRO_SOF + | UDPHS_CLRINT_DET_SUSPD; + + // Enable interrupts for EOR (End of Reset), wake up and SOF (start of frame) + //UDIEN = (1<UDPHS_IEN = UDPHS_IEN_ENDOFRSM + | UDPHS_IEN_WAKE_UP + | UDPHS_IEN_DET_SUSPD; + + // enable attach resistor + //UDCON = 0; + UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_DETACH; // Pull Up on DP + UDPHS->UDPHS_CTRL |= UDPHS_CTRL_PULLD_DIS; // Disable Pull Down + TX_RX_LED_INIT; -} +*/} void USB_::detach() { + UDPHS->UDPHS_CTRL |= UDPHS_CTRL_DETACH; // detach + UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_PULLD_DIS; // Enable Pull Down } // Check for interrupts @@ -657,4 +905,6 @@ void USB_::poll() { } -#endif /* if defined(USBCON) */ \ No newline at end of file +#endif /* if defined(USBCON) */ + +#endif diff --git a/hardware/sam/cores/sam/USBCore.h b/hardware/sam/cores/sam/USBCore.h index 8d1380689..02558647d 100644 --- a/hardware/sam/cores/sam/USBCore.h +++ b/hardware/sam/cores/sam/USBCore.h @@ -248,6 +248,7 @@ typedef struct InterfaceDescriptor dif; EndpointDescriptor in; EndpointDescriptor out; + } CDCDescriptor; typedef struct @@ -300,4 +301,4 @@ typedef struct #define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 } -#endif \ No newline at end of file +#endif diff --git a/hardware/sam/cores/sam/USBDesc.h b/hardware/sam/cores/sam/USBDesc.h index 549ed9ea5..1c3b28a0c 100644 --- a/hardware/sam/cores/sam/USBDesc.h +++ b/hardware/sam/cores/sam/USBDesc.h @@ -39,9 +39,9 @@ #define CDC_ACM_INTERFACE 0 // CDC ACM #define CDC_DATA_INTERFACE 1 // CDC Data #define CDC_FIRST_ENDPOINT 1 -#define CDC_ENDPOINT_ACM (CDC_FIRST_ENDPOINT) // CDC First +#define CDC_ENDPOINT_IN (CDC_FIRST_ENDPOINT) // CDC First #define CDC_ENDPOINT_OUT (CDC_FIRST_ENDPOINT+1) -#define CDC_ENDPOINT_IN (CDC_FIRST_ENDPOINT+2) +#define CDC_ENDPOINT_ACM (CDC_FIRST_ENDPOINT+2) #define HID_INTERFACE (CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT) // HID Interface #define HID_FIRST_ENDPOINT (CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT) @@ -62,6 +62,7 @@ #define IPRODUCT 2 #define USB_PID_LEONARDO 0x0034 #define USB_PID_MICRO 0x0035 +#define ARDUINO_MODEL_USB_PID 0x0036 #define USB_VID 0x2341 // arduino LLC vid #define USB_PID ARDUINO_MODEL_USB_PID