mirror of
https://github.com/esp8266/Arduino.git
synced 2025-10-15 11:26:40 +03:00
[sam] USB Host stack v1 with enumeration working okay using validation example
This commit is contained in:
@@ -1,295 +0,0 @@
|
||||
/* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */
|
||||
/* MAX3421E USB host controller support */
|
||||
|
||||
#include "Max3421e.h"
|
||||
// #include "Max3421e_constants.h"
|
||||
|
||||
static byte vbusState;
|
||||
|
||||
/* Functions */
|
||||
|
||||
/* Constructor */
|
||||
MAX3421E::MAX3421E()
|
||||
{
|
||||
spi_init();
|
||||
#if !defined(TARGET_MEGA_ADK)
|
||||
pinMode( MAX_INT, INPUT);
|
||||
pinMode( MAX_GPX, INPUT );
|
||||
#else
|
||||
// "Internal" pins so can't use Arduino helper functions.
|
||||
INT_DDR &= ~_BV(INT);
|
||||
GPX_DDR &= ~_BV(GPX);
|
||||
#endif
|
||||
pinMode( MAX_SS, OUTPUT );
|
||||
digitalWrite(MAX_SS,HIGH);
|
||||
#if !defined(TARGET_MEGA_ADK)
|
||||
pinMode( MAX_RESET, OUTPUT );
|
||||
digitalWrite( MAX_RESET, HIGH ); //release MAX3421E from reset
|
||||
#else
|
||||
// "Internal" pins so can't use Arduino helper functions.
|
||||
RST_DDR |= _BV(RST);
|
||||
RST_PORT |= _BV(RST); // Equivalent to setRST(HIGH) from old code.
|
||||
#endif
|
||||
}
|
||||
|
||||
byte MAX3421E::getVbusState( void )
|
||||
{
|
||||
return( vbusState );
|
||||
}
|
||||
/* initialization */
|
||||
//void MAX3421E::init()
|
||||
//{
|
||||
// /* setup pins */
|
||||
// pinMode( MAX_INT, INPUT);
|
||||
// pinMode( MAX_GPX, INPUT );
|
||||
// pinMode( MAX_SS, OUTPUT );
|
||||
// //pinMode( BPNT_0, OUTPUT );
|
||||
// //pinMode( BPNT_1, OUTPUT );
|
||||
// //digitalWrite( BPNT_0, LOW );
|
||||
// //digitalWrite( BPNT_1, LOW );
|
||||
// Deselect_MAX3421E;
|
||||
// pinMode( MAX_RESET, OUTPUT );
|
||||
// digitalWrite( MAX_RESET, HIGH ); //release MAX3421E from reset
|
||||
//}
|
||||
//byte MAX3421E::getVbusState( void )
|
||||
//{
|
||||
// return( vbusState );
|
||||
//}
|
||||
//void MAX3421E::toggle( byte pin )
|
||||
//{
|
||||
// digitalWrite( pin, HIGH );
|
||||
// digitalWrite( pin, LOW );
|
||||
//}
|
||||
/* Single host register write */
|
||||
void MAX3421E::regWr( byte reg, byte val)
|
||||
{
|
||||
digitalWrite(MAX_SS,LOW);
|
||||
SPDR = ( reg | 0x02 );
|
||||
while(!( SPSR & ( 1 << SPIF )));
|
||||
SPDR = val;
|
||||
while(!( SPSR & ( 1 << SPIF )));
|
||||
digitalWrite(MAX_SS,HIGH);
|
||||
return;
|
||||
}
|
||||
/* multiple-byte write */
|
||||
/* returns a pointer to a memory position after last written */
|
||||
char * MAX3421E::bytesWr( byte reg, byte nbytes, char * data )
|
||||
{
|
||||
digitalWrite(MAX_SS,LOW);
|
||||
SPDR = ( reg | 0x02 );
|
||||
while( nbytes-- ) {
|
||||
while(!( SPSR & ( 1 << SPIF ))); //check if previous byte was sent
|
||||
SPDR = ( *data ); // send next data byte
|
||||
data++; // advance data pointer
|
||||
}
|
||||
while(!( SPSR & ( 1 << SPIF )));
|
||||
digitalWrite(MAX_SS,HIGH);
|
||||
return( data );
|
||||
}
|
||||
/* GPIO write. GPIO byte is split between 2 registers, so two writes are needed to write one byte */
|
||||
/* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */
|
||||
/* upper 4 bits of IOPINS1, IOPINS2 are read-only, so no masking is necessary */
|
||||
void MAX3421E::gpioWr( byte val )
|
||||
{
|
||||
regWr( rIOPINS1, val );
|
||||
val = val >>4;
|
||||
regWr( rIOPINS2, val );
|
||||
|
||||
return;
|
||||
}
|
||||
/* Single host register read */
|
||||
byte MAX3421E::regRd( byte reg )
|
||||
{
|
||||
byte tmp;
|
||||
digitalWrite(MAX_SS,LOW);
|
||||
SPDR = reg;
|
||||
while(!( SPSR & ( 1 << SPIF )));
|
||||
SPDR = 0; //send empty byte
|
||||
while(!( SPSR & ( 1 << SPIF )));
|
||||
digitalWrite(MAX_SS,HIGH);
|
||||
return( SPDR );
|
||||
}
|
||||
/* multiple-bytes register read */
|
||||
/* returns a pointer to a memory position after last read */
|
||||
char * MAX3421E::bytesRd ( byte reg, byte nbytes, char * data )
|
||||
{
|
||||
digitalWrite(MAX_SS,LOW);
|
||||
SPDR = reg;
|
||||
while(!( SPSR & ( 1 << SPIF ))); //wait
|
||||
while( nbytes ) {
|
||||
SPDR = 0; //send empty byte
|
||||
nbytes--;
|
||||
while(!( SPSR & ( 1 << SPIF )));
|
||||
*data = SPDR;
|
||||
data++;
|
||||
}
|
||||
digitalWrite(MAX_SS,HIGH);
|
||||
return( data );
|
||||
}
|
||||
/* GPIO read. See gpioWr for explanation */
|
||||
/* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */
|
||||
byte MAX3421E::gpioRd( void )
|
||||
{
|
||||
byte tmpbyte = 0;
|
||||
tmpbyte = regRd( rIOPINS2 ); //pins 4-7
|
||||
tmpbyte &= 0xf0; //clean lower nibble
|
||||
tmpbyte |= ( regRd( rIOPINS1 ) >>4 ) ; //shift low bits and OR with upper from previous operation. Upper nibble zeroes during shift, at least with this compiler
|
||||
return( tmpbyte );
|
||||
}
|
||||
/* reset MAX3421E using chip reset bit. SPI configuration is not affected */
|
||||
boolean MAX3421E::reset()
|
||||
{
|
||||
unsigned short tmp = 0;
|
||||
regWr( rUSBCTL, bmCHIPRES ); //Chip reset. This stops the oscillator
|
||||
regWr( rUSBCTL, 0x00 ); //Remove the reset
|
||||
while(!(regRd( rUSBIRQ ) & bmOSCOKIRQ )) { //wait until the PLL is stable
|
||||
tmp++; //timeout after 256 attempts
|
||||
if( tmp == 0 ) {
|
||||
return( false );
|
||||
}
|
||||
}
|
||||
return( true );
|
||||
}
|
||||
/* turn USB power on/off */
|
||||
/* does nothing, returns TRUE. Left for compatibility with old sketches */
|
||||
/* will be deleted eventually */
|
||||
///* ON pin of VBUS switch (MAX4793 or similar) is connected to GPOUT7 */
|
||||
///* OVERLOAD pin of Vbus switch is connected to GPIN7 */
|
||||
///* OVERLOAD state low. NO OVERLOAD or VBUS OFF state high. */
|
||||
boolean MAX3421E::vbusPwr ( boolean action )
|
||||
{
|
||||
// byte tmp;
|
||||
// tmp = regRd( rIOPINS2 ); //copy of IOPINS2
|
||||
// if( action ) { //turn on by setting GPOUT7
|
||||
// tmp |= bmGPOUT7;
|
||||
// }
|
||||
// else { //turn off by clearing GPOUT7
|
||||
// tmp &= ~bmGPOUT7;
|
||||
// }
|
||||
// regWr( rIOPINS2, tmp ); //send GPOUT7
|
||||
// if( action ) {
|
||||
// delay( 60 );
|
||||
// }
|
||||
// if (( regRd( rIOPINS2 ) & bmGPIN7 ) == 0 ) { // check if overload is present. MAX4793 /FLAG ( pin 4 ) goes low if overload
|
||||
// return( false );
|
||||
// }
|
||||
return( true ); // power on/off successful
|
||||
}
|
||||
/* probe bus to determine device presense and speed and switch host to this speed */
|
||||
void MAX3421E::busprobe( void )
|
||||
{
|
||||
byte bus_sample;
|
||||
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 ):
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case( bmKSTATUS ):
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case( bmSE1 ): //illegal state
|
||||
vbusState = SE1;
|
||||
break;
|
||||
case( bmSE0 ): //disconnected state
|
||||
regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST|bmSEPIRQ);
|
||||
vbusState = SE0;
|
||||
break;
|
||||
}//end switch( bus_sample )
|
||||
}
|
||||
/* MAX3421E initialization after power-on */
|
||||
void MAX3421E::powerOn()
|
||||
{
|
||||
/* Configure full-duplex SPI, interrupt pulse */
|
||||
regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL + bmGPXB )); //Full-duplex SPI, level interrupt, GPX
|
||||
if( reset() == false ) { //stop/start the oscillator
|
||||
Serial.println("Error: OSCOKIRQ failed to assert");
|
||||
}
|
||||
|
||||
/* configure host operation */
|
||||
regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST|bmSEPIRQ ); // set pull-downs, Host, Separate GPIN IRQ on GPX
|
||||
regWr( rHIEN, bmCONDETIE|bmFRAMEIE ); //connection detection
|
||||
/* check if device is connected */
|
||||
regWr( rHCTL,bmSAMPLEBUS ); // sample USB bus
|
||||
while(!(regRd( rHCTL ) & bmSAMPLEBUS )); //wait for sample operation to finish
|
||||
busprobe(); //check if anything is connected
|
||||
regWr( rHIRQ, bmCONDETIRQ ); //clear connection detect interrupt
|
||||
regWr( rCPUCTL, 0x01 ); //enable interrupt pin
|
||||
}
|
||||
/* MAX3421 state change task and interrupt handler */
|
||||
byte MAX3421E::Task( void )
|
||||
{
|
||||
byte rcode = 0;
|
||||
byte pinvalue;
|
||||
//Serial.print("Vbus state: ");
|
||||
//Serial.println( vbusState, HEX );
|
||||
|
||||
#if !defined(TARGET_MEGA_ADK)
|
||||
pinvalue = digitalRead( MAX_INT );
|
||||
#else
|
||||
// "Internal" pin so can't use Arduino helper functions.
|
||||
pinvalue = INT_PIN & _BV(INT) ? HIGH : LOW; // from old `readINT()`
|
||||
#endif
|
||||
if( pinvalue == LOW ) {
|
||||
rcode = IntHandler();
|
||||
}
|
||||
|
||||
#if !defined(TARGET_MEGA_ADK)
|
||||
pinvalue = digitalRead( MAX_GPX );
|
||||
#else
|
||||
// "Internal" pin so can't use Arduino helper functions.
|
||||
pinvalue = GPX_PIN & _BV(GPX) ? HIGH : LOW; // from old `readGPX()`
|
||||
#endif
|
||||
if( pinvalue == LOW ) {
|
||||
GpxHandler();
|
||||
}
|
||||
// usbSM(); //USB state machine
|
||||
return( rcode );
|
||||
}
|
||||
byte MAX3421E::IntHandler()
|
||||
{
|
||||
byte HIRQ;
|
||||
byte HIRQ_sendback = 0x00;
|
||||
HIRQ = regRd( rHIRQ ); //determine interrupt source
|
||||
//if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler
|
||||
// HIRQ_sendback |= bmFRAMEIRQ;
|
||||
//}//end FRAMEIRQ handling
|
||||
if( HIRQ & bmCONDETIRQ ) {
|
||||
busprobe();
|
||||
HIRQ_sendback |= bmCONDETIRQ;
|
||||
}
|
||||
/* End HIRQ interrupts handling, clear serviced IRQs */
|
||||
regWr( rHIRQ, HIRQ_sendback );
|
||||
return( HIRQ_sendback );
|
||||
}
|
||||
byte MAX3421E::GpxHandler()
|
||||
{
|
||||
byte GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register
|
||||
// if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload
|
||||
// vbusPwr( OFF ); //attempt powercycle
|
||||
// delay( 1000 );
|
||||
// vbusPwr( ON );
|
||||
// regWr( rGPINIRQ, bmGPINIRQ7 );
|
||||
// }
|
||||
return( GPINIRQ );
|
||||
}
|
||||
|
||||
//void MAX3421E::usbSM( void ) //USB state machine
|
||||
//{
|
||||
//
|
||||
//
|
||||
//}
|
@@ -1,54 +0,0 @@
|
||||
/* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */
|
||||
/* MAX3421E functions */
|
||||
#ifndef _MAX3421E_H_
|
||||
#define _MAX3421E_H_
|
||||
|
||||
|
||||
//#include <Spi.h>
|
||||
//#include <WProgram.h>
|
||||
#include "Arduino.h"
|
||||
#include "Max3421e_constants.h"
|
||||
|
||||
class MAX3421E /* : public SPI */ {
|
||||
// byte vbusState;
|
||||
public:
|
||||
MAX3421E( void );
|
||||
byte getVbusState( void );
|
||||
// void toggle( byte pin );
|
||||
static void regWr( byte, byte );
|
||||
char * bytesWr( byte, byte, char * );
|
||||
static void gpioWr( byte );
|
||||
byte regRd( byte );
|
||||
char * bytesRd( byte, byte, char * );
|
||||
byte gpioRd( void );
|
||||
boolean reset();
|
||||
boolean vbusPwr ( boolean );
|
||||
void busprobe( void );
|
||||
void powerOn();
|
||||
byte IntHandler();
|
||||
byte GpxHandler();
|
||||
byte Task();
|
||||
private:
|
||||
static void spi_init() {
|
||||
uint8_t tmp;
|
||||
// initialize SPI pins
|
||||
pinMode(SCK_PIN, OUTPUT);
|
||||
pinMode(MOSI_PIN, OUTPUT);
|
||||
pinMode(MISO_PIN, INPUT);
|
||||
pinMode(SS_PIN, OUTPUT);
|
||||
digitalWrite( SS_PIN, HIGH );
|
||||
/* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */
|
||||
SPCR = 0x50;
|
||||
SPSR = 0x01;
|
||||
/**/
|
||||
tmp = SPSR;
|
||||
tmp = SPDR;
|
||||
}
|
||||
// void init();
|
||||
friend class Max_LCD;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //_MAX3421E_H_
|
@@ -1,273 +0,0 @@
|
||||
/* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */
|
||||
/* MAX3421E register/bit names and bitmasks */
|
||||
|
||||
#ifndef _MAX3421Econstants_h_
|
||||
#define _MAX3421Econstants_h_
|
||||
|
||||
/* SPI pins for diffrent Arduinos */
|
||||
|
||||
#define MEGA256_IS_ADK // Undefine this if you're using a non-ADK Mega256
|
||||
|
||||
// TODO: Check if the 2560 check should use `defined` too.
|
||||
#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__)
|
||||
#define SCK_PIN 52
|
||||
#define MISO_PIN 50
|
||||
#define MOSI_PIN 51
|
||||
#if defined(__AVR_ATmega2560__) && defined(MEGA256_IS_ADK)
|
||||
#define TARGET_MEGA_ADK
|
||||
#define SS_PIN 53 // TODO: Handle this as an internal pin.
|
||||
#else
|
||||
// TODO: Test with Mega + shield combination
|
||||
#define SS_PIN 53
|
||||
#endif
|
||||
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
|
||||
#define SCK_PIN 13
|
||||
#define MISO_PIN 12
|
||||
#define MOSI_PIN 11
|
||||
#define SS_PIN 10
|
||||
#else
|
||||
#error The currently selected board needs to have its SPI pin definitions added to this file.
|
||||
#endif
|
||||
|
||||
#if !defined(TARGET_MEGA_ADK)
|
||||
#define MAX_SS SS_PIN
|
||||
#define MAX_INT 9
|
||||
#define MAX_GPX 8
|
||||
#define MAX_RESET 7
|
||||
#else
|
||||
// Because the Arduino Mega ADK board uses "internal" pins (i.e. ones that
|
||||
// are not broken out to headers, are not in `pins_arduino.h` and can't
|
||||
// be used with functions like `pinMode()` & `digitalWrite()`) they need
|
||||
// to be defined by the low-level AVR approach.
|
||||
// These definitions and the code to use them comes from an older version
|
||||
// of the `Max3421e.cpp` file.
|
||||
// TODO: Add these internal pins to `pins_arduino.h` for the Mega ADK so
|
||||
// we can usual the standard Arduino functions & not special-case this?
|
||||
#define INT PE6
|
||||
#define INT_PORT PORTE
|
||||
#define INT_DDR DDRE
|
||||
#define INT_PIN PINE
|
||||
|
||||
#define RST PJ2
|
||||
#define RST_PORT PORTJ
|
||||
#define RST_DDR DDRJ
|
||||
#define RST_PIN PINJ
|
||||
|
||||
#define GPX PJ3
|
||||
#define GPX_PORT PORTJ
|
||||
#define GPX_DDR DDRJ
|
||||
#define GPX_PIN PINJ
|
||||
|
||||
#define MAX_SS SS_PIN // TODO: Handle this as an internal pin.
|
||||
#endif
|
||||
|
||||
/* "Breakpoint" pins for debugging */
|
||||
//#define BPNT_0 3
|
||||
//#define BPNT_1 2
|
||||
|
||||
//#define Select_MAX3421E digitalWrite(MAX_SS,LOW)
|
||||
//#define Deselect_MAX3421E digitalWrite(MAX_SS,HIGH)
|
||||
|
||||
/* */
|
||||
|
||||
#define ON true
|
||||
#define OFF false
|
||||
|
||||
/* VBUS states */
|
||||
#define SE0 0
|
||||
#define SE1 1
|
||||
#define FSHOST 2
|
||||
#define LSHOST 3
|
||||
|
||||
/* MAX3421E command byte format: rrrrr0wa where 'r' is register number */
|
||||
//
|
||||
// MAX3421E Registers in HOST mode.
|
||||
//
|
||||
#define rRCVFIFO 0x08 //1<<3
|
||||
#define rSNDFIFO 0x10 //2<<3
|
||||
#define rSUDFIFO 0x20 //4<<3
|
||||
#define rRCVBC 0x30 //6<<3
|
||||
#define rSNDBC 0x38 //7<<3
|
||||
|
||||
#define rUSBIRQ 0x68 //13<<3
|
||||
/* USBIRQ Bits */
|
||||
#define bmVBUSIRQ 0x40 //b6
|
||||
#define bmNOVBUSIRQ 0x20 //b5
|
||||
#define bmOSCOKIRQ 0x01 //b0
|
||||
|
||||
#define rUSBIEN 0x70 //14<<3
|
||||
/* USBIEN Bits */
|
||||
#define bmVBUSIE 0x40 //b6
|
||||
#define bmNOVBUSIE 0x20 //b5
|
||||
#define bmOSCOKIE 0x01 //b0
|
||||
|
||||
#define rUSBCTL 0x78 //15<<3
|
||||
/* USBCTL Bits */
|
||||
#define bmCHIPRES 0x20 //b5
|
||||
#define bmPWRDOWN 0x10 //b4
|
||||
|
||||
#define rCPUCTL 0x80 //16<<3
|
||||
/* CPUCTL Bits */
|
||||
#define bmPUSLEWID1 0x80 //b7
|
||||
#define bmPULSEWID0 0x40 //b6
|
||||
#define bmIE 0x01 //b0
|
||||
|
||||
#define rPINCTL 0x88 //17<<3
|
||||
/* PINCTL Bits */
|
||||
#define bmFDUPSPI 0x10 //b4
|
||||
#define bmINTLEVEL 0x08 //b3
|
||||
#define bmPOSINT 0x04 //b2
|
||||
#define bmGPXB 0x02 //b1
|
||||
#define bmGPXA 0x01 //b0
|
||||
// GPX pin selections
|
||||
#define GPX_OPERATE 0x00
|
||||
#define GPX_VBDET 0x01
|
||||
#define GPX_BUSACT 0x02
|
||||
#define GPX_SOF 0x03
|
||||
|
||||
#define rREVISION 0x90 //18<<3
|
||||
|
||||
#define rIOPINS1 0xa0 //20<<3
|
||||
|
||||
/* IOPINS1 Bits */
|
||||
#define bmGPOUT0 0x01
|
||||
#define bmGPOUT1 0x02
|
||||
#define bmGPOUT2 0x04
|
||||
#define bmGPOUT3 0x08
|
||||
#define bmGPIN0 0x10
|
||||
#define bmGPIN1 0x20
|
||||
#define bmGPIN2 0x40
|
||||
#define bmGPIN3 0x80
|
||||
|
||||
#define rIOPINS2 0xa8 //21<<3
|
||||
/* IOPINS2 Bits */
|
||||
#define bmGPOUT4 0x01
|
||||
#define bmGPOUT5 0x02
|
||||
#define bmGPOUT6 0x04
|
||||
#define bmGPOUT7 0x08
|
||||
#define bmGPIN4 0x10
|
||||
#define bmGPIN5 0x20
|
||||
#define bmGPIN6 0x40
|
||||
#define bmGPIN7 0x80
|
||||
|
||||
#define rGPINIRQ 0xb0 //22<<3
|
||||
/* GPINIRQ Bits */
|
||||
#define bmGPINIRQ0 0x01
|
||||
#define bmGPINIRQ1 0x02
|
||||
#define bmGPINIRQ2 0x04
|
||||
#define bmGPINIRQ3 0x08
|
||||
#define bmGPINIRQ4 0x10
|
||||
#define bmGPINIRQ5 0x20
|
||||
#define bmGPINIRQ6 0x40
|
||||
#define bmGPINIRQ7 0x80
|
||||
|
||||
#define rGPINIEN 0xb8 //23<<3
|
||||
/* GPINIEN Bits */
|
||||
#define bmGPINIEN0 0x01
|
||||
#define bmGPINIEN1 0x02
|
||||
#define bmGPINIEN2 0x04
|
||||
#define bmGPINIEN3 0x08
|
||||
#define bmGPINIEN4 0x10
|
||||
#define bmGPINIEN5 0x20
|
||||
#define bmGPINIEN6 0x40
|
||||
#define bmGPINIEN7 0x80
|
||||
|
||||
#define rGPINPOL 0xc0 //24<<3
|
||||
/* GPINPOL Bits */
|
||||
#define bmGPINPOL0 0x01
|
||||
#define bmGPINPOL1 0x02
|
||||
#define bmGPINPOL2 0x04
|
||||
#define bmGPINPOL3 0x08
|
||||
#define bmGPINPOL4 0x10
|
||||
#define bmGPINPOL5 0x20
|
||||
#define bmGPINPOL6 0x40
|
||||
#define bmGPINPOL7 0x80
|
||||
|
||||
#define rHIRQ 0xc8 //25<<3
|
||||
/* HIRQ Bits */
|
||||
#define bmBUSEVENTIRQ 0x01 // indicates BUS Reset Done or BUS Resume
|
||||
#define bmRWUIRQ 0x02
|
||||
#define bmRCVDAVIRQ 0x04
|
||||
#define bmSNDBAVIRQ 0x08
|
||||
#define bmSUSDNIRQ 0x10
|
||||
#define bmCONDETIRQ 0x20
|
||||
#define bmFRAMEIRQ 0x40
|
||||
#define bmHXFRDNIRQ 0x80
|
||||
|
||||
#define rHIEN 0xd0 //26<<3
|
||||
/* HIEN Bits */
|
||||
#define bmBUSEVENTIE 0x01
|
||||
#define bmRWUIE 0x02
|
||||
#define bmRCVDAVIE 0x04
|
||||
#define bmSNDBAVIE 0x08
|
||||
#define bmSUSDNIE 0x10
|
||||
#define bmCONDETIE 0x20
|
||||
#define bmFRAMEIE 0x40
|
||||
#define bmHXFRDNIE 0x80
|
||||
|
||||
#define rMODE 0xd8 //27<<3
|
||||
/* MODE Bits */
|
||||
#define bmHOST 0x01
|
||||
#define bmLOWSPEED 0x02
|
||||
#define bmHUBPRE 0x04
|
||||
#define bmSOFKAENAB 0x08
|
||||
#define bmSEPIRQ 0x10
|
||||
#define bmDELAYISO 0x20
|
||||
#define bmDMPULLDN 0x40
|
||||
#define bmDPPULLDN 0x80
|
||||
|
||||
#define rPERADDR 0xe0 //28<<3
|
||||
|
||||
#define rHCTL 0xe8 //29<<3
|
||||
/* HCTL Bits */
|
||||
#define bmBUSRST 0x01
|
||||
#define bmFRMRST 0x02
|
||||
#define bmSAMPLEBUS 0x04
|
||||
#define bmSIGRSM 0x08
|
||||
#define bmRCVTOG0 0x10
|
||||
#define bmRCVTOG1 0x20
|
||||
#define bmSNDTOG0 0x40
|
||||
#define bmSNDTOG1 0x80
|
||||
|
||||
#define rHXFR 0xf0 //30<<3
|
||||
/* Host transfer token values for writing the HXFR register (R30) */
|
||||
/* OR this bit field with the endpoint number in bits 3:0 */
|
||||
#define tokSETUP 0x10 // HS=0, ISO=0, OUTNIN=0, SETUP=1
|
||||
#define tokIN 0x00 // HS=0, ISO=0, OUTNIN=0, SETUP=0
|
||||
#define tokOUT 0x20 // HS=0, ISO=0, OUTNIN=1, SETUP=0
|
||||
#define tokINHS 0x80 // HS=1, ISO=0, OUTNIN=0, SETUP=0
|
||||
#define tokOUTHS 0xA0 // HS=1, ISO=0, OUTNIN=1, SETUP=0
|
||||
#define tokISOIN 0x40 // HS=0, ISO=1, OUTNIN=0, SETUP=0
|
||||
#define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0
|
||||
|
||||
#define rHRSL 0xf8 //31<<3
|
||||
/* HRSL Bits */
|
||||
#define bmRCVTOGRD 0x10
|
||||
#define bmSNDTOGRD 0x20
|
||||
#define bmKSTATUS 0x40
|
||||
#define bmJSTATUS 0x80
|
||||
#define bmSE0 0x00 //SE0 - disconnect state
|
||||
#define bmSE1 0xc0 //SE1 - illegal state
|
||||
/* Host error result codes, the 4 LSB's in the HRSL register */
|
||||
#define hrSUCCESS 0x00
|
||||
#define hrBUSY 0x01
|
||||
#define hrBADREQ 0x02
|
||||
#define hrUNDEF 0x03
|
||||
#define hrNAK 0x04
|
||||
#define hrSTALL 0x05
|
||||
#define hrTOGERR 0x06
|
||||
#define hrWRONGPID 0x07
|
||||
#define hrBADBC 0x08
|
||||
#define hrPIDERR 0x09
|
||||
#define hrPKTERR 0x0A
|
||||
#define hrCRCERR 0x0B
|
||||
#define hrKERR 0x0C
|
||||
#define hrJERR 0x0D
|
||||
#define hrTIMEOUT 0x0E
|
||||
#define hrBABBLE 0x0F
|
||||
|
||||
#define MODE_FS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB)
|
||||
#define MODE_LS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB)
|
||||
|
||||
|
||||
#endif //_MAX3421Econstants_h_
|
File diff suppressed because it is too large
Load Diff
@@ -1,38 +1,36 @@
|
||||
/* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */
|
||||
/* USB functions */
|
||||
#ifndef _usb_h_
|
||||
#define _usb_h_
|
||||
#ifndef USB_H_INCLUDED
|
||||
#define USB_H_INCLUDED
|
||||
|
||||
#include <Max3421e.h>
|
||||
#include <stdint.h>
|
||||
#include "ch9.h"
|
||||
|
||||
/* Common setup data constant combinations */
|
||||
#define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //get descriptor request type
|
||||
#define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface'
|
||||
#define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type
|
||||
#define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE // Get descriptor request type
|
||||
#define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE // Set request type for all but 'set feature' and 'set interface'
|
||||
#define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE // Get interface request type
|
||||
|
||||
/* HID requests */
|
||||
#define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
|
||||
#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
|
||||
#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
|
||||
#define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE
|
||||
|
||||
#define USB_XFER_TIMEOUT 5000 //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
|
||||
#define USB_NAK_LIMIT 32000 //NAK limit for a transfer. o meand NAKs are not counted
|
||||
#define USB_RETRY_LIMIT 3 //retry limit for a transfer
|
||||
#define USB_SETTLE_DELAY 200 //settle delay in milliseconds
|
||||
#define USB_NAK_NOWAIT 1 //used in Richard's PS2/Wiimote code
|
||||
#define USB_XFER_TIMEOUT 5000 // USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
|
||||
#define USB_NAK_LIMIT 32000 // NAK limit for a transfer. o means NAKs are not counted
|
||||
#define USB_RETRY_LIMIT 3 // Retry limit for a transfer
|
||||
#define USB_SETTLE_DELAY 200 // Settle delay in milliseconds
|
||||
#define USB_NAK_NOWAIT 1 // Used in Richard's PS2/Wiimote code
|
||||
|
||||
#define USB_NUMDEVICES 2 //number of USB devices
|
||||
#define USB_NUMDEVICES 2 // Number of USB devices
|
||||
|
||||
/* USB state machine states */
|
||||
|
||||
#define USB_STATE_MASK 0xf0
|
||||
|
||||
#define USB_STATE_DETACHED 0x10
|
||||
#define USB_DETACHED_SUBSTATE_INITIALIZE 0x11
|
||||
#define USB_DETACHED_SUBSTATE_INITIALIZE 0x11
|
||||
#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12
|
||||
#define USB_DETACHED_SUBSTATE_ILLEGAL 0x13
|
||||
#define USB_ATTACHED_SUBSTATE_SETTLE 0x20
|
||||
#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30
|
||||
#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30
|
||||
#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40
|
||||
#define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50
|
||||
#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60
|
||||
@@ -40,137 +38,166 @@
|
||||
#define USB_STATE_CONFIGURING 0x80
|
||||
#define USB_STATE_RUNNING 0x90
|
||||
#define USB_STATE_ERROR 0xa0
|
||||
|
||||
// byte usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE
|
||||
#define USB_STATE_MASK 0xf0
|
||||
|
||||
/* USB Setup Packet Structure */
|
||||
typedef struct {
|
||||
union { // offset description
|
||||
byte bmRequestType; // 0 Bit-map of request type
|
||||
struct {
|
||||
byte recipient: 5; // Recipient of the request
|
||||
byte type: 2; // Type of request
|
||||
byte direction: 1; // Direction of data X-fer
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{ // offset description
|
||||
uint8_t bmRequestType; // 0 Bit-map of request type
|
||||
struct
|
||||
{
|
||||
uint8_t recipient: 5; // Recipient of the request
|
||||
uint8_t type: 2; // Type of request
|
||||
uint8_t direction: 1; // Direction of data X-fer
|
||||
};
|
||||
}ReqType_u;
|
||||
byte bRequest; // 1 Request
|
||||
union {
|
||||
unsigned int wValue; // 2 Depends on bRequest
|
||||
struct {
|
||||
byte wValueLo;
|
||||
byte wValueHi;
|
||||
} ReqType_u;
|
||||
uint8_t bRequest; // 1 Request
|
||||
union
|
||||
{
|
||||
uint16_t wValue; // 2 Depends on bRequest
|
||||
struct
|
||||
{
|
||||
uint8_t wValueLo;
|
||||
uint8_t wValueHi;
|
||||
};
|
||||
}wVal_u;
|
||||
unsigned int wIndex; // 4 Depends on bRequest
|
||||
unsigned int wLength; // 6 Depends on bRequest
|
||||
} wVal_u;
|
||||
uint16_t wIndex; // 4 Depends on bRequest
|
||||
uint16_t wLength; // 6 Depends on bRequest
|
||||
} SETUP_PKT, *PSETUP_PKT;
|
||||
|
||||
/* Endpoint information structure */
|
||||
/* bToggle of endpoint 0 initialized to 0xff */
|
||||
/* during enumeration bToggle is set to 00 */
|
||||
typedef struct {
|
||||
byte epAddr; //copy from endpoint descriptor. Bit 7 indicates direction ( ignored for control endpoints )
|
||||
byte Attr; // Endpoint transfer type.
|
||||
unsigned int MaxPktSize; // Maximum packet size.
|
||||
byte Interval; // Polling interval in frames.
|
||||
byte sndToggle; //last toggle value, bitmask for HCTL toggle bits
|
||||
byte rcvToggle; //last toggle value, bitmask for HCTL toggle bits
|
||||
typedef struct
|
||||
{
|
||||
uint32_t epAddr; // Copy from endpoint descriptor. Bit 7 indicates direction (ignored for control endpoints)
|
||||
uint8_t Attr; // Endpoint transfer type.
|
||||
uint16_t MaxPktSize; // Maximum packet size.
|
||||
uint8_t Interval; // Polling interval in frames.
|
||||
uint8_t sndToggle; // Last toggle value, bitmask for HCTL toggle bits
|
||||
uint8_t rcvToggle; // Last toggle value, bitmask for HCTL toggle bits
|
||||
/* not sure if both are necessary */
|
||||
} EP_RECORD;
|
||||
/* device record structure */
|
||||
typedef struct {
|
||||
EP_RECORD* epinfo; //device endpoint information
|
||||
byte devclass; //device class
|
||||
|
||||
/* Device record structure */
|
||||
typedef struct
|
||||
{
|
||||
EP_RECORD* epinfo; // Device endpoint information
|
||||
uint8_t devclass; // Device class
|
||||
} DEV_RECORD;
|
||||
|
||||
|
||||
|
||||
class USB : public MAX3421E {
|
||||
//data structures
|
||||
/* device table. Filled during enumeration */
|
||||
/* index corresponds to device address */
|
||||
/* each entry contains pointer to endpoint structure */
|
||||
/* and device class to use in various places */
|
||||
//DEV_RECORD devtable[ USB_NUMDEVICES + 1 ];
|
||||
//EP_RECORD dev0ep; //Endpoint data structure used during enumeration for uninitialized device
|
||||
|
||||
//byte usb_task_state;
|
||||
|
||||
/**
|
||||
* USBHost Class
|
||||
* The device table is filled during enumeration.
|
||||
* Index corresponds to device address and each entry contains pointer to endpoint structure and device class to use.
|
||||
*/
|
||||
class USBHost
|
||||
{
|
||||
public:
|
||||
USB( void );
|
||||
byte getUsbTaskState( void );
|
||||
void setUsbTaskState( byte state );
|
||||
EP_RECORD* getDevTableEntry( byte addr, byte ep );
|
||||
void setDevTableEntry( byte addr, EP_RECORD* eprecord_ptr );
|
||||
byte ctrlReq( byte addr, byte ep, byte bmReqType, byte bRequest, byte wValLo, byte wValHi, unsigned int wInd, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
/* Control requests */
|
||||
byte getDevDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
byte getConfDescr( byte addr, byte ep, unsigned int nbytes, byte conf, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
byte getStrDescr( byte addr, byte ep, unsigned int nbytes, byte index, unsigned int langid, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
byte setAddr( byte oldaddr, byte ep, byte newaddr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
byte setConf( byte addr, byte ep, byte conf_value, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
/**/
|
||||
byte setProto( byte addr, byte ep, byte interface, byte protocol, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
byte getProto( byte addr, byte ep, byte interface, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
byte getReportDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
byte setReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
byte getReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
byte getIdle( byte addr, byte ep, byte interface, byte reportID, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
byte setIdle( byte addr, byte ep, byte interface, byte reportID, byte duration, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
/**/
|
||||
byte ctrlData( byte addr, byte ep, unsigned int nbytes, char* dataptr, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
byte ctrlStatus( byte ep, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
byte inTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
int newInTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit = USB_NAK_LIMIT);
|
||||
byte outTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
byte dispatchPkt( byte token, byte ep, unsigned int nak_limit = USB_NAK_LIMIT );
|
||||
void Task( void );
|
||||
USBHost(void);
|
||||
uint32_t getUsbTaskState(void);
|
||||
void setUsbTaskState(uint32_t state);
|
||||
EP_RECORD* getDevTableEntry(uint32_t addr, uint32_t ep);
|
||||
void setDevTableEntry(uint32_t addr, EP_RECORD* eprecord_ptr);
|
||||
uint32_t ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, uint16_t wInd, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
|
||||
/* Control requests */
|
||||
uint32_t getDevDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t getConfDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t conf, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t getStrDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t setAddr(uint32_t oldaddr, uint32_t ep, uint32_t newaddr, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t setConf(uint32_t addr, uint32_t ep, uint8_t conf_value, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
|
||||
/* Status requests */
|
||||
uint32_t setProto(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t protocol, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t getProto(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t getReportDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t setReport(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t getReport(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t getIdle(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t setIdle(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t reportID, uint8_t duration, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
|
||||
/* Transfer requests */
|
||||
uint32_t ctrlData(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t direction, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t ctrlStatus(uint32_t ep, uint32_t direction, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t inTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
int32_t newInTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t outTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
uint32_t dispatchPkt(uint32_t token, uint32_t ep, uint32_t nak_limit = USB_NAK_LIMIT);
|
||||
void Task(void);
|
||||
|
||||
private:
|
||||
void init();
|
||||
};
|
||||
|
||||
//get device descriptor
|
||||
inline byte USB::getDevDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr, nak_limit ));
|
||||
// Get device descriptor
|
||||
inline uint32_t USBHost::getDevDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit)
|
||||
{
|
||||
return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr, nak_limit));
|
||||
}
|
||||
//get configuration descriptor
|
||||
inline byte USB::getConfDescr( byte addr, byte ep, unsigned int nbytes, byte conf, char* dataptr, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr, nak_limit ));
|
||||
|
||||
// Get configuration descriptor
|
||||
inline uint32_t USBHost::getConfDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t conf, uint8_t* dataptr, uint32_t nak_limit)
|
||||
{
|
||||
return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr, nak_limit));
|
||||
}
|
||||
//get string descriptor
|
||||
inline byte USB::getStrDescr( byte addr, byte ep, unsigned int nbytes, byte index, unsigned int langid, char* dataptr, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nbytes, dataptr, nak_limit ));
|
||||
|
||||
// Get string descriptor
|
||||
inline uint32_t USBHost::getStrDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr, uint32_t nak_limit)
|
||||
{
|
||||
return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nbytes, dataptr, nak_limit));
|
||||
}
|
||||
//set address
|
||||
inline byte USB::setAddr( byte oldaddr, byte ep, byte newaddr, unsigned int nak_limit ) {
|
||||
return( ctrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL, nak_limit ));
|
||||
|
||||
// Set address
|
||||
inline uint32_t USBHost::setAddr(uint32_t oldaddr, uint32_t ep, uint32_t newaddr, uint32_t nak_limit)
|
||||
{
|
||||
return (ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0, nak_limit));
|
||||
}
|
||||
//set configuration
|
||||
inline byte USB::setConf( byte addr, byte ep, byte conf_value, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL, nak_limit ));
|
||||
|
||||
// Set configuration
|
||||
inline uint32_t USBHost::setConf(uint32_t addr, uint32_t ep, uint8_t conf_value, uint32_t nak_limit)
|
||||
{
|
||||
return (ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0, nak_limit));
|
||||
}
|
||||
//class requests
|
||||
inline byte USB::setProto( byte addr, byte ep, byte interface, byte protocol, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, NULL, nak_limit ));
|
||||
|
||||
// Class requests
|
||||
inline uint32_t USBHost::setProto(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t protocol, uint32_t nak_limit)
|
||||
{
|
||||
return (ctrlReq(addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, 0, nak_limit));
|
||||
}
|
||||
inline byte USB::getProto( byte addr, byte ep, byte interface, char* dataptr, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr, nak_limit ));
|
||||
|
||||
inline uint32_t USBHost::getProto(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t* dataptr, uint32_t nak_limit)
|
||||
{
|
||||
return (ctrlReq(addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr, nak_limit));
|
||||
}
|
||||
//get HID report descriptor
|
||||
inline byte USB::getReportDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, dataptr, nak_limit ));
|
||||
|
||||
// Get HID report descriptor
|
||||
inline uint32_t USBHost::getReportDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit)
|
||||
{
|
||||
return (ctrlReq(addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, dataptr, nak_limit));
|
||||
}
|
||||
inline byte USB::setReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit ));
|
||||
|
||||
inline uint32_t USBHost::setReport(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, uint32_t nak_limit)
|
||||
{
|
||||
return (ctrlReq(addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit));
|
||||
}
|
||||
inline byte USB::getReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit ) { // ** RI 04/11/09
|
||||
return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit ));
|
||||
|
||||
inline uint32_t USBHost::getReport(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, uint32_t nak_limit)
|
||||
{
|
||||
return (ctrlReq(addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit));
|
||||
}
|
||||
/* returns one byte of data in dataptr */
|
||||
inline byte USB::getIdle( byte addr, byte ep, byte interface, byte reportID, char* dataptr, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr, nak_limit ));
|
||||
|
||||
/* returns one uint8_t of data in dataptr */
|
||||
inline uint32_t USBHost::getIdle(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr, uint32_t nak_limit)
|
||||
{
|
||||
return (ctrlReq(addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr, nak_limit));
|
||||
}
|
||||
inline byte USB::setIdle( byte addr, byte ep, byte interface, byte reportID, byte duration, unsigned int nak_limit ) {
|
||||
return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, interface, 0x0000, NULL, nak_limit ));
|
||||
}
|
||||
#endif //_usb_h_
|
||||
|
||||
inline uint32_t USBHost::setIdle(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t reportID, uint8_t duration, uint32_t nak_limit)
|
||||
{
|
||||
return (ctrlReq(addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, interface, 0x0000, 0, nak_limit));
|
||||
}
|
||||
|
||||
#endif /* USB_H_INCLUDED */
|
||||
|
@@ -3,6 +3,8 @@
|
||||
#ifndef _ch9_h_
|
||||
#define _ch9_h_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Misc.USB constants */
|
||||
#define DEV_DESCR_LEN 18 //device descriptor length
|
||||
#define CONF_DESCR_LEN 9 //configuration descriptor length
|
||||
@@ -96,73 +98,77 @@
|
||||
#define HID_PROTOCOL_MOUSE 0x02
|
||||
|
||||
|
||||
_Pragma("pack(1)")
|
||||
|
||||
/* descriptor data structures */
|
||||
|
||||
/* Device descriptor structure */
|
||||
typedef struct {
|
||||
byte bLength; // Length of this descriptor.
|
||||
byte bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE).
|
||||
unsigned int bcdUSB; // USB Spec Release Number (BCD).
|
||||
byte bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
byte bDeviceSubClass; // Subclass code (assigned by the USB-IF).
|
||||
byte bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
byte bMaxPacketSize0; // Maximum packet size for endpoint 0.
|
||||
unsigned int idVendor; // Vendor ID (assigned by the USB-IF).
|
||||
unsigned int idProduct; // Product ID (assigned by the manufacturer).
|
||||
unsigned int bcdDevice; // Device release number (BCD).
|
||||
byte iManufacturer; // Index of String Descriptor describing the manufacturer.
|
||||
byte iProduct; // Index of String Descriptor describing the product.
|
||||
byte iSerialNumber; // Index of String Descriptor with the device's serial number.
|
||||
byte bNumConfigurations; // Number of possible configurations.
|
||||
uint8_t bLength; // Length of this descriptor.
|
||||
uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE).
|
||||
uint16_t bcdUSB; // USB Spec Release Number (BCD).
|
||||
uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF).
|
||||
uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0.
|
||||
uint16_t idVendor; // Vendor ID (assigned by the USB-IF).
|
||||
uint16_t idProduct; // Product ID (assigned by the manufacturer).
|
||||
uint16_t bcdDevice; // Device release number (BCD).
|
||||
uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer.
|
||||
uint8_t iProduct; // Index of String Descriptor describing the product.
|
||||
uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number.
|
||||
uint8_t bNumConfigurations; // Number of possible configurations.
|
||||
} USB_DEVICE_DESCRIPTOR;
|
||||
|
||||
/* Configuration descriptor structure */
|
||||
typedef struct
|
||||
{
|
||||
byte bLength; // Length of this descriptor.
|
||||
byte bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).
|
||||
unsigned int wTotalLength; // Total length of all descriptors for this configuration.
|
||||
byte bNumInterfaces; // Number of interfaces in this configuration.
|
||||
byte bConfigurationValue; // Value of this configuration (1 based).
|
||||
byte iConfiguration; // Index of String Descriptor describing the configuration.
|
||||
byte bmAttributes; // Configuration characteristics.
|
||||
byte bMaxPower; // Maximum power consumed by this configuration.
|
||||
uint8_t bLength; // Length of this descriptor.
|
||||
uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).
|
||||
uint16_t wTotalLength; // Total length of all descriptors for this configuration.
|
||||
uint8_t bNumInterfaces; // Number of interfaces in this configuration.
|
||||
uint8_t bConfigurationValue; // Value of this configuration (1 based).
|
||||
uint8_t iConfiguration; // Index of String Descriptor describing the configuration.
|
||||
uint8_t bmAttributes; // Configuration characteristics.
|
||||
uint8_t bMaxPower; // Maximum power consumed by this configuration.
|
||||
} USB_CONFIGURATION_DESCRIPTOR;
|
||||
|
||||
/* Interface descriptor structure */
|
||||
typedef struct
|
||||
{
|
||||
byte bLength; // Length of this descriptor.
|
||||
byte bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).
|
||||
byte bInterfaceNumber; // Number of this interface (0 based).
|
||||
byte bAlternateSetting; // Value of this alternate interface setting.
|
||||
byte bNumEndpoints; // Number of endpoints in this interface.
|
||||
byte bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
byte bInterfaceSubClass; // Subclass code (assigned by the USB-IF).
|
||||
byte bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
byte iInterface; // Index of String Descriptor describing the interface.
|
||||
uint8_t bLength; // Length of this descriptor.
|
||||
uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).
|
||||
uint8_t bInterfaceNumber; // Number of this interface (0 based).
|
||||
uint8_t bAlternateSetting; // Value of this alternate interface setting.
|
||||
uint8_t bNumEndpoints; // Number of endpoints in this interface.
|
||||
uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF).
|
||||
uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
|
||||
uint8_t iInterface; // Index of String Descriptor describing the interface.
|
||||
} USB_INTERFACE_DESCRIPTOR;
|
||||
|
||||
/* Endpoint descriptor structure */
|
||||
typedef struct
|
||||
{
|
||||
byte bLength; // Length of this descriptor.
|
||||
byte bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).
|
||||
byte bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).
|
||||
byte bmAttributes; // Endpoint transfer type.
|
||||
unsigned int wMaxPacketSize; // Maximum packet size.
|
||||
byte bInterval; // Polling interval in frames.
|
||||
uint8_t bLength; // Length of this descriptor.
|
||||
uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).
|
||||
uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).
|
||||
uint8_t bmAttributes; // Endpoint transfer type.
|
||||
uint16_t wMaxPacketSize; // Maximum packet size.
|
||||
uint8_t bInterval; // Polling interval in frames.
|
||||
} USB_ENDPOINT_DESCRIPTOR;
|
||||
|
||||
/* HID descriptor */
|
||||
typedef struct {
|
||||
byte bLength;
|
||||
byte bDescriptorType;
|
||||
unsigned int bcdHID;
|
||||
byte bCountryCode;
|
||||
byte bNumDescriptors;
|
||||
byte bDescrType;
|
||||
unsigned int wDescriptorLength;
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdHID;
|
||||
uint8_t bCountryCode;
|
||||
uint8_t bNumDescriptors;
|
||||
uint8_t bDescrType;
|
||||
uint16_t wDescriptorLength;
|
||||
} USB_HID_DESCRIPTOR;
|
||||
|
||||
_Pragma("pack()")
|
||||
|
||||
#endif // _ch9_h_
|
||||
|
@@ -56,9 +56,11 @@
|
||||
|
||||
#include "include/timetick.h"
|
||||
#include "include/USB_device.h"
|
||||
#include "include/USB_host.h"
|
||||
|
||||
#if SAM3XA_SERIES
|
||||
#include "include/uotghs.h"
|
||||
#include "include/uotghs_device.h"
|
||||
#include "include/uotghs_host.h"
|
||||
#endif /* SAM3XA_SERIES */
|
||||
|
||||
#endif /* _LIB_SAM_ */
|
||||
|
@@ -16,8 +16,8 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _USB_DRIVER_
|
||||
#define _USB_DRIVER_
|
||||
#ifndef USB_DEVICE_H_INCLUDED
|
||||
#define USB_DEVICE_H_INCLUDED
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -403,4 +403,4 @@ typedef uint32_t iram_size_t;
|
||||
|
||||
//! @}
|
||||
|
||||
#endif /* _USB_DRIVER_*/
|
||||
#endif /* USB_DEVICE_H_INCLUDED */
|
||||
|
59
hardware/arduino/sam/system/libsam/include/USB_host.h
Normal file
59
hardware/arduino/sam/system/libsam/include/USB_host.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright (c) 2011 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 USB_HOST_H_INCLUDED
|
||||
#define USB_HOST_H_INCLUDED
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define tokSETUP UOTGHS_HSTPIPCFG_PTOKEN_SETUP
|
||||
#define tokIN UOTGHS_HSTPIPCFG_PTOKEN_IN
|
||||
#define tokOUT UOTGHS_HSTPIPCFG_PTOKEN_OUT
|
||||
#define tokINHS UOTGHS_HSTPIPCFG_PTOKEN_IN
|
||||
#define tokOUTHS UOTGHS_HSTPIPCFG_PTOKEN_OUT
|
||||
|
||||
//! \brief Device speed
|
||||
/*typedef enum {
|
||||
UHD_SPEED_LOW = 0,
|
||||
UHD_SPEED_FULL = 1,
|
||||
UHD_SPEED_HIGH = 2,
|
||||
} uhd_speed_t;*/
|
||||
|
||||
//! States of USBB interface
|
||||
typedef enum {
|
||||
UHD_STATE_NO_VBUS = 0,
|
||||
UHD_STATE_DISCONNECTED = 1,
|
||||
UHD_STATE_CONNECTED = 2,
|
||||
UHD_STATE_ERROR = 3,
|
||||
} uhd_vbus_state_t;
|
||||
|
||||
//extern uhd_speed_t uhd_get_speed(void);
|
||||
|
||||
|
||||
extern void UHD_SetStack(void (*pf_isr)(void));
|
||||
extern void UHD_Init(void);
|
||||
extern void UHD_BusReset(void);
|
||||
extern uhd_vbus_state_t UHD_GetVBUSState(void);
|
||||
extern uint32_t UHD_EP0_Alloc(uint32_t ul_add, uint32_t ul_ep_size);
|
||||
extern void UHD_EP_Free(uint32_t add, uint32_t endp);
|
||||
extern uint32_t UHD_EP_Read(uint32_t ul_ep, uint32_t ul_size, uint8_t* data);
|
||||
extern void UHD_EP_Write(uint32_t ul_ep, uint32_t ul_size, uint8_t* data);
|
||||
extern void UHD_EP_Send(uint32_t ul_ep, uint32_t ul_token_type);
|
||||
extern uint32_t UHD_EP_Is_Transfer_Complete(uint32_t ul_ep, uint32_t ul_token_type);
|
||||
|
||||
#endif /* USB_HOST_H_INCLUDED */
|
@@ -16,8 +16,8 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef UOTGHS_H_INCLUDED
|
||||
#define UOTGHS_H_INCLUDED
|
||||
#ifndef UOTGHS_DEVICE_H_INCLUDED
|
||||
#define UOTGHS_DEVICE_H_INCLUDED
|
||||
|
||||
|
||||
#define MAX_ENDPOINTS 10
|
||||
@@ -737,4 +737,4 @@
|
||||
//! @}
|
||||
|
||||
|
||||
#endif /* UOTGHS_H_INCLUDED */
|
||||
#endif /* UOTGHS_DEVICE_H_INCLUDED */
|
378
hardware/arduino/sam/system/libsam/include/uotghs_host.h
Normal file
378
hardware/arduino/sam/system/libsam/include/uotghs_host.h
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
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_HOST_H_INCLUDED
|
||||
#define UOTGHS_HOST_H_INCLUDED
|
||||
|
||||
//! \ingroup usb_host_group
|
||||
//! \defgroup uhd_group USB Host Driver (UHD)
|
||||
//! UOTGHS low-level driver for USB host mode
|
||||
//!
|
||||
//! @{
|
||||
|
||||
//! @name UOTGHS Host IP properties
|
||||
//!
|
||||
//! @{
|
||||
//! Get maximal number of endpoints
|
||||
#define uhd_get_pipe_max_nbr() (9)
|
||||
#define UOTGHS_EPT_NUM (uhd_get_pipe_max_nbr()+1)
|
||||
//! @}
|
||||
|
||||
//! @name Host Vbus line control
|
||||
//!
|
||||
//! VBOF is an optional output pin which allows to enable or disable
|
||||
//! the external VBus generator.
|
||||
//!
|
||||
//! @{
|
||||
//! Enables hardware control of USB_VBOF output pin when a Vbus error occur
|
||||
#define uhd_enable_vbus_error_hw_control() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSHWC))
|
||||
//! Disables hardware control of USB_VBOF output pin when a Vbus error occur
|
||||
#define uhd_disable_vbus_error_hw_control() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSHWC))
|
||||
|
||||
//! Pin and function for USB_VBOF according to configuration from USB_VBOF
|
||||
#define USB_VBOF_PIN USB_VBOF_GPIO
|
||||
#define USB_VBOF_FUNCTION USB_VBOF_FLAGS
|
||||
//! Output USB_VBOF onto its pin
|
||||
#define uhd_output_vbof_pin() do {\
|
||||
pio_configure_pin(USB_VBOF_PIN, USB_VBOF_FUNCTION); \
|
||||
} while (0)
|
||||
|
||||
//! Set USB_VBOF output pin polarity
|
||||
#define uhd_set_vbof_active_high() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSPO))
|
||||
#define uhd_set_vbof_active_low() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSPO))
|
||||
//! Requests VBus activation
|
||||
#define uhd_enable_vbus() (Set_bits(UOTGHS->UOTGHS_SFR, UOTGHS_SR_VBUSRQ))
|
||||
//! Requests VBus deactivation
|
||||
#define uhd_disable_vbus() (Set_bits(UOTGHS->UOTGHS_SCR, UOTGHS_SR_VBUSRQ))
|
||||
//! Tests if VBus activation has been requested
|
||||
#define Is_uhd_vbus_enabled() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_VBUSRQ))
|
||||
//! @}
|
||||
|
||||
//! @name Host Vbus line monitoring
|
||||
//!
|
||||
//! The VBus level is always checked by USBC hardware.
|
||||
//!
|
||||
//! @{
|
||||
#define uhd_enable_vbus_error_interrupt() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE))
|
||||
#define uhd_disable_vbus_error_interrupt() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE))
|
||||
#define Is_uhd_vbus_error_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE))
|
||||
#define uhd_ack_vbus_error_interrupt() (Set_bits(UOTGHS->UOTGHS_SCR, UOTGHS_SCR_VBERRIC))
|
||||
#define Is_uhd_vbus_error_interrupt() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_VBERRI))
|
||||
//! @}
|
||||
|
||||
#define uhd_ack_errors_interrupt() (UOTGHS->UOTGHS_SCR = (UOTGHS_SCR_VBERRIC|UOTGHS_SCR_BCERRIC|UOTGHS_SCR_HNPERRIC|UOTGHS_SCR_STOIC))
|
||||
#define Is_uhd_errors_interrupt() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE|UOTGHS_CTRL_BCERRE|UOTGHS_CTRL_HNPERRE|UOTGHS_CTRL_STOE))
|
||||
#define uhd_enable_suspend_error_interrupt()
|
||||
#define uhd_enable_hnp_error_interrupt()
|
||||
#define uhd_enable_bconn_error_interrupt()
|
||||
|
||||
//! @name USB device connection/disconnection monitoring
|
||||
//! @{
|
||||
#define uhd_enable_connection_int() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_DCONNIES)
|
||||
#define uhd_disable_connection_int() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_DCONNIEC)
|
||||
#define Is_uhd_connection_int_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_DCONNIE))
|
||||
#define uhd_ack_connection() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DCONNIC)
|
||||
#define Is_uhd_connection() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_DCONNI))
|
||||
|
||||
#define uhd_enable_disconnection_int() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_DDISCIES)
|
||||
#define uhd_disable_disconnection_int() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_DDISCIEC)
|
||||
#define Is_uhd_disconnection_int_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_DDISCIE))
|
||||
#define uhd_ack_disconnection() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DDISCIC)
|
||||
#define Is_uhd_disconnection() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_DDISCI))
|
||||
//! @}
|
||||
|
||||
//! @name USB device speed control
|
||||
//! @{
|
||||
#define uhd_get_speed_mode() (Rd_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_SPEED_Msk))
|
||||
#define Is_uhd_low_speed_mode() (uhd_get_speed_mode() == UOTGHS_SR_SPEED_LOW_SPEED)
|
||||
#define Is_uhd_full_speed_mode() (uhd_get_speed_mode() == UOTGHS_SR_SPEED_FULL_SPEED)
|
||||
#define Is_uhd_high_speed_mode() (uhd_get_speed_mode() == UOTGHS_SR_SPEED_HIGH_SPEED)
|
||||
//! Enable high speed mode
|
||||
# define uhd_enable_high_speed_mode() (Wr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SPDCONF_Msk, UOTGHS_HSTCTRL_SPDCONF_HIGH_SPEED))
|
||||
//! Disable high speed mode
|
||||
# define uhd_disable_high_speed_mode() (Wr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SPDCONF_Msk, UOTGHS_HSTCTRL_SPDCONF_FORCED_FS))
|
||||
//! @}
|
||||
|
||||
//! @name Bus events control
|
||||
//! These macros manage the bus events: reset, SOF, resume, wakeup.
|
||||
//! @{
|
||||
|
||||
//! Initiates a reset event
|
||||
//! @{
|
||||
#define uhd_start_reset() (Set_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESET))
|
||||
#define Is_uhd_starting_reset() (Tst_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESET))
|
||||
#define uhd_stop_reset() (Clr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESET))
|
||||
|
||||
#define uhd_enable_reset_sent_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_RSTIES)
|
||||
#define uhd_disable_reset_sent_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_RSTIEC)
|
||||
#define Is_uhd_reset_sent_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_RSTIE))
|
||||
#define uhd_ack_reset_sent() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_RSTIC)
|
||||
#define Is_uhd_reset_sent() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_RSTI))
|
||||
//! @}
|
||||
|
||||
//! Initiates a SOF events
|
||||
//! @{
|
||||
#define uhd_enable_sof() (Set_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SOFE))
|
||||
#define uhd_disable_sof() (Clr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SOFE))
|
||||
#define Is_uhd_sof_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SOFE))
|
||||
#define uhd_get_sof_number() ((UOTGHS->UOTGHS_HSTFNUM&UOTGHS_HSTFNUM_FNUM_Msk)>>UOTGHS_HSTFNUM_FNUM_Pos)
|
||||
#define uhd_get_microsof_number() ((UOTGHS->UOTGHS_HSTFNUM&UOTGHS_HSTFNUM_MFNUM_Msk)>>UOTGHS_HSTFNUM_MFNUM_Pos)
|
||||
#define uhd_get_frame_position() (Rd_bits(UOTGHS->UOTGHS_HSTFNUM, UOTGHS_HSTFNUM_FLENHIGH_Msk))
|
||||
#define uhd_enable_sof_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_HSOFIES)
|
||||
#define uhd_disable_sof_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HSOFIEC)
|
||||
#define Is_uhd_sof_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_HSOFIE))
|
||||
#define uhd_ack_sof() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_HSOFIC)
|
||||
#define Is_uhd_sof() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_HSOFI))
|
||||
//! @}
|
||||
|
||||
//! Initiates a resume event
|
||||
//! It is called downstream resume event.
|
||||
//! @{
|
||||
#define uhd_send_resume() (Set_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESUME))
|
||||
#define Is_uhd_sending_resume() (Tst_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESUME))
|
||||
|
||||
#define uhd_enable_downstream_resume_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_RSMEDIES)
|
||||
#define uhd_disable_downstream_resume_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_RSMEDIEC)
|
||||
#define Is_uhd_downstream_resume_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_RSMEDIE))
|
||||
#define uhd_ack_downstream_resume() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_RSMEDIC)
|
||||
#define Is_uhd_downstream_resume() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_RSMEDI))
|
||||
//! @}
|
||||
|
||||
//! Detection of a wake-up event
|
||||
//! A wake-up event is received when the host controller is in the suspend mode:
|
||||
//! - and an upstream resume from the peripheral is detected.
|
||||
//! - and a peripheral disconnection is detected.
|
||||
//! @{
|
||||
#define uhd_enable_wakeup_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_HWUPIES)
|
||||
#define uhd_disable_wakeup_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HWUPIEC)
|
||||
#define Is_uhd_wakeup_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_HWUPIE))
|
||||
#define uhd_ack_wakeup() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_HWUPIC)
|
||||
#define Is_uhd_wakeup() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_HWUPI))
|
||||
|
||||
#define uhd_enable_upstream_resume_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_RXRSMIES)
|
||||
#define uhd_disable_upstream_resume_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_RXRSMIEC)
|
||||
#define Is_uhd_upstream_resume_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_RXRSMIE))
|
||||
#define uhd_ack_upstream_resume() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_RXRSMIC)
|
||||
#define Is_uhd_upstream_resume() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_RXRSMI))
|
||||
//! @}
|
||||
//! @}
|
||||
|
||||
|
||||
//! @name Pipes management
|
||||
//! @{
|
||||
|
||||
//! USB address of pipes
|
||||
//! @{
|
||||
#define uhd_configure_address(p, addr) \
|
||||
(Wr_bitfield((&UOTGHS->UOTGHS_HSTADDR1)[(p)>>2], \
|
||||
UOTGHS_HSTADDR1_HSTADDRP0_Msk << (((p)&0x03)<<3), addr))
|
||||
#define uhd_get_configured_address(p) \
|
||||
(Rd_bitfield((&UOTGHS->UOTGHS_HSTADDR1)[(p)>>2], \
|
||||
UOTGHS_HSTADDR1_HSTADDRP0_Msk << (((p)&0x03)<<3)))
|
||||
//! @}
|
||||
|
||||
//! Pipe enable
|
||||
//! Enable, disable, reset, freeze
|
||||
//! @{
|
||||
#define uhd_enable_pipe(p) \
|
||||
(Set_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
|
||||
#define uhd_disable_pipe(p) \
|
||||
(Clr_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
|
||||
#define Is_uhd_pipe_enabled(p) \
|
||||
(Tst_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
|
||||
#define uhd_reset_pipe(p) \
|
||||
(Set_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p))); \
|
||||
(Clr_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
|
||||
#define Is_uhd_resetting_pipe(p) \
|
||||
(Tst_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
|
||||
#define uhd_freeze_pipe(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_PFREEZES)
|
||||
#define uhd_unfreeze_pipe(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_PFREEZEC)
|
||||
#define Is_uhd_pipe_frozen(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_PFREEZE))
|
||||
#define uhd_reset_data_toggle(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_RSTDTS)
|
||||
#define Is_uhd_data_toggle_reset(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_RSTDT))
|
||||
//! @}
|
||||
|
||||
//! Pipe configuration
|
||||
//! @{
|
||||
#define uhd_configure_pipe_int_req_freq(p,freq) (Wr_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_INTFRQ_Msk, (freq)))
|
||||
#define uhd_get_pipe_int_req_freq(p) (Rd_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_INTFRQ_Msk))
|
||||
#define uhd_configure_pipe_endpoint_number(p,ep) (Wr_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PEPNUM_Msk, (ep)))
|
||||
#define uhd_get_pipe_endpoint_address(p) \
|
||||
(uhd_is_pipe_in(p) ?\
|
||||
(uhd_get_pipe_endpoint_number(p) | USB_EP_DIR_IN) :\
|
||||
(uhd_get_pipe_endpoint_number(p) | USB_EP_DIR_OUT))
|
||||
#define uhd_get_pipe_endpoint_number(p) (Rd_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], (UOTGHS_HSTPIPCFG_PEPNUM_Msk)))
|
||||
#define uhd_configure_pipe_type(p, type) (Wr_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTYPE_Msk, type))
|
||||
#define uhd_get_pipe_type(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTYPE_Msk))
|
||||
#define uhd_enable_pipe_bank_autoswitch(p) (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_AUTOSW))
|
||||
#define uhd_disable_pipe_bank_autoswitch(p) (Clr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_AUTOSW))
|
||||
#define Is_uhd_pipe_bank_autoswitch_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_AUTOSW))
|
||||
#define uhd_configure_pipe_token(p, token) (Wr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTOKEN_Msk, token))
|
||||
#define uhd_get_pipe_token(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTOKEN_Msk))
|
||||
#define uhd_is_pipe_in(p) (UOTGHS_HSTPIPCFG_PTOKEN_IN==uhd_get_pipe_token(p))
|
||||
#define uhd_is_pipe_out(p) (UOTGHS_HSTPIPCFG_PTOKEN_OUT==uhd_get_pipe_token(p))
|
||||
//! Bounds given integer size to allowed range and rounds it up to the nearest
|
||||
//! available greater size, then applies register format of UOTGHS controller
|
||||
//! for pipe size bit-field.
|
||||
#define uhd_format_pipe_size(size) \
|
||||
(32 - clz(((uint32_t)min(max(size, 8), 1024) << 1) - 1) - 1 - 3)
|
||||
#define uhd_configure_pipe_size(p,size) \
|
||||
(Wr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PSIZE_Msk, uhd_format_pipe_size(size)))
|
||||
#define uhd_get_pipe_size(p) (8<<((Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], (UOTGHS_HSTPIPCFG_PSIZE_Msk)))>> UOTGHS_HSTPIPCFG_PSIZE_Pos))
|
||||
#define uhd_configure_pipe_bank(p,bank) (Wr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PBK_Msk, (bank)))
|
||||
#define uhd_get_pipe_bank(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PBK_Msk))
|
||||
#define uhd_allocate_memory(p) (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_ALLOC))
|
||||
#define uhd_unallocate_memory(p) (Clr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_ALLOC))
|
||||
#define Is_uhd_memory_allocated(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_ALLOC))
|
||||
|
||||
//! Enable PING management only available in HS mode
|
||||
# define uhd_enable_ping(p) (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PINGEN))
|
||||
//#endif
|
||||
#define uhd_configure_pipe(p, freq, ep_num, type, token, size, bank, bank_switch) \
|
||||
(Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p],\
|
||||
(bank)|\
|
||||
((uhd_format_pipe_size(size)<<UOTGHS_HSTPIPCFG_PSIZE_Pos)&UOTGHS_HSTPIPCFG_PSIZE_Msk)|\
|
||||
(((token)<<UOTGHS_HSTPIPCFG_PTOKEN_Pos)&UOTGHS_HSTPIPCFG_PTOKEN_Msk)|\
|
||||
(((type)<<UOTGHS_HSTPIPCFG_PTYPE_Pos)&UOTGHS_HSTPIPCFG_PTYPE_Msk)|\
|
||||
(((ep_num)<<UOTGHS_HSTPIPCFG_PEPNUM_Pos)&UOTGHS_HSTPIPCFG_PEPNUM_Msk)|\
|
||||
bank_switch |\
|
||||
(((freq)<<UOTGHS_HSTPIPCFG_INTFRQ_Pos)&UOTGHS_HSTPIPCFG_INTFRQ_Msk)))
|
||||
|
||||
#define Is_uhd_pipe_configured(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_CFGOK))
|
||||
//! @}
|
||||
|
||||
//! Pipe main interrupts management
|
||||
//! @{
|
||||
#define uhd_enable_pipe_interrupt(p) (UOTGHS->UOTGHS_HSTIER = (UOTGHS_HSTIER_PEP_0 << (p)))
|
||||
#define uhd_disable_pipe_interrupt(p) (UOTGHS->UOTGHS_HSTIDR = (UOTGHS_HSTIDR_PEP_0 << (p)))
|
||||
#define Is_uhd_pipe_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_PEP_0 << (p)))
|
||||
#define Is_uhd_pipe_interrupt(p) (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_PEP_0 << (p)))
|
||||
//! returns the lowest pipe number generating a pipe interrupt or UOTGHS_EPT_NUM if none
|
||||
#define uhd_get_interrupt_pipe_number() \
|
||||
(ctz(((UOTGHS->UOTGHS_HSTISR >> 8) & (UOTGHS->UOTGHS_HSTIMR >> 8)) | (1 << UOTGHS_EPT_NUM)))
|
||||
//! @}
|
||||
|
||||
//! Pipe overflow and underflow for isochronous and interrupt endpoints
|
||||
//! @{
|
||||
#define uhd_enable_overflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_OVERFIES)
|
||||
#define uhd_disable_overflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_OVERFIEC)
|
||||
#define Is_uhd_overflow_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_OVERFIE))
|
||||
#define uhd_ack_overflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_OVERFIC)
|
||||
#define Is_uhd_overflow(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_OVERFI))
|
||||
|
||||
#define uhd_enable_underflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_UNDERFIES)
|
||||
#define uhd_disable_underflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_UNDERFIEC)
|
||||
#define Is_uhd_underflow_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_UNDERFIE))
|
||||
#define uhd_ack_underflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_UNDERFIC)
|
||||
#define Is_uhd_underflow(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_UNDERFI))
|
||||
//! @}
|
||||
|
||||
//! USB packet errors management
|
||||
//! @{
|
||||
#define uhd_enable_stall_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_RXSTALLDES)
|
||||
#define uhd_disable_stall_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_RXSTALLDEC)
|
||||
#define Is_uhd_stall_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_RXSTALLDE))
|
||||
#define uhd_ack_stall(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_RXSTALLDIC)
|
||||
#define Is_uhd_stall(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RXSTALLDI))
|
||||
|
||||
#define uhd_enable_pipe_error_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_PERRES)
|
||||
#define uhd_disable_pipe_error_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_PERREC)
|
||||
#define Is_uhd_pipe_error_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_PERRE))
|
||||
#define uhd_ack_all_errors(p) (UOTGHS->UOTGHS_HSTPIPERR[p] = 0UL)
|
||||
#define Is_uhd_pipe_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_PERRI))
|
||||
#define uhd_error_status(p) (UOTGHS->UOTGHS_HSTPIPERR[p])
|
||||
#define Is_uhd_bad_data_toggle(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_DATATGL))
|
||||
#define Is_uhd_data_pid_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_DATAPID))
|
||||
#define Is_uhd_pid_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_PID))
|
||||
#define Is_uhd_timeout_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_TIMEOUT))
|
||||
#define Is_uhd_crc16_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_CRC16))
|
||||
#define uhd_get_error_counter(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_COUNTER))
|
||||
//! @}
|
||||
|
||||
//! Pipe data management
|
||||
//! @{
|
||||
#define uhd_data_toggle(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_DTSEQ))
|
||||
|
||||
#define uhd_enable_bank_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_NBUSYBKES)
|
||||
#define uhd_disable_bank_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_NBUSYBKEC)
|
||||
#define Is_uhd_bank_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_NBUSYBKE))
|
||||
#define uhd_nb_busy_bank(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_NBUSYBK_Msk))
|
||||
#define uhd_current_bank(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_CURRBK_Msk ))
|
||||
|
||||
#define uhd_enable_short_packet_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_SHORTPACKETES)
|
||||
#define uhd_disable_short_packet_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_SHORTPACKETIEC)
|
||||
#define Is_uhd_short_packet_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_SHORTPACKETIE)) )
|
||||
#define uhd_ack_short_packet(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_SHORTPACKETIC)
|
||||
#define Is_uhd_short_packet(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_SHORTPACKETI))
|
||||
#define uhd_byte_count(p) (Rd_bitfield(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_PBYCT_Msk))
|
||||
|
||||
#define Is_uhd_fifocon(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_FIFOCON))
|
||||
#define uhd_ack_fifocon(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_FIFOCONC)
|
||||
|
||||
#define uhd_enable_setup_ready_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_TXSTPES)
|
||||
#define uhd_disable_setup_ready_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_TXSTPEC)
|
||||
#define Is_uhd_setup_ready_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_TXSTPE))
|
||||
#define uhd_ack_setup_ready(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_TXSTPIC)
|
||||
#define Is_uhd_setup_ready(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_TXSTPI))
|
||||
|
||||
#define uhd_enable_in_received_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_RXINES)
|
||||
#define uhd_disable_in_received_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_RXINEC)
|
||||
#define Is_uhd_in_received_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_RXINE))
|
||||
#define uhd_ack_in_received(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_RXINIC)
|
||||
#define Is_uhd_in_received(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RXINI))
|
||||
|
||||
#define uhd_enable_out_ready_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_TXOUTES)
|
||||
#define uhd_disable_out_ready_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_TXOUTEC)
|
||||
#define Is_uhd_out_ready_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_TXOUTE))
|
||||
#define uhd_ack_out_ready(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_TXOUTIC)
|
||||
#define Is_uhd_out_ready(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_TXOUTI))
|
||||
#define uhd_raise_out_ready(p) (UOTGHS->UOTGHS_HSTPIPIFR[p] = UOTGHS_HSTPIPIFR_TXOUTIS)
|
||||
|
||||
#define uhd_enable_nak_received_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_NAKEDES)
|
||||
#define uhd_disable_nak_received_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_NAKEDEC)
|
||||
#define Is_uhd_nak_received_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_NAKEDE))
|
||||
#define uhd_ack_nak_received(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_NAKEDIC)
|
||||
#define Is_uhd_nak_received(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_NAKEDI))
|
||||
|
||||
#define Is_uhd_read_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RWALL))
|
||||
#define Is_uhd_write_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RWALL ))
|
||||
|
||||
#define uhd_enable_continuous_in_mode(p) (Set_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INMODE))
|
||||
#define uhd_disable_continuous_in_mode(p) (Clr_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INMODE))
|
||||
#define Is_uhd_continuous_in_mode_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INMODE))
|
||||
|
||||
#define uhd_in_request_number(p, in_num) (Set_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], (in_num)-1))
|
||||
#define uhd_get_in_request_number(p) (((Rd_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INRQ_Msk))>>UOTGHS_HSTPIPINRQ_INRQ_Pos)+1)
|
||||
//! @}
|
||||
|
||||
//! Maximum transfer size on USB DMA
|
||||
#define UHD_PIPE_MAX_TRANS 0x8000
|
||||
|
||||
//! Get 64-, 32-, 16- or 8-bit access to FIFO data register of selected pipe.
|
||||
//! @param p Target Pipe number
|
||||
//! @param scale Data scale in bits: 64, 32, 16 or 8
|
||||
//! @return Volatile 64-, 32-, 16- or 8-bit data pointer to FIFO data register
|
||||
//! @warning It is up to the user of this macro to make sure that all accesses
|
||||
//! are aligned with their natural boundaries except 64-bit accesses which
|
||||
//! require only 32-bit alignment.
|
||||
//! @warning It is up to the user of this macro to make sure that used HSB
|
||||
//! addresses are identical to the DPRAM internal pointer modulo 32 bits.
|
||||
#define uhd_get_pipe_fifo_access(p, scale) \
|
||||
(((volatile TPASTE2(U, scale) (*)[UHD_PIPE_MAX_TRANS / ((scale) / 8)])UOTGHS_RAM_ADDR)[(p)])
|
||||
|
||||
#endif /* UOTGHS_HOST_H_INCLUDED */
|
@@ -17,22 +17,10 @@
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if SAM3XA_SERIES
|
||||
|
||||
//#define TRACE_UOTGHS(x) x
|
||||
#define TRACE_UOTGHS(x)
|
||||
|
||||
static void (*gpf_isr)(void) = (0UL);
|
||||
|
||||
static volatile uint32_t ul_send_fifo_ptr[MAX_ENDPOINTS];
|
||||
static volatile uint32_t ul_recv_fifo_ptr[MAX_ENDPOINTS];
|
||||
|
||||
void UDD_SetStack(void (*pf_isr)(void))
|
||||
{
|
||||
gpf_isr = pf_isr;
|
||||
}
|
||||
void (*gpf_isr)(void) = (0UL);
|
||||
|
||||
void UOTGHS_Handler( void )
|
||||
{
|
||||
@@ -40,291 +28,4 @@ void UOTGHS_Handler( void )
|
||||
gpf_isr();
|
||||
}
|
||||
|
||||
uint32_t UDD_Init(void)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < MAX_ENDPOINTS; ++i)
|
||||
{
|
||||
ul_send_fifo_ptr[i] = 0;
|
||||
ul_recv_fifo_ptr[i] = 0;
|
||||
}
|
||||
|
||||
// Enables the USB Clock
|
||||
pmc_enable_periph_clk(ID_UOTGHS);
|
||||
pmc_enable_upll_clock();
|
||||
pmc_switch_udpck_to_upllck(0); // div=0+1
|
||||
pmc_enable_udpck();
|
||||
|
||||
// Configure interrupts
|
||||
NVIC_SetPriority((IRQn_Type) ID_UOTGHS, 0UL);
|
||||
NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS);
|
||||
|
||||
// Always authorize asynchrone USB interrupts to exit from sleep mode
|
||||
// for SAM3 USB wake up device except BACKUP mode
|
||||
//pmc_set_fast_startup_input(PMC_FSMR_USBAL);
|
||||
|
||||
// ID pin not used then force device mode
|
||||
otg_disable_id_pin();
|
||||
otg_force_device_mode();
|
||||
|
||||
// Enable USB hardware
|
||||
otg_disable_pad();
|
||||
otg_enable_pad();
|
||||
otg_enable();
|
||||
otg_unfreeze_clock();
|
||||
|
||||
// Check USB clock
|
||||
//while (!Is_otg_clock_usable())
|
||||
// ;
|
||||
|
||||
udd_low_speed_disable();
|
||||
udd_high_speed_disable();
|
||||
|
||||
//otg_ack_vbus_transition();
|
||||
// Force Vbus interrupt in case of Vbus always with a high level
|
||||
// This is possible with a short timing between a Host mode stop/start.
|
||||
/*if (Is_otg_vbus_high()) {
|
||||
otg_raise_vbus_transition();
|
||||
}
|
||||
otg_enable_vbus_interrupt();*/
|
||||
otg_freeze_clock();
|
||||
|
||||
return 0UL ;
|
||||
}
|
||||
|
||||
void UDD_Attach(void)
|
||||
{
|
||||
irqflags_t flags = cpu_irq_save();
|
||||
|
||||
TRACE_UOTGHS(printf("=> UDD_Attach\r\n");)
|
||||
|
||||
otg_unfreeze_clock();
|
||||
|
||||
// Check USB clock because the source can be a PLL
|
||||
while (!Is_otg_clock_usable());
|
||||
|
||||
// Authorize attach if Vbus is present
|
||||
udd_attach_device();
|
||||
|
||||
// Enable USB line events
|
||||
udd_enable_reset_interrupt();
|
||||
//udd_enable_sof_interrupt();
|
||||
|
||||
cpu_irq_restore(flags);
|
||||
}
|
||||
|
||||
void UDD_Detach(void)
|
||||
{
|
||||
TRACE_UOTGHS(printf("=> UDD_Detach\r\n");)
|
||||
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_DETACH;
|
||||
}
|
||||
|
||||
void UDD_InitEP( uint32_t ul_ep_nb, uint32_t ul_ep_cfg )
|
||||
{
|
||||
ul_ep_nb = ul_ep_nb & 0xF; // EP range is 0..9, hence mask is 0xF.
|
||||
|
||||
TRACE_UOTGHS(printf("=> UDD_InitEP : init EP %d\r\n", ul_ep_nb);)
|
||||
|
||||
// Configure EP
|
||||
UOTGHS->UOTGHS_DEVEPTCFG[ul_ep_nb] = ul_ep_cfg;
|
||||
// Enable EP
|
||||
udd_enable_endpoint(ul_ep_nb);
|
||||
|
||||
if (!Is_udd_endpoint_configured(ul_ep_nb)) {
|
||||
TRACE_UOTGHS(printf("=> UDD_InitEP : ERROR FAILED TO INIT EP %d\r\n", ul_ep_nb);)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UDD_InitEndpoints(const uint32_t* eps_table, const uint32_t ul_eps_table_size)
|
||||
{
|
||||
uint32_t ul_ep_nb ;
|
||||
|
||||
for (ul_ep_nb = 1; ul_ep_nb < ul_eps_table_size; ul_ep_nb++)
|
||||
{
|
||||
// Configure EP
|
||||
UOTGHS->UOTGHS_DEVEPTCFG[ul_ep_nb] = eps_table[ul_ep_nb];
|
||||
// Enable EP
|
||||
udd_enable_endpoint(ul_ep_nb);
|
||||
|
||||
if (!Is_udd_endpoint_configured(ul_ep_nb)) {
|
||||
TRACE_UOTGHS(printf("=> UDD_InitEP : ERROR FAILED TO INIT EP %d\r\n", ul_ep_nb);)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until ready to accept IN packet.
|
||||
void UDD_WaitIN(void)
|
||||
{
|
||||
while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_TXINI))
|
||||
;
|
||||
}
|
||||
|
||||
void UDD_WaitOUT(void)
|
||||
{
|
||||
while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXOUTI))
|
||||
;
|
||||
}
|
||||
|
||||
// Send packet.
|
||||
void UDD_ClearIN(void)
|
||||
{
|
||||
TRACE_UOTGHS(printf("=> UDD_ClearIN: sent %d bytes\r\n", ul_send_fifo_ptr[EP0]);)
|
||||
|
||||
UOTGHS->UOTGHS_DEVEPTICR[EP0] = UOTGHS_DEVEPTICR_TXINIC;
|
||||
ul_send_fifo_ptr[EP0] = 0;
|
||||
}
|
||||
|
||||
void UDD_ClearOUT(void)
|
||||
{
|
||||
UOTGHS->UOTGHS_DEVEPTICR[EP0] = UOTGHS_DEVEPTICR_RXOUTIC;
|
||||
ul_recv_fifo_ptr[EP0] = 0;
|
||||
}
|
||||
|
||||
// Wait for IN FIFO to be ready to accept data or OUT FIFO to receive data.
|
||||
// Return true if new IN FIFO buffer available.
|
||||
uint32_t UDD_WaitForINOrOUT(void)
|
||||
{
|
||||
while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & (UOTGHS_DEVEPTISR_TXINI | UOTGHS_DEVEPTISR_RXOUTI)))
|
||||
;
|
||||
return ((UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXOUTI) == 0);
|
||||
}
|
||||
|
||||
uint32_t UDD_ReceivedSetupInt(void)
|
||||
{
|
||||
return UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXSTPI;
|
||||
}
|
||||
|
||||
void UDD_ClearSetupInt(void)
|
||||
{
|
||||
UOTGHS->UOTGHS_DEVEPTICR[EP0] = (UOTGHS_DEVEPTICR_RXSTPIC);
|
||||
}
|
||||
|
||||
uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len)
|
||||
{
|
||||
const uint8_t *ptr_src = data;
|
||||
uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep);
|
||||
uint32_t i;
|
||||
|
||||
TRACE_UOTGHS(printf("=> UDD_Send (1): ep=%d ul_send_fifo_ptr=%d len=%d\r\n", ep, ul_send_fifo_ptr[ep], len);)
|
||||
|
||||
if (ep == EP0)
|
||||
{
|
||||
if (ul_send_fifo_ptr[ep] + len > EP0_SIZE)
|
||||
len = EP0_SIZE - ul_send_fifo_ptr[ep];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ul_send_fifo_ptr[ep] + len > EPX_SIZE)
|
||||
len = EPX_SIZE - ul_send_fifo_ptr[ep];
|
||||
}
|
||||
|
||||
for (i = 0, ptr_dest += ul_send_fifo_ptr[ep]; i < len; ++i)
|
||||
*ptr_dest++ = *ptr_src++;
|
||||
|
||||
ul_send_fifo_ptr[ep] += i;
|
||||
|
||||
|
||||
if (ep == EP0)
|
||||
{
|
||||
TRACE_UOTGHS(printf("=> UDD_Send (2): ep=%d ptr_dest=%d maxlen=%d\r\n", ep, ul_send_fifo_ptr[ep], EP0_SIZE);)
|
||||
if (ul_send_fifo_ptr[ep] == EP0_SIZE)
|
||||
{
|
||||
UDD_ClearIN(); // Fifo is full, release this packet
|
||||
UDD_WaitIN(); // Wait for new FIFO buffer to be ready
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ul_send_fifo_ptr[ep] == EPX_SIZE)
|
||||
{
|
||||
UDD_ClearIN(); // Fifo is full, release this packet
|
||||
UDD_WaitIN(); // Wait for new FIFO buffer to be ready
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void UDD_Send8(uint32_t ep, uint8_t data )
|
||||
{
|
||||
uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep);
|
||||
|
||||
TRACE_UOTGHS(printf("=> UDD_Send8 : ul_send_fifo_ptr=%d data=0x%x\r\n", ul_send_fifo_ptr[ep], data);)
|
||||
|
||||
ptr_dest[ul_send_fifo_ptr[ep]] = data;
|
||||
ul_send_fifo_ptr[ep] += 1;
|
||||
}
|
||||
|
||||
uint8_t UDD_Recv8(uint32_t ep)
|
||||
{
|
||||
uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep);
|
||||
uint8_t data = ptr_dest[ul_recv_fifo_ptr[ep]];
|
||||
|
||||
TRACE_UOTGHS(printf("=> UDD_Recv8 : ul_recv_fifo_ptr=%d\r\n", ul_recv_fifo_ptr[ep]);)
|
||||
|
||||
ul_recv_fifo_ptr[ep] += 1;
|
||||
return data;
|
||||
}
|
||||
|
||||
void UDD_Recv(uint32_t ep, uint8_t* data, uint32_t len)
|
||||
{
|
||||
uint8_t *ptr_src = (uint8_t *) &udd_get_endpoint_fifo_access8(ep);
|
||||
uint8_t *ptr_dest = data;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0, ptr_src += ul_recv_fifo_ptr[ep]; i < len; ++i)
|
||||
*ptr_dest++ = *ptr_src++;
|
||||
|
||||
ul_recv_fifo_ptr[ep] += i;
|
||||
}
|
||||
|
||||
void UDD_Stall(void)
|
||||
{
|
||||
UOTGHS->UOTGHS_DEVEPT = (UOTGHS_DEVEPT_EPEN0 << EP0);
|
||||
UOTGHS->UOTGHS_DEVEPTIER[EP0] = UOTGHS_DEVEPTIER_STALLRQS;
|
||||
}
|
||||
|
||||
|
||||
uint32_t UDD_FifoByteCount(uint32_t ep)
|
||||
{
|
||||
return ((UOTGHS->UOTGHS_DEVEPTISR[ep] & UOTGHS_DEVEPTISR_BYCT_Msk) >> UOTGHS_DEVEPTISR_BYCT_Pos);
|
||||
}
|
||||
|
||||
void UDD_ReleaseRX(uint32_t ep)
|
||||
{
|
||||
TRACE_UOTGHS(puts("=> UDD_ReleaseRX\r\n");)
|
||||
UOTGHS->UOTGHS_DEVEPTICR[ep] = (UOTGHS_DEVEPTICR_NAKOUTIC | UOTGHS_DEVEPTICR_RXOUTIC);
|
||||
UOTGHS->UOTGHS_DEVEPTIDR[ep] = UOTGHS_DEVEPTIDR_FIFOCONC;
|
||||
ul_recv_fifo_ptr[ep] = 0;
|
||||
}
|
||||
|
||||
void UDD_ReleaseTX(uint32_t ep)
|
||||
{
|
||||
TRACE_UOTGHS(printf("=> UDD_ReleaseTX ep=%d\r\n", ep);)
|
||||
UOTGHS->UOTGHS_DEVEPTICR[ep] = (UOTGHS_DEVEPTICR_NAKINIC | UOTGHS_DEVEPTICR_RXOUTIC | UOTGHS_DEVEPTICR_TXINIC);
|
||||
UOTGHS->UOTGHS_DEVEPTIDR[ep] = UOTGHS_DEVEPTIDR_FIFOCONC;
|
||||
ul_send_fifo_ptr[ep] = 0;
|
||||
}
|
||||
|
||||
// Return true if the current bank is not full.
|
||||
uint32_t UDD_ReadWriteAllowed(uint32_t ep)
|
||||
{
|
||||
return (UOTGHS->UOTGHS_DEVEPTISR[ep] & UOTGHS_DEVEPTISR_RWALL);
|
||||
}
|
||||
|
||||
void UDD_SetAddress(uint32_t addr)
|
||||
{
|
||||
TRACE_UOTGHS(printf("=> UDD_SetAddress : setting address to %d\r\n", addr);)
|
||||
|
||||
udd_configure_address(addr);
|
||||
udd_enable_address();
|
||||
}
|
||||
|
||||
uint32_t UDD_GetFrameNumber(void)
|
||||
{
|
||||
return udd_frame_number();
|
||||
}
|
||||
|
||||
#endif /* SAM3XA_SERIES */
|
||||
|
324
hardware/arduino/sam/system/libsam/source/uotghs_device.c
Normal file
324
hardware/arduino/sam/system/libsam/source/uotghs_device.c
Normal file
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
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 "chip.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if SAM3XA_SERIES
|
||||
|
||||
//#define TRACE_UOTGHS(x) x
|
||||
#define TRACE_UOTGHS(x)
|
||||
|
||||
extern void (*gpf_isr)(void);
|
||||
|
||||
static volatile uint32_t ul_send_fifo_ptr[MAX_ENDPOINTS];
|
||||
static volatile uint32_t ul_recv_fifo_ptr[MAX_ENDPOINTS];
|
||||
|
||||
void UDD_SetStack(void (*pf_isr)(void))
|
||||
{
|
||||
gpf_isr = pf_isr;
|
||||
}
|
||||
|
||||
uint32_t UDD_Init(void)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < MAX_ENDPOINTS; ++i)
|
||||
{
|
||||
ul_send_fifo_ptr[i] = 0;
|
||||
ul_recv_fifo_ptr[i] = 0;
|
||||
}
|
||||
|
||||
// Enables the USB Clock
|
||||
pmc_enable_periph_clk(ID_UOTGHS);
|
||||
pmc_enable_upll_clock();
|
||||
pmc_switch_udpck_to_upllck(0); // div=0+1
|
||||
pmc_enable_udpck();
|
||||
|
||||
// Configure interrupts
|
||||
NVIC_SetPriority((IRQn_Type) ID_UOTGHS, 0UL);
|
||||
NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS);
|
||||
|
||||
// Always authorize asynchrone USB interrupts to exit from sleep mode
|
||||
// for SAM3 USB wake up device except BACKUP mode
|
||||
//pmc_set_fast_startup_input(PMC_FSMR_USBAL);
|
||||
|
||||
// ID pin not used then force device mode
|
||||
otg_disable_id_pin();
|
||||
otg_force_device_mode();
|
||||
|
||||
// Enable USB hardware
|
||||
otg_disable_pad();
|
||||
otg_enable_pad();
|
||||
otg_enable();
|
||||
otg_unfreeze_clock();
|
||||
|
||||
// Check USB clock
|
||||
//while (!Is_otg_clock_usable())
|
||||
// ;
|
||||
|
||||
udd_low_speed_disable();
|
||||
udd_high_speed_disable();
|
||||
|
||||
//otg_ack_vbus_transition();
|
||||
// Force Vbus interrupt in case of Vbus always with a high level
|
||||
// This is possible with a short timing between a Host mode stop/start.
|
||||
/*if (Is_otg_vbus_high()) {
|
||||
otg_raise_vbus_transition();
|
||||
}
|
||||
otg_enable_vbus_interrupt();*/
|
||||
otg_freeze_clock();
|
||||
|
||||
return 0UL ;
|
||||
}
|
||||
|
||||
void UDD_Attach(void)
|
||||
{
|
||||
irqflags_t flags = cpu_irq_save();
|
||||
|
||||
TRACE_UOTGHS(printf("=> UDD_Attach\r\n");)
|
||||
|
||||
otg_unfreeze_clock();
|
||||
|
||||
// Check USB clock because the source can be a PLL
|
||||
while (!Is_otg_clock_usable());
|
||||
|
||||
// Authorize attach if Vbus is present
|
||||
udd_attach_device();
|
||||
|
||||
// Enable USB line events
|
||||
udd_enable_reset_interrupt();
|
||||
//udd_enable_sof_interrupt();
|
||||
|
||||
cpu_irq_restore(flags);
|
||||
}
|
||||
|
||||
void UDD_Detach(void)
|
||||
{
|
||||
TRACE_UOTGHS(printf("=> UDD_Detach\r\n");)
|
||||
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_DETACH;
|
||||
}
|
||||
|
||||
void UDD_InitEP( uint32_t ul_ep_nb, uint32_t ul_ep_cfg )
|
||||
{
|
||||
ul_ep_nb = ul_ep_nb & 0xF; // EP range is 0..9, hence mask is 0xF.
|
||||
|
||||
TRACE_UOTGHS(printf("=> UDD_InitEP : init EP %d\r\n", ul_ep_nb);)
|
||||
|
||||
// Configure EP
|
||||
UOTGHS->UOTGHS_DEVEPTCFG[ul_ep_nb] = ul_ep_cfg;
|
||||
// Enable EP
|
||||
udd_enable_endpoint(ul_ep_nb);
|
||||
|
||||
if (!Is_udd_endpoint_configured(ul_ep_nb)) {
|
||||
TRACE_UOTGHS(printf("=> UDD_InitEP : ERROR FAILED TO INIT EP %d\r\n", ul_ep_nb);)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UDD_InitEndpoints(const uint32_t* eps_table, const uint32_t ul_eps_table_size)
|
||||
{
|
||||
uint32_t ul_ep_nb ;
|
||||
|
||||
for (ul_ep_nb = 1; ul_ep_nb < ul_eps_table_size; ul_ep_nb++)
|
||||
{
|
||||
// Configure EP
|
||||
UOTGHS->UOTGHS_DEVEPTCFG[ul_ep_nb] = eps_table[ul_ep_nb];
|
||||
// Enable EP
|
||||
udd_enable_endpoint(ul_ep_nb);
|
||||
|
||||
if (!Is_udd_endpoint_configured(ul_ep_nb)) {
|
||||
TRACE_UOTGHS(printf("=> UDD_InitEP : ERROR FAILED TO INIT EP %d\r\n", ul_ep_nb);)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until ready to accept IN packet.
|
||||
void UDD_WaitIN(void)
|
||||
{
|
||||
while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_TXINI))
|
||||
;
|
||||
}
|
||||
|
||||
void UDD_WaitOUT(void)
|
||||
{
|
||||
while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXOUTI))
|
||||
;
|
||||
}
|
||||
|
||||
// Send packet.
|
||||
void UDD_ClearIN(void)
|
||||
{
|
||||
TRACE_UOTGHS(printf("=> UDD_ClearIN: sent %d bytes\r\n", ul_send_fifo_ptr[EP0]);)
|
||||
|
||||
UOTGHS->UOTGHS_DEVEPTICR[EP0] = UOTGHS_DEVEPTICR_TXINIC;
|
||||
ul_send_fifo_ptr[EP0] = 0;
|
||||
}
|
||||
|
||||
void UDD_ClearOUT(void)
|
||||
{
|
||||
UOTGHS->UOTGHS_DEVEPTICR[EP0] = UOTGHS_DEVEPTICR_RXOUTIC;
|
||||
ul_recv_fifo_ptr[EP0] = 0;
|
||||
}
|
||||
|
||||
// Wait for IN FIFO to be ready to accept data or OUT FIFO to receive data.
|
||||
// Return true if new IN FIFO buffer available.
|
||||
uint32_t UDD_WaitForINOrOUT(void)
|
||||
{
|
||||
while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & (UOTGHS_DEVEPTISR_TXINI | UOTGHS_DEVEPTISR_RXOUTI)))
|
||||
;
|
||||
return ((UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXOUTI) == 0);
|
||||
}
|
||||
|
||||
uint32_t UDD_ReceivedSetupInt(void)
|
||||
{
|
||||
return UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXSTPI;
|
||||
}
|
||||
|
||||
void UDD_ClearSetupInt(void)
|
||||
{
|
||||
UOTGHS->UOTGHS_DEVEPTICR[EP0] = (UOTGHS_DEVEPTICR_RXSTPIC);
|
||||
}
|
||||
|
||||
uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len)
|
||||
{
|
||||
const uint8_t *ptr_src = data;
|
||||
uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep);
|
||||
uint32_t i;
|
||||
|
||||
TRACE_UOTGHS(printf("=> UDD_Send (1): ep=%d ul_send_fifo_ptr=%d len=%d\r\n", ep, ul_send_fifo_ptr[ep], len);)
|
||||
|
||||
if (ep == EP0)
|
||||
{
|
||||
if (ul_send_fifo_ptr[ep] + len > EP0_SIZE)
|
||||
len = EP0_SIZE - ul_send_fifo_ptr[ep];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ul_send_fifo_ptr[ep] + len > EPX_SIZE)
|
||||
len = EPX_SIZE - ul_send_fifo_ptr[ep];
|
||||
}
|
||||
|
||||
for (i = 0, ptr_dest += ul_send_fifo_ptr[ep]; i < len; ++i)
|
||||
*ptr_dest++ = *ptr_src++;
|
||||
|
||||
ul_send_fifo_ptr[ep] += i;
|
||||
|
||||
|
||||
if (ep == EP0)
|
||||
{
|
||||
TRACE_UOTGHS(printf("=> UDD_Send (2): ep=%d ptr_dest=%d maxlen=%d\r\n", ep, ul_send_fifo_ptr[ep], EP0_SIZE);)
|
||||
if (ul_send_fifo_ptr[ep] == EP0_SIZE)
|
||||
{
|
||||
UDD_ClearIN(); // Fifo is full, release this packet
|
||||
UDD_WaitIN(); // Wait for new FIFO buffer to be ready
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ul_send_fifo_ptr[ep] == EPX_SIZE)
|
||||
{
|
||||
UDD_ClearIN(); // Fifo is full, release this packet
|
||||
UDD_WaitIN(); // Wait for new FIFO buffer to be ready
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void UDD_Send8(uint32_t ep, uint8_t data )
|
||||
{
|
||||
uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep);
|
||||
|
||||
TRACE_UOTGHS(printf("=> UDD_Send8 : ul_send_fifo_ptr=%d data=0x%x\r\n", ul_send_fifo_ptr[ep], data);)
|
||||
|
||||
ptr_dest[ul_send_fifo_ptr[ep]] = data;
|
||||
ul_send_fifo_ptr[ep] += 1;
|
||||
}
|
||||
|
||||
uint8_t UDD_Recv8(uint32_t ep)
|
||||
{
|
||||
uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep);
|
||||
uint8_t data = ptr_dest[ul_recv_fifo_ptr[ep]];
|
||||
|
||||
TRACE_UOTGHS(printf("=> UDD_Recv8 : ul_recv_fifo_ptr=%d\r\n", ul_recv_fifo_ptr[ep]);)
|
||||
|
||||
ul_recv_fifo_ptr[ep] += 1;
|
||||
return data;
|
||||
}
|
||||
|
||||
void UDD_Recv(uint32_t ep, uint8_t* data, uint32_t len)
|
||||
{
|
||||
uint8_t *ptr_src = (uint8_t *) &udd_get_endpoint_fifo_access8(ep);
|
||||
uint8_t *ptr_dest = data;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0, ptr_src += ul_recv_fifo_ptr[ep]; i < len; ++i)
|
||||
*ptr_dest++ = *ptr_src++;
|
||||
|
||||
ul_recv_fifo_ptr[ep] += i;
|
||||
}
|
||||
|
||||
void UDD_Stall(void)
|
||||
{
|
||||
UOTGHS->UOTGHS_DEVEPT = (UOTGHS_DEVEPT_EPEN0 << EP0);
|
||||
UOTGHS->UOTGHS_DEVEPTIER[EP0] = UOTGHS_DEVEPTIER_STALLRQS;
|
||||
}
|
||||
|
||||
|
||||
uint32_t UDD_FifoByteCount(uint32_t ep)
|
||||
{
|
||||
return ((UOTGHS->UOTGHS_DEVEPTISR[ep] & UOTGHS_DEVEPTISR_BYCT_Msk) >> UOTGHS_DEVEPTISR_BYCT_Pos);
|
||||
}
|
||||
|
||||
void UDD_ReleaseRX(uint32_t ep)
|
||||
{
|
||||
TRACE_UOTGHS(puts("=> UDD_ReleaseRX\r\n");)
|
||||
UOTGHS->UOTGHS_DEVEPTICR[ep] = (UOTGHS_DEVEPTICR_NAKOUTIC | UOTGHS_DEVEPTICR_RXOUTIC);
|
||||
UOTGHS->UOTGHS_DEVEPTIDR[ep] = UOTGHS_DEVEPTIDR_FIFOCONC;
|
||||
ul_recv_fifo_ptr[ep] = 0;
|
||||
}
|
||||
|
||||
void UDD_ReleaseTX(uint32_t ep)
|
||||
{
|
||||
TRACE_UOTGHS(printf("=> UDD_ReleaseTX ep=%d\r\n", ep);)
|
||||
UOTGHS->UOTGHS_DEVEPTICR[ep] = (UOTGHS_DEVEPTICR_NAKINIC | UOTGHS_DEVEPTICR_RXOUTIC | UOTGHS_DEVEPTICR_TXINIC);
|
||||
UOTGHS->UOTGHS_DEVEPTIDR[ep] = UOTGHS_DEVEPTIDR_FIFOCONC;
|
||||
ul_send_fifo_ptr[ep] = 0;
|
||||
}
|
||||
|
||||
// Return true if the current bank is not full.
|
||||
uint32_t UDD_ReadWriteAllowed(uint32_t ep)
|
||||
{
|
||||
return (UOTGHS->UOTGHS_DEVEPTISR[ep] & UOTGHS_DEVEPTISR_RWALL);
|
||||
}
|
||||
|
||||
void UDD_SetAddress(uint32_t addr)
|
||||
{
|
||||
TRACE_UOTGHS(printf("=> UDD_SetAddress : setting address to %d\r\n", addr);)
|
||||
|
||||
udd_configure_address(addr);
|
||||
udd_enable_address();
|
||||
}
|
||||
|
||||
uint32_t UDD_GetFrameNumber(void)
|
||||
{
|
||||
return udd_frame_number();
|
||||
}
|
||||
|
||||
#endif /* SAM3XA_SERIES */
|
404
hardware/arduino/sam/system/libsam/source/uotghs_host.c
Normal file
404
hardware/arduino/sam/system/libsam/source/uotghs_host.c
Normal file
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
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 "chip.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if SAM3XA_SERIES
|
||||
|
||||
#define TRACE_UOTGHS(x) x
|
||||
//#define TRACE_UOTGHS(x)
|
||||
|
||||
extern void (*gpf_isr)(void);
|
||||
|
||||
static uhd_vbus_state_t uhd_state = UHD_STATE_NO_VBUS;
|
||||
|
||||
static void UHD_ISR(void)
|
||||
{
|
||||
// Manage dis/connection event
|
||||
if (Is_uhd_disconnection() && Is_uhd_disconnection_int_enabled()) {
|
||||
printf(">>> UHD_ISR : Disconnection INT\r\n");
|
||||
uhd_ack_disconnection();
|
||||
uhd_disable_disconnection_int();
|
||||
// Stop reset signal, in case of disconnection during reset
|
||||
uhd_stop_reset();
|
||||
// Disable wakeup/resumes interrupts,
|
||||
// in case of disconnection during suspend mode
|
||||
//UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HWUPIEC
|
||||
// | UOTGHS_HSTIDR_RSMEDIEC
|
||||
// | UOTGHS_HSTIDR_RXRSMIEC;
|
||||
uhd_ack_connection();
|
||||
uhd_enable_connection_int();
|
||||
uhd_state = UHD_STATE_DISCONNECTED;
|
||||
return;
|
||||
}
|
||||
if (Is_uhd_connection() && Is_uhd_connection_int_enabled()) {
|
||||
printf(">>> UHD_ISR : Connection INT\r\n");
|
||||
uhd_ack_connection();
|
||||
uhd_disable_connection_int();
|
||||
uhd_ack_disconnection();
|
||||
uhd_enable_disconnection_int();
|
||||
//uhd_enable_sof();
|
||||
uhd_state = UHD_STATE_CONNECTED;
|
||||
return;
|
||||
}
|
||||
|
||||
// Manage Vbus error
|
||||
if (Is_uhd_vbus_error_interrupt())
|
||||
{
|
||||
printf(">>> UHD_ISR : VBUS error INT\r\n");
|
||||
uhd_ack_vbus_error_interrupt();
|
||||
uhd_state = UHD_STATE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check USB clock ready after asynchronous interrupt
|
||||
while (!Is_otg_clock_usable())
|
||||
;
|
||||
otg_unfreeze_clock();
|
||||
|
||||
// Manage Vbus state change
|
||||
if (Is_otg_vbus_transition())
|
||||
{
|
||||
otg_ack_vbus_transition();
|
||||
if (Is_otg_vbus_high())
|
||||
{
|
||||
printf(">>> UHD_ISR : VBUS transition INT : UHD_STATE_DISCONNECT\r\n");
|
||||
uhd_state = UHD_STATE_DISCONNECTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(">>> UHD_ISR : VBUS transition INT : UHD_STATE_NO_VBUS\r\n");
|
||||
otg_freeze_clock();
|
||||
uhd_state = UHD_STATE_NO_VBUS;
|
||||
}
|
||||
printf(">>> UHD_ISR : VBUS transition INT : done.\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Other errors
|
||||
if (Is_uhd_errors_interrupt())
|
||||
{
|
||||
printf(">>> UHD_ISR : Other error INT\r\n");
|
||||
uhd_ack_errors_interrupt();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void UHD_SetStack(void (*pf_isr)(void))
|
||||
{
|
||||
gpf_isr = pf_isr;
|
||||
}
|
||||
|
||||
void UHD_Init(void)
|
||||
{
|
||||
irqflags_t flags;
|
||||
|
||||
// To avoid USB interrupt before end of initialization
|
||||
flags = cpu_irq_save();
|
||||
|
||||
// Setup USB Host interrupt callback
|
||||
UHD_SetStack(&UHD_ISR);
|
||||
|
||||
// Enables the USB Clock
|
||||
pmc_enable_upll_clock();
|
||||
pmc_switch_udpck_to_upllck(0); // div=0+1
|
||||
pmc_enable_udpck();
|
||||
pmc_enable_periph_clk(ID_UOTGHS);
|
||||
|
||||
// Always authorize asynchronous USB interrupts to exit of sleep mode
|
||||
// For SAM3 USB wake up device except BACKUP mode
|
||||
NVIC_SetPriority((IRQn_Type) ID_UOTGHS, 0);
|
||||
NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS);
|
||||
|
||||
// ID pin not used then force host mode
|
||||
otg_disable_id_pin();
|
||||
otg_force_host_mode();
|
||||
|
||||
// Signal is active low (because all SAM3X Pins are high after startup)
|
||||
// Hence VBOF must be low after connection request to power up the remote device
|
||||
uhd_set_vbof_active_low();
|
||||
|
||||
otg_enable_pad();
|
||||
otg_enable();
|
||||
|
||||
otg_unfreeze_clock();
|
||||
|
||||
// Check USB clock
|
||||
while (!Is_otg_clock_usable())
|
||||
;
|
||||
|
||||
// Clear all interrupts that may have been set by a previous host mode
|
||||
UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DCONNIC | UOTGHS_HSTICR_DDISCIC
|
||||
| UOTGHS_HSTICR_HSOFIC | UOTGHS_HSTICR_HWUPIC
|
||||
| UOTGHS_HSTICR_RSMEDIC | UOTGHS_HSTICR_RSTIC
|
||||
| UOTGHS_HSTICR_RXRSMIC;
|
||||
|
||||
otg_ack_vbus_transition();
|
||||
|
||||
// Enable Vbus change and error interrupts
|
||||
// Disable automatic Vbus control after Vbus error
|
||||
Set_bits(UOTGHS->UOTGHS_CTRL,
|
||||
UOTGHS_CTRL_VBUSHWC | UOTGHS_CTRL_VBUSTE | UOTGHS_CTRL_VBERRE);
|
||||
|
||||
uhd_enable_vbus();
|
||||
|
||||
// Force Vbus interrupt when Vbus is always high
|
||||
// This is possible due to a short timing between a Host mode stop/start.
|
||||
if (Is_otg_vbus_high())
|
||||
{
|
||||
otg_raise_vbus_transition();
|
||||
}
|
||||
|
||||
// Enable main control interrupt
|
||||
// Connection, SOF and reset
|
||||
UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTICR_DCONNIC;// | UOTGHS_HSTICR_RSTIC;// | UOTGHS_HSTICR_HSOFIC;
|
||||
|
||||
otg_freeze_clock();
|
||||
|
||||
uhd_state = UHD_STATE_NO_VBUS;
|
||||
|
||||
cpu_irq_restore(flags);
|
||||
}
|
||||
|
||||
void UHD_BusReset(void)
|
||||
{
|
||||
uhd_start_reset();
|
||||
}
|
||||
|
||||
uhd_vbus_state_t UHD_GetVBUSState(void)
|
||||
{
|
||||
return uhd_state;
|
||||
}
|
||||
|
||||
/*uhd_speed_t uhd_get_speed(void)
|
||||
{
|
||||
switch (uhd_get_speed_mode())
|
||||
{
|
||||
case UOTGHS_SR_SPEED_HIGH_SPEED:
|
||||
return UHD_SPEED_HIGH;
|
||||
|
||||
case UOTGHS_SR_SPEED_FULL_SPEED:
|
||||
return UHD_SPEED_FULL;
|
||||
|
||||
case UOTGHS_SR_SPEED_LOW_SPEED:
|
||||
return UHD_SPEED_LOW;
|
||||
|
||||
default:
|
||||
return UHD_SPEED_LOW;
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* \brief Allocate FIFO for pipe 0.
|
||||
*
|
||||
* \param ul_add Address of remote device for pipe 0.
|
||||
* \param ul_ep_size Actual size of the FIFO in bytes.
|
||||
*
|
||||
* \retval 0 success.
|
||||
* \retval 1 error.
|
||||
*/
|
||||
uint32_t UHD_EP0_Alloc(uint32_t ul_add, uint32_t ul_ep_size)
|
||||
{
|
||||
if (ul_ep_size < 8)
|
||||
{
|
||||
TRACE_UOTGHS(printf("/!\\ UHD_EP0_Alloc : incorrect pipe size!\r\n");)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (Is_uhd_pipe_enabled(0))
|
||||
{
|
||||
// Pipe is already allocated
|
||||
return 0;
|
||||
}
|
||||
|
||||
uhd_enable_pipe(0);
|
||||
uhd_configure_pipe(0, // Pipe 0
|
||||
0, // No frequency
|
||||
0, // Enpoint 0
|
||||
UOTGHS_HSTPIPCFG_PTYPE_CTRL,
|
||||
UOTGHS_HSTPIPCFG_PTOKEN_SETUP,
|
||||
ul_ep_size,
|
||||
UOTGHS_HSTPIPCFG_PBK_1_BANK, 0);
|
||||
|
||||
uhd_allocate_memory(0);
|
||||
|
||||
if (!Is_uhd_pipe_configured(0))
|
||||
{
|
||||
TRACE_UOTGHS(printf("/!\\ UHD_EP0_Alloc : incorrect pipe settings!\r\n");)
|
||||
uhd_disable_pipe(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uhd_configure_address(0, ul_add);
|
||||
|
||||
// Always enable stall and error interrupts of control endpoint
|
||||
/*uhd_enable_stall_interrupt(0);
|
||||
uhd_enable_pipe_error_interrupt(0);
|
||||
uhd_enable_pipe_interrupt(0);*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UHD_EP_Free(uint32_t add, uint32_t endp)
|
||||
{
|
||||
// Search endpoint(s) in all pipes
|
||||
for (uint8_t pipe = 0; pipe < UOTGHS_EPT_NUM; pipe++)
|
||||
{
|
||||
if (!Is_uhd_pipe_enabled(pipe))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (add != uhd_get_configured_address(pipe))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if (endp != 0xFF)
|
||||
{
|
||||
// Disable specific endpoint number
|
||||
if (endp != uhd_get_pipe_endpoint_address(pipe))
|
||||
{
|
||||
continue; // Mismatch
|
||||
}
|
||||
}
|
||||
*/
|
||||
// Unalloc pipe
|
||||
uhd_disable_pipe(pipe);
|
||||
uhd_unallocate_memory(pipe);
|
||||
uhd_reset_pipe(pipe);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t UHD_EP_Read(uint32_t ul_ep, uint32_t ul_size, uint8_t* data)
|
||||
{
|
||||
uint8_t *ptr_ep_data = 0;
|
||||
uint8_t nb_byte_received = 0;
|
||||
uint32_t ul_nb_trans = 0;
|
||||
|
||||
// Get information to read data
|
||||
nb_byte_received = uhd_byte_count(ul_ep);
|
||||
|
||||
ptr_ep_data = (uint8_t *) & uhd_get_pipe_fifo_access(ul_ep, 8);
|
||||
|
||||
// Copy data from pipe to payload buffer
|
||||
while (ul_size && nb_byte_received) {
|
||||
*data++ = *ptr_ep_data++;
|
||||
ul_nb_trans++;
|
||||
ul_size--;
|
||||
nb_byte_received--;
|
||||
}
|
||||
|
||||
return ul_nb_trans;
|
||||
}
|
||||
|
||||
void UHD_EP_Write(uint32_t ul_ep, uint32_t ul_size, uint8_t* data)
|
||||
{
|
||||
volatile uint8_t *ptr_ep_data = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
// Check pipe
|
||||
if (!Is_uhd_pipe_enabled(ul_ep))
|
||||
{
|
||||
// Endpoint not valid
|
||||
TRACE_UOTGHS(printf("/!\\ UHD_EP_Send : pipe is not enabled!\r\n");)
|
||||
return;
|
||||
}
|
||||
|
||||
ptr_ep_data = (volatile uint8_t *)&uhd_get_pipe_fifo_access(ul_ep, 8);
|
||||
for (i = 0; i < ul_size; ++i)
|
||||
*ptr_ep_data++ = *data++;
|
||||
}
|
||||
|
||||
void UHD_EP_Send(uint32_t ul_ep, uint32_t ul_token_type)
|
||||
{
|
||||
// Check pipe
|
||||
if (!Is_uhd_pipe_enabled(ul_ep))
|
||||
{
|
||||
// Endpoint not valid
|
||||
TRACE_UOTGHS(printf("/!\\ UHD_EP_Send : pipe is not enabled!\r\n");)
|
||||
return;
|
||||
}
|
||||
|
||||
// Set token type
|
||||
uhd_configure_pipe_token(ul_ep, ul_token_type);
|
||||
|
||||
// Clear interrupt flags
|
||||
uhd_ack_setup_ready(ul_ep);
|
||||
uhd_ack_in_received(ul_ep);
|
||||
uhd_ack_out_ready(ul_ep);
|
||||
uhd_ack_short_packet(ul_ep);
|
||||
|
||||
// Send actual packet
|
||||
uhd_ack_fifocon(ul_ep);
|
||||
uhd_unfreeze_pipe(ul_ep);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check is transfer is complete.
|
||||
*
|
||||
* \param ul_add Address of remote device for pipe 0.
|
||||
* \param ul_ep_size Actual size of the FIFO in bytes.
|
||||
*
|
||||
* \retval 0 transfer is not complete.
|
||||
* \retval 1 transfer is complete.
|
||||
*/
|
||||
uint32_t UHD_EP_Is_Transfer_Complete(uint32_t ul_ep, uint32_t ul_token_type)
|
||||
{
|
||||
// Check for transfer completion depending on token type
|
||||
switch (ul_token_type)
|
||||
{
|
||||
case UOTGHS_HSTPIPCFG_PTOKEN_SETUP:
|
||||
if (Is_uhd_setup_ready(ul_ep))
|
||||
{
|
||||
uhd_freeze_pipe(ul_ep);
|
||||
uhd_ack_setup_ready(ul_ep);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case UOTGHS_HSTPIPCFG_PTOKEN_IN:
|
||||
if (Is_uhd_in_received(ul_ep))
|
||||
{
|
||||
// In case of low USB speed and with a high CPU frequency,
|
||||
// a ACK from host can be always running on USB line
|
||||
// then wait end of ACK on IN pipe.
|
||||
while(!Is_uhd_pipe_frozen(ul_ep))
|
||||
;
|
||||
|
||||
// IN packet received
|
||||
uhd_ack_in_received(ul_ep);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
case UOTGHS_HSTPIPCFG_PTOKEN_OUT:
|
||||
if (Is_uhd_out_ready(ul_ep))
|
||||
{
|
||||
// OUT packet sent
|
||||
uhd_freeze_pipe(ul_ep);
|
||||
uhd_ack_out_ready(ul_ep);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing to report
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SAM3XA_SERIES */
|
Reference in New Issue
Block a user