📄 srcout_m.c
字号:
#pragma NOIV // Do not generate interrupt vectors
//-----------------------------------------------------------------------------
// File: srcout_m.c
// Contents: Hooks required to implement USB peripheral function.
// Code written for EZUSB FX2 128-pin REVE...
// Firmware tested on EZUSB FX2 128-pin (CY3681 DK)
// Copyright (c) 2001 Cypress Semiconductor All rights reserved
//-----------------------------------------------------------------------------
#include "fx2.h"
#include "fx2regs.h"
#include "fx2sdly.h" // SYNCDELAY macro
extern BOOL GotSUD; // Received setup data flag
extern BOOL Sleep;
extern BOOL Rwuen;
extern BOOL Selfpwr;
BYTE Configuration; // Current configuration
BYTE AlternateSetting; // Alternate settings
// proto's from "gpif.c"
void GpifInit( void );
// ...debug LEDs: accessed via movx reads only ( through CPLD )
xdata volatile const BYTE LED0_ON _at_ 0x8000;
xdata volatile const BYTE LED0_OFF _at_ 0x8100;
xdata volatile const BYTE LED1_ON _at_ 0x9000;
xdata volatile const BYTE LED1_OFF _at_ 0x9100;
xdata volatile const BYTE LED2_ON _at_ 0xA000;
xdata volatile const BYTE LED2_OFF _at_ 0xA100;
xdata volatile const BYTE LED3_ON _at_ 0xB000;
xdata volatile const BYTE LED3_OFF _at_ 0xB100;
// it may be worth noting here that the default monitor loads at 0xC000
// use this global variable when (de)asserting debug LEDs...
BYTE ledX_rdvar = 0x00;
// 512 for high speed, 64 for full speed
static WORD enum_pkt_size = 0x0000;
// when set firmware running in TD_Poll( ); handles data transfers
BOOL td_poll_handles_transfers = 0;
//-----------------------------------------------------------------------------
// Task Dispatcher hooks
// The following hooks are called by the task dispatcher.
//-----------------------------------------------------------------------------
void TD_Init( void )
{ // Called once at startup
CPUCS = 0x10; // CLKSPD[1:0]=10, for 48MHz operation
// CLKOE=0, don't drive CLKOUT
GpifInit( ); // init GPIF engine via GPIFTool output file
// Registers which require a synchronization delay, see section 15.14
// FIFORESET FIFOPINPOLAR
// INPKTEND OUTPKTEND
// EPxBCH:L REVCTL
// GPIFTCB3 GPIFTCB2
// GPIFTCB1 GPIFTCB0
// EPxFIFOPFH:L EPxAUTOINLENH:L
// EPxFIFOCFG EPxGPIFFLGSEL
// PINFLAGSxx EPxFIFOIRQ
// EPxFIFOIE GPIFIRQ
// GPIFIE GPIFADRH:L
// UDMACRCH:L EPxGPIFTRIG
// GPIFTRIG
// Note: The pre-REVE EPxGPIFTCH/L register are affected, as well...
// ...these have been replaced by GPIFTC[B3:B0] registers
SYNCDELAY; // see TRM section 15.14
REVCTL = 0x01; // use enhanced packet handling
// NOTEME: explain what all happens when REVCTL.0=1
// EP2 512 BULK OUT 4x
SYNCDELAY; // see TRM section 15.14
EP2CFG = 0xA0; // BUF[1:0]=00 for 4x buffering
// EP6 512 BULK IN 4x
SYNCDELAY; //
EP6CFG = 0xE0; // BUF[1:0]=00 for 4x buffering
// EP4 and EP8 are not used in this implementation...
SYNCDELAY; //
EP4CFG = 0x20; // clear valid bit
SYNCDELAY; //
EP8CFG = 0x60; // clear valid bit
SYNCDELAY; //
FIFORESET = 0x80; // activate NAK-ALL to avoid race conditions
SYNCDELAY; //
FIFORESET = 0x02; // reset, FIFO 2
SYNCDELAY; //
FIFORESET = 0x04; // reset, FIFO 4
SYNCDELAY; //
FIFORESET = 0x06; // reset, FIFO 6
SYNCDELAY; //
FIFORESET = 0x08; // reset, FIFO 8
SYNCDELAY; //
FIFORESET = 0x00; // deactivate NAK-ALL
// 8-bit bus (WORDWIDE=0)...
SYNCDELAY; //
EP2FIFOCFG = 0x00;
SYNCDELAY; //
EP6FIFOCFG = 0x04;
// OUT endp's come up "unarmed" in the cpu domain
// ...to "arm" the endp's when AUTOOUT=0 the cpu write's OUTPKTEND w/skip=1 (N times)
SYNCDELAY; //
OUTPKTEND = 0x82; // arm first buffer
SYNCDELAY; //
OUTPKTEND = 0x82; // arm second buffer
SYNCDELAY; //
OUTPKTEND = 0x82; // arm third buffer
SYNCDELAY; //
OUTPKTEND = 0x82; // arm fourth buffer
SYNCDELAY; //
// IN endp's come up in the cpu/peripheral domain
// setup INT4 as internal source for GPIF interrupts
// using INT4CLR (SFR), automatically enabled
INTSETUP |= 0x03; // Enable INT4 FIFO/GPIF Autovectoring
SYNCDELAY; // used here as "delay"
EXIF &= ~0x40; // just in case one was pending...
SYNCDELAY; // used here as "delay"
GPIFIRQ = 0x02;
SYNCDELAY; //
GPIFIE = 0x02; // Enable GPIFWF interrupt
SYNCDELAY; //
EIE |= 0x04; // Enable INT4 ISR, EIE.2(EIEX4=1)
// turn debug LED[3:0] off...
ledX_rdvar = LED0_OFF;
ledX_rdvar = LED1_OFF;
ledX_rdvar = LED2_OFF;
ledX_rdvar = LED3_OFF;
}
#define GPIFTRIGWR 0
#define GPIFTRIGRD 4
#define GPIF_EP2 0
#define GPIF_EP4 1
#define GPIF_EP6 2
#define GPIF_EP8 3
void TD_Poll( void )
{ // Called repeatedly while the device is idle
static WORD xFIFOTC_OUT = 0x0000;
// Registers which require a synchronization delay, see section 15.14
// FIFORESET FIFOPINPOLAR
// INPKTEND OUTPKTEND
// EPxBCH:L REVCTL
// GPIFTCB3 GPIFTCB2
// GPIFTCB1 GPIFTCB0
// EPxFIFOPFH:L EPxAUTOINLENH:L
// EPxFIFOCFG EPxGPIFFLGSEL
// PINFLAGSxx EPxFIFOIRQ
// EPxFIFOIE GPIFIRQ
// GPIFIE GPIFADRH:L
// UDMACRCH:L EPxGPIFTRIG
// GPIFTRIG
// Note: The pre-REVE EPxGPIFTCH/L register are affected, as well...
// ...these have been replaced by GPIFTC[B3:B0] registers
if( td_poll_handles_transfers )
{
// Handle OUT data...
// is the host sending data...
if( !( EP2468STAT & 0x01 ) )
{
// EP2EF=0, when endp buffer "not" empty
// ...at this point the pkt. switched from the usb domain to the cpu domain
// if the host sent a pkt... then a buffer was available
// AUTOOUT=0, so pass pkt. to peripheral domain - (GPIF)
SYNCDELAY;
OUTPKTEND = 0x02; // w/skip=0
}
else
{
// host is "not" sending data...
}
// is the peripheral interface idle...
if( GPIFTRIG & 0x80 )
{
// DONE=1, when GPIF is "idle"
// check if there's a pkt in the peripheral domain...
if( EP24FIFOFLGS & 0x02 )
{
// ...EF=1 when buffer "empty", no more data to xfr.
}
else
{
// EF=0, when slave fifo is "not empty"
// ...the cpu passed the pkt. to the peripheral domain
// check if peripheral "not full"...
if( GPIFREADYSTAT & 0x02 )
{
// RDY1=1, when peripheral is "not" FULL (tied to peripheral "full" flag)
xFIFOTC_OUT = ( ( EP2FIFOBCH << 8 ) + EP2FIFOBCL );
// setup GPIF transaction count
SYNCDELAY;
EP2GPIFTCH = EP2FIFOBCH;
SYNCDELAY;
EP2GPIFTCL = EP2FIFOBCL;
// trigger FIFO write transaction(s), using SFR
// R/W=0, EP[1:0]=00 for EP2 write(s)
SYNCDELAY;
GPIFTRIG = GPIFTRIGWR | GPIF_EP2;
// NOTE: 512 bytes transfers in ~75usec on 8-bit async bus
// ...once master (GPIF) drains OUT pkt, it (re)arms to usb domain
if( xFIFOTC_OUT < enum_pkt_size )
{
// handle short pkt. to peripheral
// wait for the transaction to terminate naturally...
while( !( GPIFTRIG & 0x80 ) )
{
// should take <75usec @ 8-bit async.
; // poll GPIFTRIG.7, DONE bit...
}
// signal "shortpkt" to peripheral peripheral here...
}
else
{
// was max. pkt. size...
// ...let transaction terminate naturally...
}
}
else
{
// RDY1=0, when peripheral is FULL
}
}
}
else
{
// DONE=0 when GPIF is "not" IDLE...
}
// Handle IN data...
// is the peripheral interface idle...
if( GPIFTRIG & 0x80 )
{
// check if peripheral "not empty"...
if( GPIFREADYSTAT & 0x01 )
{
// RDY0=1, when peripheral "not" empty...
if( EP68FIFOFLGS & 0x01 )
{
// EP6FF=1, when fifo "full"
}
else
{
// EP6FF=0, when fifo "not full", buffer available...
// setup GPIF transaction count
SYNCDELAY;
EP6GPIFTCH = 0x02;
SYNCDELAY;
EP6GPIFTCL = 0x00;
SYNCDELAY;
// trigger FIFO read transaction(s), using SFR
// R/W=1, EP[1:0]=FIFO_EpNum for EPx read(s)
GPIFTRIG = GPIFTRIGRD | GPIF_EP6;
// NOTE: 512 bytes transfers in ~75usec on 8-bit async bus
// NOTE: 64 bytes transfers in ~10usec on 8-bit async bus
// wait for the transaction to terminate naturally...
SYNCDELAY; //
while( !( GPIFTRIG & 0x80 ) )
{
// should take <75usec @ 8-bit async.
; // poll GPIFTRIG.7, DONE bit...
}
// AUTOIN=0, so 8051 pass pkt. to host...
SYNCDELAY; //
INPKTEND = 0x06; // w/skip=0;.commit however many bytes in pkt.
SYNCDELAY; //
// ...NOTE: this also handles "shortpkt"
}
}
else
{
// master has all the data the peripheral sent...
}
}
else
{
// peripheral interface busy...
}
}
else
{
// handle data transfers via vend_ax cmnds...
}
}
BOOL TD_Suspend( void )
{ // Called before the device goes into suspend mode
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
if( EZUSB_HIGHSPEED( ) )
{ // ...FX2 in high speed mode
SYNCDELAY; //
EP6AUTOINLENH = 0x02; // set core AUTO commit len = 512 bytes
SYNCDELAY; //
EP6AUTOINLENL = 0x00;
SYNCDELAY; //
enum_pkt_size = 512; // max. pkt. size = 512 bytes
}
else
{ // ...FX2 in full speed mode
SYNCDELAY; //
EP6AUTOINLENH = 0x00; // set core AUTO commit len = 64 bytes
SYNCDELAY; //
EP6AUTOINLENL = 0x40;
SYNCDELAY; //
enum_pkt_size = 64; // max. pkt. size = 64 bytes
}
Configuration = SETUPDAT[ 2 ];
return( TRUE ); // Handled by user code
}
BOOL DR_GetConfiguration( void )
{ // Called when a Get Configuration command is received
EP0BUF[ 0 ] = Configuration;
EP0BCH = 0;
EP0BCL = 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
EP0BUF[ 0 ] = AlternateSetting;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -