www.pudn.com > FX GPIF.zip > gfbrds.c
#pragma NOIV // Do not generate interrupt vectors
//-----------------------------------------------------------------------------
// File: gfbrds.c
// Contents: Hooks required to implement USB peripheral function.
// EZUSB FX GPIF firmware to "pass-on" USB pkts to/from slave.
// Copyright (c) 2001 Cypress Semiconductor All rights reserved
//-----------------------------------------------------------------------------
#include "ezusb.h"
#include "ezregs.h"
#include "Fx.h"
extern BOOL GotSUD; // Received setup data flag
extern BOOL Sleep;
// proto's from ...\gpif.c
void GpifInit( void );
// local proto needed for BKPT LED address trigger
void TD_Poll( void );
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
BYTE Configuration; // Current configuration
BYTE AlternateSetting; // Alternate settings
sbit PA0 = IOA ^ 0; // GSTATE[ 0 ]
sbit PA1 = IOA ^ 1; // GSTATE[ 1 ]
sbit PA2 = IOA ^ 2; // GSTATE[ 2 ]
sbit PA3 = IOA ^ 3;
sbit PA6 = IOA ^ 6;
sbit PA7 = IOA ^ 7;
sbit PC0 = IOC ^ 0;
sbit PC1 = IOC ^ 1;
sbit PC2 = IOC ^ 2; // INTO#, tied to slave PC3 pin, issue zerolenpkt
sbit SHORTPKT = IOC ^ 3; // tied to slave INT0# pin, issue shortpkt
sbit PC4 = IOC ^ 4;
sbit PC5 = IOC ^ 5;
sbit PC6 = IOC ^ 6;
sbit PC7 = IOC ^ 7;
// ISR action needed flags, typically set via ISR, clr via foreground...
BOOL zerolenpkt = 0; // slave issued zerolenpkt
// ...idle system service this event in ~8usec
// ...busy system could take ~20usec or so...
BOOL xfrvia_TD_Poll = 0; // switch between TD_Poll() and VendorCmd()
// ...also, used to sequence master/slave POR
// Rev. D FX DK board, addr decode (movx reads only) via CPLD
xdata volatile const unsigned char LED0_ON _at_ 0x8000;
xdata volatile const unsigned char LED0_OFF _at_ 0x8100;
xdata volatile const unsigned char LED1_ON _at_ 0x9000;
xdata volatile const unsigned char LED1_OFF _at_ 0x9100;
xdata volatile const unsigned char LED2_ON _at_ 0xA000;
xdata volatile const unsigned char LED2_OFF _at_ 0xA100;
xdata volatile const unsigned char LED3_ON _at_ 0xB000;
xdata volatile const unsigned char LED3_OFF _at_ 0xB100;
// it may be worth noting that by default the Keil mon-51
// ...utility loads at 0xE000 and above
// use this global (gfbrds.c) variable when (de)asserting debug LEDs...
BYTE ledX_rdvar = 0x00;
//-----------------------------------------------------------------------------
// Task Dispatcher hooks
// The following hooks are called by the task dispatcher.
//-----------------------------------------------------------------------------
void TD_Init( void )
{ // Called once at startup
CPUCS &= 0xFD; // don't drive CLKOUT (CLKOE=0)
PORTSETUP |= 0x01; // use SFR, "mov" versions of PORT I/O
OEC = 0x08; // setup PC3 as an output, SHORTPKT
SHORTPKT = 1; // SHORTPKT -> high-low-high transition...
IN07VAL = 0x04; // enable endp 2 IN
OUT07VAL = 0x04; // enable endp 2 OUT
USBPAIR = 0x09; // enable 2x buffering on both endp's
BPADDR = ( WORD )TD_Poll; // set breakpoint to trigger on TD_Poll()
USBBAV |= 0x02; // BPEN=1, enable breakpoint feature
USBBAV &= 0xFB; // BPPULSE=0, disable breakpoint pulse mode
GpifInit( ); // Configure GPIF from GPIFTool output file
IFCONFIG |= 0x08; // GSTATE=1, drive GSTATE[2:0] out on PORTA[2:0]
// XCLKSEL pin determines if slave interface is:
// HIGH = sync (use XCLK pin to clock interface) or
// LOW = async (use internal 48MHz to clock interface)
ABSETUP |= 0x20; // GPIFTool issue with not setting ABSETUP.5=1(ASYNC)
// - when user selects ->
// - "Interface Timing Async"
GPIFADRL = 0x00; // gaddr[5:0] not used, asserts during GPIF WF
AINTC = 0x40; // tc=64, FITC=0 (set to max, tc for INs)
AOUTTC = 0x40; // tc=64, FITC=0 (set to max, tc for OUTs)
PORTCCFG |= 0x04; // alt. func INTO#
// enable INTO# external pin interrupt, used by slave to issue SHORTPKT
EX0 = 1; // enable INT0# pin ISR
IT0 = 1; // configure INT0# pin, edge trigger
// turn debug LED[3:0] off...
ledX_rdvar = LED0_OFF;
ledX_rdvar = LED1_OFF;
ledX_rdvar = LED2_OFF;
ledX_rdvar = LED3_OFF;
}
void TD_Poll( void )
{ // Called repeatedly while the device is idle
static BYTE AFIFOTC_OUT = 0x00; // store var for testing shortpkt
BYTE xfr = 0x00; // dummy var for GPIF triggers
if( xfrvia_TD_Poll )
{
// is the host sending data...OR is the fifo not empty
if( !( OUT2CS & 0x02 ) || !( ABOUTCS & 0x10 ) )
{ // OUT2BSY=0, when endp FIFO "not" empty, host sent pkt.
if( ABOUTCS & 0x10 )
{ // AOUTEF=1, when slave FIFO buffer available...
ledX_rdvar = LED0_ON;
// "pass-on" pkt. to master (GPIF)
DMALEN = OUT2BC;
if( DMALEN )
{
DMASRC = &OUT2BUF; // pointing to address of EP2OUT
DMADEST = &AOUTDATA; // pointing to address of AOUTFIFO
EA = 0; // protect against interrupts in Block0
DMAGO = 0xFF; // dummy write to start xfr
while( !( DMAGO & 0x80 ) )
{ // this 8051 doesn't mind waiting here
; // ... for DMADONE, ~1.5usec (64 bytes)
}
EA = 1; // (re)enable interrupts...
}
else
{ // Warning: DMA engine xfr's 256 bytes when DMALEN=0
// DO NOT DMA data, handle host sending zerolen OUT pkt to master...
SHORTPKT = 0;
AFIFOTC_OUT = 0x00;
SHORTPKT = 1; // signal SHORTPKT to slave
}
OUT2BC = 0x00; // (re)arm the endp
}
else
{ // AOUTEF=0, when slave FIFO buffer "not" available (is "not-empty")...
if( IDLE_CS & 0x80 )
{ // if GPIF done then check slave status...
if( !( READY & 0x10 ) )
{ // RDY4=0, when slave is "not" FULL (tied to slave "full" flag)
AFIFOTC_OUT = AOUTBC;
AOUTTC = AOUTBC; // tc=bc, FITC=0
// xfr pkt. to peripheral, via GPIF
ATRIG = AOUTBC; // launch... AFIFO -> GPIF transaction(s)
if( AFIFOTC_OUT < 0x40 )
{ // handle short pkt. to slave, via PC3...
while( !( IDLE_CS & 0x80 ) )
{ // should take <15usec @ 8-bit async.
; // ~200nsec/write byte to slave...
}
SHORTPKT = 0; // Needs to be >4 instr. cycles long...
AFIFOTC_OUT = 0x00;
SHORTPKT = 1; // signal SHORTPKT to slave
}
else
{ // was max pkt. size...
}
}
else
{ // RDY4=1, when slave is FULL (tied to AINFF)
}
}
else
{ // peripheral interface busy...
}
}
}
else
{ // host is "not" sending data...
ledX_rdvar = LED0_OFF;
}
// does slave have data... OR do we already have data for the host...
if( IDLE_CS & 0x80 )
{ // if GPIF done then check slave status...
if( !( READY & 0x04 ) || !( ABINTF & 0x10 ) || ( zerolenpkt ) )
{ // RDY2=0, when slave "not" empty... (slave "not" empty flag, AOUTPF)
ledX_rdvar = LED1_ON;
if( (ABINTF & 0x10 ) && ( !zerolenpkt ) )
{ // AINEF=1, when buffer available...
// ...try to read 64 bytes (max pkt size) from slave
xfr = ATRIG; // launch... GPIF -> AFIFO transaction(s)
// should take <15usec @ 8-bit async...
// ~200nsec/read byte from slave...
}
else
{
if( !( IN2CS & 0x02 ) )
{ // IN2BUSY=0 when buffer available...
DMALEN = AINBC;
if( DMALEN )
{
DMASRC = &AINDATA;// pointing to address of AINFIFO
DMADEST = &IN2BUF;// pointing to address of EP2IN
EA = 0; // protect against interrupts in Block0
DMAGO = 0xFF; // dummy write to start xfr
while( !( DMAGO & 0x80 ) )
{ // this 8051 doesn't mind waiting here
; // ... for DMADONE, ~1.5usec (64 bytes)
}
EA = 1; // (re)enable interrupts...
}
else
{ // DO NOT DMA the data...
// "shortpkt" should have already taken care of this...
zerolenpkt = 0; // clr action needed flag
EX0 = 1; // (re)enable INT0# pin ISR
}
IN2BC = DMALEN; // arm endp, using bytes read via GPIF
}
else
{ // if EP busy then host is behind...
// ...and we still have two buffers containing data
}
}
}
else
{ // host has all the data the slave sent...
ledX_rdvar = LED1_OFF;
}
}
else
{ // peripheral interface busy...
}
}
else
{ // handle xfr via DR_VendorCmd
}
// turn off breakpoint LED
USBBAV |= 0x08;
}
BOOL TD_Suspend(void) // Called before the device goes into suspend mode
{
// Turn off breakpoint light before entering suspend
USBBAV |= bmBREAK; // Clear the breakpoint
return(TRUE);
}
BOOL TD_Resume(void) // Called after the device resumes
{
return(TRUE);
}
//-----------------------------------------------------------------------------
// Device Request hooks
// The following hooks are called by the end point 0 device request parser.
//-----------------------------------------------------------------------------
BOOL DR_GetDescriptor(void)
{
return(TRUE);
}
BOOL DR_SetConfiguration(void) // Called when a Set Configuration command is received
{
Configuration = SETUPDAT[2];
return(TRUE); // Handled by user code
}
BOOL DR_GetConfiguration(void) // Called when a Get Configuration command is received
{
IN0BUF[0] = Configuration;
EZUSB_SET_EP_BYTES(IN0BUF_ID,1);
return(TRUE); // Handled by user code
}
BOOL DR_SetInterface(void) // Called when a Set Interface command is received
{
AlternateSetting = SETUPDAT[2];
return(TRUE); // Handled by user code
}
BOOL DR_GetInterface(void) // Called when a Set Interface command is received
{
IN0BUF[0] = AlternateSetting;
EZUSB_SET_EP_BYTES(IN0BUF_ID,1);
return(TRUE); // Handled by user code
}
BOOL DR_GetStatus(void)
{
return(TRUE);
}
BOOL DR_ClearFeature(void)
{
return(TRUE);
}
BOOL DR_SetFeature(void)
{
return(TRUE);
}
#define VX_B0 0xB0 // abort GPIF
#define VX_B1 0xB1 // flush/reset slave FIFOs
#define VX_B2 0xB2 // handle data xfr via TD_Poll
#define VX_B3 0xB3 // handle data xfr via DR_VendorCmd
#define VX_B4 0xB4 // clear debug leds
#define VX_B5 0xB5 // read aout fifo bc
#define VX_B6 0xB6 // read DONE
#define VX_B7 0xB7 // read aout fifo tc
#define VX_B8 0xB8 // read ain fifo tc
BOOL DR_VendorCmnd( void )
{
switch( SETUPDAT[ 1 ] )
{
case VX_B0:
{ // ABORT GPIF waveform
ABORT = 0xFF;
*IN0BUF = 0xB0; // return command type
break;
}
case VX_B1:
{ // flush slave FIFOs
ABFLUSH = 0xFF;
*IN0BUF = 0xB1; // return command type
break;
}
case VX_B2:
{ // handle data xfr via TD_Poll
zerolenpkt = 0; // clr flag, just in case one was pending
EX0 = 1; // (re)enable INT0# pin ISR
ledX_rdvar = LED3_OFF;
xfrvia_TD_Poll = 1;
*IN0BUF = 0xB2; // return command type
break;
}
case VX_B3:
{ // handle data xfr via DR_VendorCmd
xfrvia_TD_Poll = 0;
*IN0BUF = 0xB3; // return command type
break;
}
case VX_B4:
{ // clear debug leds
ledX_rdvar = LED0_OFF;
ledX_rdvar = LED1_OFF;
ledX_rdvar = LED2_OFF;
ledX_rdvar = LED3_OFF;
*IN0BUF = 0xB4; // return command type
break;
}
case VX_B5:
{ // read aout fifo bc
*IN0BUF = AOUTBC; // return command type
break;
}
case VX_B6:
{ // read DONE
*IN0BUF = IDLE_CS; // return command type
break;
}
case VX_B7:
{ // read aout fifo tc
*IN0BUF = AOUTTC; // return command type
break;
}
case VX_B8:
{ // read ain fifo tc
*IN0BUF = AINTC; // return command type
break;
}
default:
{
break;
}
}
IN0BC = 0x01; // arm endp, # bytes to xfr
EP0CS |= bmBIT1; // ack handshake phase of device request
return( FALSE ); // no errors, cmd handled okay
}
//-----------------------------------------------------------------------------
// USB Interrupt Handlers
// The following functions are called by the USB interrupt jump table.
//-----------------------------------------------------------------------------
// Setup Data Available Interrupt Handler
void ISR_Sudav(void) interrupt 0
{
GotSUD = TRUE; // Set flag
EZUSB_IRQ_CLEAR();
USBIRQ = bmSUDAV; // Clear SUDAV IRQ
}
// Setup Token Interrupt Handler
void ISR_Sutok(void) interrupt 0
{
EZUSB_IRQ_CLEAR();
USBIRQ = bmSUTOK; // Clear SUTOK IRQ
}
void ISR_Sof(void) interrupt 0
{
EZUSB_IRQ_CLEAR();
USBIRQ = bmSOF; // Clear SOF IRQ
}
void ISR_Ures(void) interrupt 0
{
EZUSB_IRQ_CLEAR();
USBIRQ = bmURES; // Clear URES IRQ
}
// ISR for the IN Bulk NAK (IBN) interrupt.
void ISR_IBN(void) interrupt 0
{
}
void ISR_Susp(void) interrupt 0
{
Sleep = TRUE;
EZUSB_IRQ_CLEAR();
USBIRQ = bmSUSP;
}
void ISR_Ep0in(void) interrupt 0
{
}
void ISR_Ep0out(void) interrupt 0
{
}
void ISR_Ep1in(void) interrupt 0
{
}
void ISR_Ep1out(void) interrupt 0
{
}
void ISR_Ep2in(void) interrupt 0
{
}
void ISR_Ep2out( void ) interrupt 0
{
}
void ISR_Ep3in(void) interrupt 0
{
}
void ISR_Ep3out(void) interrupt 0
{
}
void ISR_Ep4in(void) interrupt 0
{
}
void ISR_Ep4out(void) interrupt 0
{
}
void ISR_Ep5in(void) interrupt 0
{
}
void ISR_Ep5out(void) interrupt 0
{
}
void ISR_Ep6in(void) interrupt 0
{
}
void ISR_Ep6out(void) interrupt 0
{
}
void ISR_Ep7in(void) interrupt 0
{
}
void ISR_Ep7out(void) interrupt 0
{
}
//-----------------------------------------------------------------------------
// INT4 Interrupt Handlers
// The following functions are called by the INT4 interrupt jump table.
//-----------------------------------------------------------------------------
void ISR_AINPF(void) interrupt 0
{
// EXIF &= ~0x40;
// ABINIRQ = bmAINPF; // Clear AINPF IRQ
}
void ISR_AINEF(void) interrupt 0
{
// EXIF &= ~0x40;
// ABINIRQ = bmAINEF; // Clear AINEF IRQ
}
void ISR_AINFF(void) interrupt 0
{
// EXIF &= ~0x40;
// ABINIRQ = bmAINFF; // Clear AINFF IRQ
}
void ISR_BINPF(void) interrupt 0
{
// EXIF &= ~0x40;
// ABINIRQ = bmBINPF; // Clear BINPF IRQ
}
void ISR_BINEF(void) interrupt 0
{
// EXIF &= ~0x40;
// ABINIRQ = bmBINEF; // Clear BINEF IRQ
}
void ISR_BINFF(void) interrupt 0
{
// EXIF &= ~0x40;
// ABINIRQ = bmBINFF; // Clear BINFF IRQ
}
void ISR_AOUTPF(void) interrupt 0
{
// EXIF &= ~0x40;
// ABOUTIRQ = bmAOUTPF; // Clear AOUTPF IRQ
}
void ISR_AOUTEF(void) interrupt 0
{
// EXIF &= ~0x40;
// ABINIRQ = bmAOUTEF; // Clear AOUTEF IRQ
}
void ISR_AOUTFF(void) interrupt 0
{
// EXIF &= ~0x40;
// ABINIRQ = bmAOUTFF; // Clear AOUTFF IRQ
}
void ISR_BOUTPF(void) interrupt 0
{
// EXIF &= ~0x40;
// ABINIRQ = bmBOUTPF; // Clear BOUTPF IRQ
}
void ISR_BOUTEF(void) interrupt 0
{
// EXIF &= ~0x40;
// ABINIRQ = bmBOUTEF; // Clear BOUTEF IRQ
}
void ISR_BOUTFF(void) interrupt 0
{
// EXIF &= ~0x40;
// ABINIRQ = bmBOUTFF; // Clear BOUTFF IRQ
}
void ISR_GPIFDONE(void) interrupt 0
{
// EXIF &= ~0x40;
// GENIRQ = bmGPIFDONE; // Clear GPIFDONE IRQ
}
void ISR_GPIFWF( void )
interrupt 0
{ // GPIF FIFORd WF detected slave empty
ABORT = 0xFF; // abort to handle shortpkt
EXIF &= ~0x40;
GENIRQ = bmGPIFWF; // Clear GPIFWF IRQ
//TGE INT4CLR = 0xFF; // need to first enable AUTOCLR feature...
}
void ISR_DMADONE(void) interrupt 0
{
// EXIF &= ~0x40;
// GENIRQ = bmDMADONE; // Clear DMADONE IRQ
}