?? gpiflongxfr.c
字號:
#pragma NOIV // Do not generate interrupt vectors
//-----------------------------------------------------------------------------
// File: gpiflongxfr.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;
// when set cpu is out of the data path
BOOL endp_auto_mode_enabled = 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 = 0x02; // REVCTL.1=1; use "dynamic OUT automaticity"
// An explaination of what all happens when REVCTL.1=1
// - dynamic out automaticity
// - enabled via REVCTL.1=1 (DYN_OUT)
// - means block auto arming of OUT endp's when turning on "auto mode"
// - allows cpu intervention when switching between AUTO and MANUAL modes
// - without having to reset the fifo
// - this feature is useful for applications that edit packet data...
// - REVCTL.1=0 not recommended for applications that "touch" data...
// 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
// (1)...OUTPKTEND w/skip=1 (N times) when REVCTL.0=1 (ENH_PKT)
// ...true even when AUTOOUT=1 for REVCTL.0=1
// 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; //
// (2)...EPxBCL w/skip=1 (N times) when REVCTL.0=0 (ENH_PKT)
SYNCDELAY; //
EP2BCL = 0x80; // arm first buffer
SYNCDELAY; //
EP2BCL = 0x80; // arm second buffer
SYNCDELAY; //
EP2BCL = 0x80; // arm third buffer
SYNCDELAY; //
EP2BCL = 0x80; // arm fourth buffer
SYNCDELAY; //
// Note: had we choosen to use AUTOOUT=1 initially, then...
// (1)...when REVCTL.1=0, the core must see MANUAL-AUTO switch of AUTO bit
// ...to properly "arm" OUT buffers...
//
// SYNCDELAY;
// EP2FIFOCFG = 0x00; // AUTOOUT=0 (manual OUT mode)
// SYNCDELAY;
// EP6FIFOCFG = 0x04;
// then,
// SYNCDELAY;
// EP2FIFOCFG = 0x10; // AUTOOUT=1 (auto OUT mode)
// SYNCDELAY;
// EP6FIFOCFG = 0x04;
//
// ...this might not be obvious because the default is AUTOOUT=0
// ...power static back to back firmware downloads may be subject to
// ...the above scheme.when the application's last status was AUTOOUT=1
//
// (2)...when REVCTL.1=1, core blocks auto arming of OUT endp's
// ...see above EPxBCL/OUTPKTEND sequence(s)
// ...sequence is as follows:
// ...(a) REVCTL.1=1
// ...(b) FIFORESET (as above)
// ...(c) EPxBCL/OUTPKTEND (as above)
// ...(d) AUTOOUT=1
// 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)
// EA=1 is handled in "fw.c"
// 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_IN = 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...
if( endp_auto_mode_enabled )
{
// AUTOOUT=1, core handles transfers
// ...cpu is not in the data path...
ledX_rdvar = LED1_ON; // visual
}
else
{
// AUTOOUT=0, cpu handles transfers
// 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)
// (1)...OUTPKTEND w/skip=0 when REVCTL.0=1 (ENH_PKT)
// SYNCDELAY;
// OUTPKTEND = 0x02; // endp#; w/skip=0
//
// ...additionally, the cpu may edit the packet data:
// - skip (OUTPKTEND = 0x82;)
// - modify data (via EPxFIFOBUF[i] and packet length (via EPxBCH/L)
// (2)...EPxBCL w/skip=0 when REVCTL.0=0 (ENH_PKT)
// SYNCDELAY;
// EP2BCL = 0x00; // w/skip=0
//
// ...additionally, the cpu may:
// - skip (EP2BCL = 0x80;)
// - modify data (via EPxFIFOBUF[i])
// - however, cpu can't modify the packet length
// REVCTL.0=0... so,
SYNCDELAY;
EP2BCL = 0x00; // w/skip=0
ledX_rdvar = LED0_ON; // visual
}
else
{
// host is "not" sending data...
}
}
// The "long transfer" is being handled by GPIF and the core via AUTOOUT mode
// ...for this example:
// - The FIFOs are being set to AUTOOUT mode for EP2 via vend_cmnd
// - The GPIF Transaction Count is set to 0xFFFFFFFF; via vend_cmnd
// - The GPIF FIFOWr Waveform is being launched via vend_cmnd
// - The GPIF Transaction Count is being read via vend_cmnd
// NOTE: The firmware in TD_Poll( ); isn't actually handling the data
// ...transfers specifically... this is here to just show where
// ...the natural data flow path resides... etc.
// Handle IN data...
// NOTE: We aren't doing IN data transfers for this example...
// 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...
// NOTE: we're using EPxGPIFTCH/L registers here to show backwards
// ...compatibility. New implementations should use the new
// ...unified GPIFTCB3, GPIFTCB2, GPIFTCB1, GPIFTCB0 registers
// ...these registers maintain a live update which the cpu can read
// ...at anytime to determine the status of a long transfer...
// setup GPIF transaction count
SYNCDELAY;
EP6GPIFTCH = 0x02;
SYNCDELAY;
EP6GPIFTCL = 0x00;
// trigger FIFO read transaction(s), using SFR
// R/W=1, EP[1:0]=FIFO_EpNum for EPx read(s)
SYNCDELAY;
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...
}
if( endp_auto_mode_enabled )
{
// AUTOOUT=1, core handles transfers
// ...cpu is not in the data path...
// ...however, cpu is responsible for committing "short packets"
xFIFOTC_IN = ( ( EP6FIFOBCH << 8 ) + EP6FIFOBCL );
if( xFIFOTC_IN < enum_pkt_size )
{
// handle short pkt. from peripheral
SYNCDELAY; //
INPKTEND = 0x06; // w/skip=0;.commit however many bytes in pkt.
SYNCDELAY; //
}
else
{
// core commits packet via EPxAUTOINLENH/L registers
}
}
else
{
// 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"
}
// NOTE: the cpu can optionally:
// ...- modify data (via EPxFIFOBUF[i] and packet length (via EPxBCH/L)
// ...
// ...when REVCTL.0=1
// ...- skip current packet;
// ...INPKTEND = 0x86; // w/skip=1, skip current packet
//
}
}
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;
EP0BCH = 0;
EP0BCL = 1;
return( TRUE ); // Handled by user code
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -