From 1b591962f1d173ac6f1c9b7897dc872aa1cf0189 Mon Sep 17 00:00:00 2001 From: Thibaut VIARD Date: Thu, 29 Mar 2012 10:59:24 +0200 Subject: [PATCH] [sam] separating usb driver from core part --- hardware/arduino/sam/cores/sam/USBAPI.h | 4 +- hardware/arduino/sam/cores/sam/USBCore.cpp | 483 +---------------- .../sam/system/libsam/build_gcc/gcc.mk | 10 +- .../arduino/sam/system/libsam/include/udp.h | 22 + .../arduino/sam/system/libsam/include/udphs.h | 82 +++ .../sam/system/libsam/include/uotghs.h | 22 + .../arduino/sam/system/libsam/source/udp.c | 27 + .../arduino/sam/system/libsam/source/udphs.c | 503 ++++++++++++++++++ .../arduino/sam/system/libsam/source/uotghs.c | 27 + 9 files changed, 693 insertions(+), 487 deletions(-) create mode 100644 hardware/arduino/sam/system/libsam/include/udp.h create mode 100644 hardware/arduino/sam/system/libsam/include/udphs.h create mode 100644 hardware/arduino/sam/system/libsam/include/uotghs.h create mode 100644 hardware/arduino/sam/system/libsam/source/udp.c create mode 100644 hardware/arduino/sam/system/libsam/source/udphs.c create mode 100644 hardware/arduino/sam/system/libsam/source/uotghs.c diff --git a/hardware/arduino/sam/cores/sam/USBAPI.h b/hardware/arduino/sam/cores/sam/USBAPI.h index fdf4cd4fd..6d0e51447 100644 --- a/hardware/arduino/sam/cores/sam/USBAPI.h +++ b/hardware/arduino/sam/cores/sam/USBAPI.h @@ -161,6 +161,6 @@ int USB_Recv(uint8_t ep, void* data, int len); // non-blocking int USB_Recv(uint8_t ep); // non-blocking void USB_Flush(uint8_t ep); -#endif - #endif /* if defined(USBCON) */ + +#endif /* ifndef __USBAPI__ */ diff --git a/hardware/arduino/sam/cores/sam/USBCore.cpp b/hardware/arduino/sam/cores/sam/USBCore.cpp index 215f656f7..aedeeb760 100644 --- a/hardware/arduino/sam/cores/sam/USBCore.cpp +++ b/hardware/arduino/sam/cores/sam/USBCore.cpp @@ -16,7 +16,7 @@ ** SOFTWARE. */ #define USBCON -#if 0 + #include "Platform.h" #include "USBAPI.h" #include "USBDesc.h" @@ -25,48 +25,7 @@ #if defined(USBCON) -#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[] = @@ -138,344 +97,10 @@ 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; -} - -/* -static void UDPHS_ClearRxFlag( unsigned char bEndpoint ) -{ - 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; - - pFifo = (u8*)((u32 *)UDPHS_EPTFIFO + (EPT_VIRTUAL_SIZE * NumEndpoint)); - -// return UEDATX; - return (pFifo[0]); -} - -static inline void Send8(u8 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; - NumEndpoint = ep & 7; -} - -static inline u16 FifoByteCount() -{ -// 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 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() -{ - return UDFNUML; -} //================================================================== //================================================================== -u8 USBGetConfiguration(void) -{ - return _usbConfiguration; -} - -#define USB_RECV_TIMEOUT - -// Number of bytes, assumes a rx endpoint -u8 USB_Available(u8 ep) -{ - SetEP(ep); - return FifoByteCount(); -} - -// Non Blocking receive -// Return number of bytes read -int USB_Recv(u8 ep, void* d, int len) -{ - if (!_usbConfiguration || len < 0) - return -1; - - 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(); - - return len; -} - -// Recv 1 byte if ready -int USB_Recv(u8 ep) -{ - u8 c; - if (USB_Recv(ep,&c,1) != 1) - return -1; - return c; -} - -// Space in send EP -u8 USB_SendSpace(u8 ep) -{ - SetEP(ep); - if (!ReadWriteAllowed()) - return 0; - return 64 - FifoByteCount(); -} - -// Blocking Send of data to an endpoint -int USB_Send(u8 ep, const void* d, int len) -{ - if (!_usbConfiguration) - return -1; - - int r = len; - const u8* data = (const u8*)d; - u8 zero = ep & TRANSFER_ZERO; - u8 timeout = 250; // 250ms timeout on send? TODO - while (len) - { - u8 n = USB_SendSpace(ep); - if (n == 0) - { - if (!(--timeout)) - return -1; - delay(1); - continue; - } - - if (n > len) - n = len; - len -= n; - { - SetEP(ep); - if (ep & TRANSFER_ZERO) - { - while (n--) - Send8(0); - } - else if (ep & TRANSFER_PGM) - { - while (n--) - Send8(*data++); - } - else - { - while (n--) - Send8(*data++); - } -// if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE))) // Release full buffer -// ReleaseTX(); - } - } - TXLED1; // light the TX LED - TxLEDPulse = TX_RX_LED_PULSE_MS; - return r; -} - - -//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++) - { - // 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; -} - -// Handle CLASS_INTERFACE requests -static -bool ClassInterfaceRequest(Setup& setup) -{ - u8 i = setup.wIndex; - -#ifdef CDC_ENABLED - if (CDC_ACM_INTERFACE == i) - return CDC_Setup(setup); -#endif - -#ifdef HID_ENABLED - if (HID_INTERFACE == i) - return HID_Setup(setup); -#endif - return false; -} - -int _cmark; -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; -} - static bool SendControl(u8 d) { @@ -719,111 +344,7 @@ ISR(USB_GEN_vect) */ -//ISR(USB_GEN_vect) -void USB_GEN_ISR() -{ - unsigned int status; - unsigned char numIT; - // Get interrupts status - status = UDPHS->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 // Any frame counting? @@ -906,5 +427,3 @@ void USB_::poll() } #endif /* if defined(USBCON) */ - -#endif diff --git a/hardware/arduino/sam/system/libsam/build_gcc/gcc.mk b/hardware/arduino/sam/system/libsam/build_gcc/gcc.mk index fedb54215..8e3dd7c17 100644 --- a/hardware/arduino/sam/system/libsam/build_gcc/gcc.mk +++ b/hardware/arduino/sam/system/libsam/build_gcc/gcc.mk @@ -8,7 +8,7 @@ # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public @@ -32,8 +32,8 @@ endif SEP=/ - -# Flags +# --------------------------------------------------------------------------------------- +# C Flags CFLAGS += -Wall -Wchar-subscripts -Wcomment -Wformat=2 -Wimplicit-int CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses @@ -55,4 +55,8 @@ CFLAGS += -Dprintf=iprintf CFLAGS += --param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb -mlong-calls -ffunction-sections -std=c99 CFLAGS += $(OPTIMIZATION) $(INCLUDES) -D$(CHIP) + +# --------------------------------------------------------------------------------------- +# ASM Flags + ASFLAGS = -mcpu=cortex-m3 -mthumb -Wall -a -g $(INCLUDES) diff --git a/hardware/arduino/sam/system/libsam/include/udp.h b/hardware/arduino/sam/system/libsam/include/udp.h new file mode 100644 index 000000000..11bb326ab --- /dev/null +++ b/hardware/arduino/sam/system/libsam/include/udp.h @@ -0,0 +1,22 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef UDPHS_H_INCLUDED +#define UDPHS_H_INCLUDED + +#endif /* UDPHS_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/libsam/include/udphs.h b/hardware/arduino/sam/system/libsam/include/udphs.h new file mode 100644 index 000000000..7d823cbf7 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/include/udphs.h @@ -0,0 +1,82 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef UDPHS_H_INCLUDED +#define UDPHS_H_INCLUDED + +#include "arduino.h" + +#define NUM_IT_MAX 3 + +#define EP_SINGLE_64 0x32 // EP0 +#define EP_DOUBLE_64 0x36 // Other endpoints + + +// Endpoint 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 + + +#ifndef TXLED1 +#define TXLED0 +#define RXLED0 +#define TXLED1 +#define RXLED1 +#endif + + +#define UDFNUML ((UDPHS->UDPHS_FNUM & UDPHS_FNUM_FRAME_NUMBER_Msk)>>3) + +#define USB_RECV_TIMEOUT + +#define UDPHS_EPTFIFO (0x20180000) // (UDPHS_EPTFIFO) Base Address + +#endif /* UDPHS_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/libsam/include/uotghs.h b/hardware/arduino/sam/system/libsam/include/uotghs.h new file mode 100644 index 000000000..01de19e5f --- /dev/null +++ b/hardware/arduino/sam/system/libsam/include/uotghs.h @@ -0,0 +1,22 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef UOTGHS_H_INCLUDED +#define UOTGHS_H_INCLUDED + +#endif /* UOTGHS_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/libsam/source/udp.c b/hardware/arduino/sam/system/libsam/source/udp.c new file mode 100644 index 000000000..711569362 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/source/udp.c @@ -0,0 +1,27 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "Arduino.h" + +#if SAM3S_SERIES || SAM4S_SERIES + +#include "USB_driver.h" +#include "udp.h" + + +#endif /* SAM3S_SERIES || SAM4S_SERIES */ diff --git a/hardware/arduino/sam/system/libsam/source/udphs.c b/hardware/arduino/sam/system/libsam/source/udphs.c new file mode 100644 index 000000000..54a7228e2 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/source/udphs.c @@ -0,0 +1,503 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "Arduino.h" + +#if SAM3U_SERIES + +#include "USB_driver.h" +#include "udphs.h" + +/// Max size of the FMA FIFO +#define EPT_VIRTUAL_SIZE 16384 +#define SHIFT_INTERUPT 8 + +int _cmark; +int _cend; + +// Global variable for endpoint number +unsigned int NumEndpoint=0; + + +inline void usbd_WaitIN( void ) +{ +// while (!(UEINTX & (1<UDPHS_EPT[0].UDPHS_EPTSTA & UDPHS_EPTSTA_TX_PK_RDY)); +} + +inline void ClearIN( void ) +{ +// UEINTX = ~(1<UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TX_COMPLT; +} + +inline void WaitOUT( void ) +{ +// while (!(UEINTX & (1<UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_RX_BK_RDY)); +} + +inline u8 WaitForINOrOUT( void ) +{ +// 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; +} + +inline void ClearOUT(void) +{ +// UEINTX = ~(1<UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_BK_RDY; +} + +/* +void UDPHS_ClearRxFlag( unsigned char bEndpoint ) +{ + UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_BK_RDY; +} +*/ + +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; +} + + +inline u8 Recv8() +{ + u8 *pFifo; + + RXLED1; // light the RX LED + RxLEDPulse = TX_RX_LED_PULSE_MS; + + pFifo = (u8*)((u32 *)UDPHS_EPTFIFO + (EPT_VIRTUAL_SIZE * NumEndpoint)); + +// return UEDATX; + return (pFifo[0]); +} + +inline void Send8(u8 d) +{ + u8 *pFifo; + pFifo = (u8*)((u32 *)UDPHS_EPTFIFO + (EPT_VIRTUAL_SIZE * NumEndpoint)); +// UEDATX = d; + pFifo[0] =d; +} + +inline void SetEP(u8 ep) +{ +// UENUM = ep; + NumEndpoint = ep & 7; +} + +inline u16 FifoByteCount() +{ +// 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); +} + +inline u8 ReceivedSetupInt() +{ +// return UEINTX & (1<UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_RX_SETUP) ); +} + +inline void ClearSetupInt() +{ +// UEINTX = ~((1<UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTSTA_RX_SETUP | UDPHS_EPTCLRSTA_RX_BK_RDY | UDPHS_EPTCLRSTA_TX_COMPLT; +} + +inline void Stall() +{ +// UECONX = (1<UDPHS_EPT[NumEndpoint].UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_FRCESTALL; +} + +inline u8 ReadWriteAllowed() +{ + //return UEINTX & (1<UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_FRCESTALL)); +} + +u8 FifoFree() +{ +// return UEINTX & (1<UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_TX_PK_RDY )); +} + +//inline void ReleaseRX() +//{ +// UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1 +//} + +//inline void ReleaseTX() +//{ +// UEINTX = 0x3A; // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0 +//} + +inline u8 FrameNumber() +{ + return UDFNUML; +} + +u8 USBGetConfiguration(void) +{ + return _usbConfiguration; +} + +// Number of bytes, assumes a rx endpoint +u8 USB_Available(u8 ep) +{ + SetEP(ep); + return FifoByteCount(); +} + +// Non Blocking receive +// Return number of bytes read +int USBD_Recv(u8 ep, void* d, int len) +{ + if (!_usbConfiguration || len < 0) + return -1; + + 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(); + + return len; +} + +// Recv 1 byte if ready +int USBD_Recv(u8 ep) +{ + u8 c; + if (USB_Recv(ep,&c,1) != 1) + return -1; + return c; +} + +// Space in send EP +u8 USB_SendSpace(u8 ep) +{ + SetEP(ep); + if (!ReadWriteAllowed()) + return 0; + return 64 - FifoByteCount(); +} + +// Blocking Send of data to an endpoint +int USB_Send(u8 ep, const void* d, int len) +{ + if (!_usbConfiguration) + return -1; + + int r = len; + const u8* data = (const u8*)d; + u8 zero = ep & TRANSFER_ZERO; + u8 timeout = 250; // 250ms timeout on send? TODO + while (len) + { + u8 n = USB_SendSpace(ep); + if (n == 0) + { + if (!(--timeout)) + return -1; + delay(1); + continue; + } + + if (n > len) + n = len; + len -= n; + { + SetEP(ep); + if (ep & TRANSFER_ZERO) + { + while (n--) + Send8(0); + } + else if (ep & TRANSFER_PGM) + { + while (n--) + Send8(*data++); + } + else + { + while (n--) + Send8(*data++); + } +// if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE))) // Release full buffer +// ReleaseTX(); + } + } + TXLED1; // light the TX LED + TxLEDPulse = TX_RX_LED_PULSE_MS; + return r; +} + + +//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++) + { + // 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; +} + +// Handle CLASS_INTERFACE requests +static +bool ClassInterfaceRequest(Setup& setup) +{ + u8 i = setup.wIndex; + +#ifdef CDC_ENABLED + if (CDC_ACM_INTERFACE == i) + return CDC_Setup(setup); +#endif + +#ifdef HID_ENABLED + if (HID_INTERFACE == i) + return HID_Setup(setup); +#endif + return false; +} + + +void USBD_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; +} + +void UDPHS_Handler( void ) +{ + unsigned int status; + unsigned char numIT; + + // Get interrupts status + status = UDPHS->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; + } +} + +void usbd_attach( void ) +{/* + _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 usbd_detach( void ) +{ + UDPHS->UDPHS_CTRL |= UDPHS_CTRL_DETACH; // detach + UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_PULLD_DIS; // Enable Pull Down +} + +#endif /* SAM3U_SERIES */ diff --git a/hardware/arduino/sam/system/libsam/source/uotghs.c b/hardware/arduino/sam/system/libsam/source/uotghs.c new file mode 100644 index 000000000..303121678 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/source/uotghs.c @@ -0,0 +1,27 @@ +/* + Copyright (c) 2012 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "Arduino.h" + +#if SAM3XA_SERIES + +#include "USB_driver.h" +#include "uotghs.h" + + +#endif /* SAM3XA_SERIES */