⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 periph.c

📁 Cy68013的应用——USB2.0接口转IDE、CF卡接口
💻 C
📖 第 1 页 / 共 2 页
字号:
#pragma NOIV               // Do not generate interrupt vectors
//-----------------------------------------------------------------------------
//   File:      periph.c
//   Contents:   Hooks required to implement USB peripheral function.
//
//   Copyright (c) 1997 AnchorChips, Inc. All rights reserved
//
// $Workfile: periph.c $
// $Date: 7/23/02 5:20p $
// $Revision: 24 $
//-----------------------------------------------------------------------------
#include "fx2.h"
#include "fx2regs.h"
#include "gpif.h"
#include "atapi.h"
#include "globals.h"

//-----------------------------------------------------------------------------
// Task Dispatcher hooks
//   The following hooks are called by the task dispatcher.
//-----------------------------------------------------------------------------

void TD_Init(void)             // Called once at startup
{
   // set our first_time flag.  This is set to the timer start bit.  The timer start
   // bit will only be set if we have already been here before.
   bFirstTime = !TR0;
   bSwitchToHighSpeed = 0;
   if (bFirstTime)
	   bHighSpeedEnabled = 0;

   // Enable both autoptrs.  ONLY use AUTOPTR2 for writing small amounts of data to EP8buf.  NEVER load
   // AUTOPTR1H again.
   AUTOPTRSETUP = 0x7;
   AUTOPTRH2 = MSB(EP8FIFOBUF);

   // relocate descriptor data to halfKBuffer.  The bus powered version of us uses a HID descriptor set.
   // Only do the copy the first time we run because we modify the descriptor version in HalfKBuffer.
   // We know it's the first time if the timer isn't running yet.
   if (bFirstTime)
   {        
      #if BUS_POWERED
      mymemmovexx(halfKBuffer, (char xdata *) &HIDDeviceDscr, (WORD)&HIDDeviceDscrEndOffset);
      CT1 = 2;    // Disable high speed state machine
      #else
      mymemmovexx(halfKBuffer, (char xdata *) &DeviceDscr, (WORD)&DscrEndOffset);
      #endif
      
   }

   // init state/reset variables
   currentState = UNCONFIGURED;

   phaseErrorState = 0;

   deviceCount = 0;

   LunBits[0] = LunBits[1] = ActiveLunBits = 0;

   initUSB();                 // configure output ports and endpoint params
   mymemmovexx(&GPIF_WAVE_DATA, (BYTE xdata *) WaveDataPioUDMA, 128);          // load wave forms in memory

   // Set up timer 0 to act as the timeout counter.
   // The default setting for the debugger uses timer 1
   TMOD = 0x21;      // Timer 1 set up for debugger (just in case).  Timer 0 is 16 bit counter
   CKCON = 0x10;     // Same setting as debugger for T1, T0 is CPU/12 (4Mhz input)
   ET0 = 1;          // Enable timer interrupt (needed to do software count of 61hz overflows)
   TR0 = 1;
}


char const code usbcString[] = "USBC";
void TD_Poll(void)             // Called repeatedly while the device is idle
{
   WORD    count = 0;

   // check EP2 EMPTY(busy) bit in EP2468STAT (SFR), core set's this bit when FIFO is empty
   if(!(EP2CS & bmEPEMPTY))   
      { 
      // Check for "USBC"
      if (checkCBW() == USBS_PASSED)
         // Good packet, forward to the device.
         processCBW();  
      else
         {
         // if we receive an invalid CBW, STALL both bulk endpoints and remain that
         // way until reset recovery (MSC BOT 6.6.1)
         EP2CS = EP8CS = bmEPSTALL;
         phaseErrorState = 1;
         }
      }

   if (bSwitchToHighSpeed)
      {
      EZUSB_Delay(2000);

      // enable high-speed state machine
      CT1 = 0;
      bSwitchToHighSpeed = 0;
	  bHighSpeedEnabled = 1;

      // Switch to the new (mass storage) descriptor set
      mymemmovexx(halfKBuffer, (char xdata *) &DeviceDscr, (WORD)&DscrEndOffset);

      // disconnect and reconnect so we attach at high-speed if this is
      // a high-speed host
      EZUSB_Discon(TRUE);
      USBCS &=~bmDISCON;

      // since the host has sent us a set configuration, we know we are plugged
      // into a high power port.  we can now draw more than 100mA, so crank up
      // the CPU clock and GPIF interface
      IFCONFIG = IFCONFIG_DEFAULT;
      CPUCS = bmCLKSPD1 | bmCLKINV; // set clock to 48MHz.  clock output disabled. inverted.
      }

   checkForMedia(0);
}


//-----------------------------------------------------------------------------
// Support functions for specific device
//-----------------------------------------------------------------------------

void initUSB(void)
{
   #if REVC_4611_BOARD
   PORTACFG = 0;
   #else
   PORTACFG = 0x01;       // set up PORTA for port I/O  
   #endif

   // Configure our outputs to drive ONLY if the ATA_ENABLE pin is active
   #if ATA_ENABLE_PIN
      {
      WAKEUPCS = 0x45;
      if (!(WAKEUPCS & 0x40))
         {
         OUTATAPI = ATAPI_IDLE_VALUE;  // includes RESET line PA.0
         OEA = PORTA_OE;            // PORTA is all output except PA.0(INTRQ) AND PA.6(DASP#)
         }
      }
   #else
      {
      OUTATAPI = ATAPI_IDLE_VALUE;  // includes RESET line PA.0
      OEA = PORTA_OE;            // PORTA is all output except PA.0(INTRQ) AND PA.6(DASP#)
      }
   #endif

   // Make Interrupt 0 level triggered
   IT0 = 0;

// if we are trying to operate in bus powered mode, we want to defer setting the 
// CPU clock speed or configuring the GPIF until we have been configured.  This
// is to keep our current under 100mA.
#if !BUS_POWERED
   IFCONFIG = IFCONFIG_DEFAULT;
   CPUCS = bmCLKSPD1 | bmCLKINV; // set clock to 48MHz.  clock output disabled. inverted.
#endif

   FIFOPINPOLAR = 0x00;    // ff pin is active low

   PINFLAGSAB = 0x00;    // FLAGA PF for FIFO selected by FIFOADR[1..0]
   PINFLAGSCD = 0x00;    // FLAGB FF for FIFO selected by FIFOADR[1..0]

   // GPIF and CTL configuration
   GPIFCTLCFG = 0x00;   // 
   GPIFIDLECTL = 0x77;  // x111x111 - CTL3 not enabled
                        // ||||||||_CTL0 = 1 during idle
                        // |||||||__CTL1 = 1 during idle
                        // ||||||___CTL2 = 1 during idle
                        // ||||_____CTL0 output enable
                        // |||______CTL1 output enable
                        // ||_______CTL2 output enable
                        // 
   GPIFIDLECS = 0;      // tristate data bus during idle interval
   GPIFWFSELECT = (2 << 6) | (3 << 4) | (0 << 2) | (1);    // Single write is 2, Single read is 3, write is 0, Read is waveform 1 

   // Endpoint initialization
   EP2CFG = 0xA0;           // ep2 is valid BULK OUT 512 quad buffered
   EP2FIFOCFG = 0x05;       // WORDWIDE=1M MANUAL
   EP2FIFOPFH = 0x00;       // PF=0 when BC > PF -> Decis=0 (1 byte in FIFO)
   EP2FIFOPFL = 0x00;       // PF and BC refer to the current pkt -> PKTSTAT=0
   EP2GPIFPFSTOP = 0;       // Do not stop on PF

   EP8CFG = 0xE0;          // ep8 is valid BULK IN 512 double buffered
   EP8FIFOCFG = bmZEROLENIN | bmWORDWIDE;      // set EP8:  0x05=MANUAL, 0x0D=AUTOIN

   // mark all unused endpoints invalid - setting each reg to 0x22 instead of just clearing
   // the valid bit to save code space.  0x22 basically sets all of these endpoints to 
   // not valid, bulk, double 512 buffered.
   EP1OUTCFG = EP1INCFG = EP4CFG = EP6CFG = 0x22;

   // disbable Auto Arm
   REVCTL = bmNOAUTOARM;

   // arm the OUT endpoint.  By default OUT endpoints come up unarmed.
   ResetAndArmEp2();

   // reset the EP8 FIFO.  If we are here as the result of a USB reset or MSC
   // Reset Recovery, EP8 may need to be cleaned up.
   FIFORESET = 0x08;

}



// Stalls EP2OUT endpoint.
void stallEP2OUT()
{
   // Check to see if stall is needed.  If it is, STALL the endpoint.
   // After we have set the STALL, make sure we didn't get the last packet while we were STALLing.
   WORD x;

   if (EP2468STAT & bmEP2EMPTY)
      x = 0;
   else
      x = EP2FIFOBCL + (EP2FIFOBCH << 8) + EP2BC;

//   if (dataTransferLen > ((x + 1) & 0xfffe))     // Round up to allow for odd xfer lengths
   if (dataTransferLen > x)     

   {
      EP2CS |= bmEPSTALL;

      EZUSB_Delay(100);

      if (EP2CS & bmEPSTALL)
         x=1234;

      // If the host has already cleared the STALL, the EP will be empty here, but we will drop safely through the if()
      if (EP2468STAT & bmEP2EMPTY)
         x = 0;
      else
         x = EP2FIFOBCL + (EP2FIFOBCH << 8) + EP2BC;
   
      if (dataTransferLen > x)     
         {
         ResetAndArmEp2();    // Stall no longer needed
         EP2CS = 0;           // Clear stall bit
         }
   }
}   

// This function pulls common information out of the CBW
void processCBWHeader()
{
   currentState = RECEIVED_CBW;     // This will prevent us from processing CBWs in the ISR.

   // Save the tag for use in the response
   cbwTagLow = *((WORD volatile xdata*)(EP2FIFOBUF+CBW_TAG));
   cbwTagHi =  *((WORD volatile xdata*)(EP2FIFOBUF+CBW_TAG+2));

   // Get the length (convert from little endian)
   *(((BYTE *) &dataTransferLen)+3) = (EP2FIFOBUF+CBW_DATA_TRANSFER_LEN_LSB)[0];  // "Residue"
   *(((BYTE *) &dataTransferLen)+2) = (EP2FIFOBUF+CBW_DATA_TRANSFER_LEN_LSB)[1];  // "Residue"
   *(((BYTE *) &dataTransferLen)+1) = (EP2FIFOBUF+CBW_DATA_TRANSFER_LEN_LSB)[2];  // "Residue"
   *(((BYTE *) &dataTransferLen)+0) = (EP2FIFOBUF+CBW_DATA_TRANSFER_LEN_LSB)[3];  // "Residue"

   directionIn = EP2FIFOBUF[CBW_FLAGS] >> 7;
}

void processCBW()
{
   BYTE CbwLun;

   processCBWHeader();

   CbwLun = EP2FIFOBUF[CBW_LUN];

   if (!(CbwLun == currentLunNum))
   {
      // Before we change waveforms, tell the ATA interface that we're going to talk to the master.
      // This allows us to use some of the ATA signals for the CF while the slave device ignores them.
      // This works well as long as we don't write to a register that affects both devices, like
      // the device select register, or the SRST bit in the control register.
      mymemmove((BYTE *)&ActiveLunConfigData,(BYTE *)&DeviceConfigData[CbwLun], sizeof(DEVICE_CONFIG_DATA));
      ActiveLunBits = LunBits[CbwLun];
      currentLunNum = CbwLun;

      if (bCompactFlash)
      {
      // The CF waveforms are stored within the PIO0 waves in lines 2 and 3.
      // This makes their offset 4 + 8 for each line = 4+16.
      // The transfer length is 8 (one full line) + 4 (the active part of the next line).
         mymemmovexx(&GPIF_WAVE_DATA, (BYTE xdata *) WaveDataPioUDMA+16+4, 8 + 4);
         mymemmovexx(&(GPIF_WAVE_DATA) + 32, (BYTE xdata *) WaveDataPioUDMA+32+16+4, 8 + 4);
         EP2FIFOCFG = EP8FIFOCFG = bmZEROLENIN;      // CF is byte-wide
      }
      else
      {
         EP2FIFOCFG = EP8FIFOCFG = bmZEROLENIN | bmWORDWIDE;      // ATA/ATAPI is word-wide

         // We've switched devices.  Do we need to switch PIO modes too?
         // if (!(DeviceConfigData[0].MaxPIO == DeviceConfigData[1].MaxPIO))
         // ALWAYS switch.  It's easier than special casing startup.
         {
            // switch to PIO4
            if(ActiveLunConfigData.MaxPIO & PIO4) 
            {
               mymemmovexx(&GPIF_WAVE_DATA, (BYTE xdata *) WaveDataPioUDMA+4, 8 + 4);
               mymemmovexx(&(GPIF_WAVE_DATA) + 32, (BYTE xdata *) WaveDataPioUDMA+32+4, 8 + 4);
            }
            // switch to PIO3
            else if(ActiveLunConfigData.MaxPIO & PIO3) 
            {
               mymemmovexx(&GPIF_WAVE_DATA, (BYTE xdata *) WaveDataPioUDMA+4, 8 + 4);
               mymemmovexx(&(GPIF_WAVE_DATA) + 32, (BYTE xdata *) WaveDataPioUDMA+32+4, 8 + 4);
               ((BYTE xdata *)&GPIF_WAVE_DATA)[0] = 0x6;
               ((BYTE xdata *)&GPIF_WAVE_DATA)[32] = 0x6;
            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -