USB Core porting WIP

This commit is contained in:
Cristian Maglie 2011-12-22 21:29:14 +01:00
parent 7d7da2d826
commit 668345cdf3
4 changed files with 415 additions and 163 deletions

View File

@ -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) */
#endif /* if defined(USBCON) */

View File

@ -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<<TXINI)));
// while (!(UEINTX & (1<<TXINI)));
while (!(UDPHS->UDPHS_EPT[0].UDPHS_EPTSTA & UDPHS_EPTSTA_TX_PK_RDY));
}
static inline void ClearIN(void)
{
UEINTX = ~(1<<TXINI);
// UEINTX = ~(1<<TXINI);
UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TX_COMPLT;
}
static inline void WaitOUT(void)
{
while (!(UEINTX & (1<<RXOUTI)))
;
// while (!(UEINTX & (1<<RXOUTI)))
// ;
// Waiting for Status stage
while (UDPHS_EPTSTA_RX_BK_RDY != (UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_RX_BK_RDY));
}
static inline u8 WaitForINOrOUT()
{
while (!(UEINTX & ((1<<TXINI)|(1<<RXOUTI))))
;
return (UEINTX & (1<<RXOUTI)) == 0;
// while (!(UEINTX & ((1<<TXINI)|(1<<RXOUTI))))
// ;
// return (UEINTX & (1<<RXOUTI)) == 0;
while (!(UDPHS->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<<RXOUTI);
// UEINTX = ~(1<<RXOUTI);
UDPHS->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<<RXSTPI);
// return UEINTX & (1<<RXSTPI);
return ( UDPHS_EPTSTA_RX_SETUP == (UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_RX_SETUP) );
}
static inline void ClearSetupInt()
{
UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
// UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTSTA_RX_SETUP | UDPHS_EPTCLRSTA_RX_BK_RDY | UDPHS_EPTCLRSTA_TX_COMPLT;
}
static inline void Stall()
{
UECONX = (1<<STALLRQ) | (1<<EPEN);
// UECONX = (1<<STALLRQ) | (1<<EPEN);
UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_FRCESTALL;
}
static inline u8 ReadWriteAllowed()
{
return UEINTX & (1<<RWAL);
//return UEINTX & (1<<RWAL);
return 1;
}
static inline u8 Stalled()
{
return UEINTX & (1<<STALLEDI);
// return UEINTX & (1<<STALLEDI);
// Check if the data has been STALLed
return ( UDPHS_EPTSTA_FRCESTALL == (UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_FRCESTALL));
}
static inline u8 FifoFree()
{
return UEINTX & (1<<FIFOCON);
// return UEINTX & (1<<FIFOCON);
return( 0 != (UDPHS->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<<i;
//UECONX = 1;
//UECFG0X = pgm_read_byte(_initEndpoints+i);
UDPHS->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<<ADDEN);
UDPHS->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<<EORSTI))
{
InitEP(0,EP_TYPE_CONTROL,EP_SINGLE_64); // init ep0
_usbConfiguration = 0; // not configured yet
UEIENX = 1 << RXSTPE; // Enable interrupts for ep0
}
// End of Reset
if (udint & (1<<EORSTI))
{
InitEP(0,EP_TYPE_CONTROL,EP_SINGLE_64); // init ep0
_usbConfiguration = 0; // not configured yet
UEIENX = 1 << RXSTPE; // Enable interrupts for ep0
}
// Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too
if (udint & (1<<SOFI))
{
// Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too
if (udint & (1<<SOFI))
{
#ifdef CDC_ENABLED
USB_Flush(CDC_TX); // Send a tx frame if found
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;
}
// check whether the one-shot period has elapsed. if so, turn off the LED
if (TxLEDPulse && !(--TxLEDPulse))
TXLED0;
if (RxLEDPulse && !(--RxLEDPulse))
RXLED0;
}
}
*/
//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<<SHIFT_INTERUPT<<0);
// Flush and enable the Suspend interrupt
UDPHS->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<<USBE)|(1<<FRZCLK); // clock frozen, usb enabled
PLLCSR = 0x12; // Need 16 MHz xtal
while (!(PLLCSR & (1<<PLOCK))) // wait for lock pll
;
USBCON = ((1<<USBE)|(1<<OTGPADE)); // start USB clock
UDIEN = (1<<EORSTE)|(1<<SOFE); // Enable interrupts for EOR (End of Reset) and SOF (start of frame)
UDCON = 0; // enable attach resistor
//UHWCON = 0x01; // power internal reg
//USBCON = (1<<USBE)|(1<<FRZCLK); // clock frozen, usb enabled
//PLLCSR = 0x12; // Need 16 MHz xtal
//while (!(PLLCSR & (1<<PLOCK))) // wait for lock pll
// ;
PMC->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<<USBE)|(1<<OTGPADE)); // start USB clock
UDPHS->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<<EORSTE)|(1<<SOFE);
UDPHS->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) */
#endif /* if defined(USBCON) */
#endif

View File

@ -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
#endif

View File

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