f326_usb_isr.c

来自「8051试验程序 基础教材」· C语言 代码 · 共 851 行 · 第 1/2 页

C
851
字号
//-----------------------------------------------------------------------------
// F326_USB_ISR.c
//-----------------------------------------------------------------------------
// Copyright 2005 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// Source file for USB firmware. Includes the following routines:
//
// - USB_ISR(): Top-level USB interrupt handler. All USB handler
//    routines are called from here.
// - Endpoint0(): Endpoint0 interrupt handler.
// - BulkOrInterruptOut(): Bulk or Interrupt OUT interrupt
//    handler.
// - BulkOrInterruptIn(): Places DataToWrite on the IN FIFO.
// - USBReset (): USB Reset event handler.
// - State_Machine(): USB state machine
// - Receive_Setup(): Determine whether a read or write request
//    been received and initializes variables accordingly.
// - Receive_File(): Receives and saves data
// - Page_Erase(): Erases a page of FLASH
// - Page_Write(): Writes to a page of FLASH
//
//
// How To Test:    See Readme.txt
//
//
// FID:            326000007
// Target:         C8051F326
// Command Line:   See Readme.txt
// Project Name:   F326_USB_Bulk
//
//
// Release 1.0
//    -Initial Revision (DM)
//    -18 DEC 2005
//

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------

#include <ioC8051F326.h>                 // SFR declarations
#include "F326_USB_Registers.h"
#include "F326_USB_Structs.h"
#include "F326_USB_Main.h"
#include "F326_USB_Descriptors.h"
#include "F326_USB_Config.h"
#include "F326_USB_Request.h"

//-----------------------------------------------------------------------------
// Extern Global Variables
//-----------------------------------------------------------------------------

extern DEVICE_STATUS  gDeviceStatus;
extern EP0_COMMAND    gEp0Command;
extern EP_STATUS      gEp0Status;
extern EP_STATUS      gEp1InStatus;
extern EP_STATUS      gEp2OutStatus;

//-----------------------------------------------------------------------------
// Global Constants
//-----------------------------------------------------------------------------

//  Constants Definitions
#define NUM_STG_PAGES   20             // Total number of flash pages to
                                       // be used for file storage
#define MAX_BLOCK_SIZE  64             // Use the maximum block size of 64
#define FLASH_PAGE_SIZE 512            // Size of each flash page
#define BLOCKS_PR_PAGE  FLASH_PAGE_SIZE/MAX_BLOCK_SIZE
#define MAX_NUM_BLOCKS  BLOCKS_PR_PAGE*NUM_STG_PAGES

// UINT type definition
#ifndef _UINT_DEF_
#define _UINT_DEF_
typedef unsigned int UINT;
#endif                                 // _UINT_DEF_

// BYTE type definition
#ifndef _BYTE_DEF_
#define _BYTE_DEF_
typedef unsigned char BYTE;
#endif                                 // _BYTE_DEF_

//  Message Types
#define READ_MSG    0x00    // Message types for communication with host
#define WRITE_MSG   0x01
#define SIZE_MSG    0x02

//  Machine States
#define ST_WAIT_DEV 0x01    // Wait for application to open a device instance
#define ST_IDLE_DEV 0x02    // Device is open, wait for Setup Message from host
#define ST_RX_SETUP 0x04    // Received Setup Message, decode and wait for data
#define ST_RX_FILE  0x08    // Receive file data from host
#define ST_TX_FILE  0x10    // Transmit file data to host
#define ST_TX_ACK   0x20    // Transmit ACK 0xFF to host after every 8 packets
#define ST_ERROR    0x80    // Error state


typedef struct {            //  Structure definition of a block of data
    BYTE Piece[MAX_BLOCK_SIZE];
}   BLOCK;

typedef struct {            //  Structure definition of a flash memory page
    BYTE FlashPage[FLASH_PAGE_SIZE];
}   PAGE;

__xdata   BLOCK   TempStorage[BLOCKS_PR_PAGE];    // Temporary storage of between
                                                // flash writes

const __code    BYTE    Pg0 @    0x1400;
const __code    BYTE    Pg1 @    0x1600;
const __code    BYTE    Pg2 @    0x1800;
const __code    BYTE    Pg3 @    0x1A00;
const __code    BYTE    Pg4 @    0x1C00;
const __code    BYTE    Pg5 @    0x1E00;
const __code    BYTE    Pg6 @    0x2000;
const __code    BYTE    Pg7 @    0x2200;
const __code    BYTE    Pg8 @    0x2400;
const __code    BYTE    Pg9 @    0x2600;

const __code    BYTE    Pg10    @    0x2800;
const __code    BYTE    Pg11    @    0x2A00;
const __code    BYTE    Pg12    @    0x2C00;
const __code    BYTE    Pg13    @    0x2E00;
const __code    BYTE    Pg14    @    0x3000;
const __code    BYTE    Pg15    @    0x3200;
const __code    BYTE    Pg16    @    0x3400;
const __code    BYTE    Pg17    @    0x3600;
const __code    BYTE    Pg18    @    0x3800;
const __code    BYTE    Pg19    @    0x3A00;

__idata   BYTE const __code * PageIndices[20] =
                                      {&Pg0,
                                        &Pg1,
                                        &Pg2,
                                        &Pg3,
                                        &Pg4,
                                        &Pg5,
                                        &Pg6,
                                        &Pg7,
                                        &Pg8,
                                        &Pg9,
                                        &Pg10,
                                        &Pg11,
                                        &Pg12,
                                        &Pg13,
                                        &Pg14,
				        &Pg15,
                                        &Pg16,
                                        &Pg17,
                                        &Pg18,
                                        &Pg19};

__data    UINT    BytesToWrite;   //  Total number of bytes to write to the host
__data    UINT    BytesToRead;    //  Total number of bytes to read from host
__data    BYTE    Buffer[3];      //  Buffer for Setup messages
__data    BYTE    NumBlocks;      //  Number of Blocks for this transfer
__data    BYTE    M_State;        //  Current Machine State
__data    BYTE    BlockIndex;     //  Index of Current Block in Page
__data    BYTE    PageIndex;      //  Index of Current Page in File
__data    BYTE    BlocksRead;     //  Total Number of Blocks Read
__data    BYTE    BlocksWrote;    //  Total Number of Blocks Written
__idata    BYTE   const __code * ReadIndex;

// __code const   BYTE    Serial1[0x0A] = {0x0A,0x03,'A',0,'B',0,'C',0,'D',0};
// Serial Number Defintion

const __code    BYTE    LengthFile[3]   @    0x1200;
//  {Length(Low Byte), Length(High Byte), Number of Blocks}

#define Led1 P2_bit.P22 // LED='1' means ON
#define Led2 P2_bit.P23 // These blink to indicate data transmission

//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------

void    State_Machine(void);
void    Receive_Setup(void);
void    Receive_File(void);

//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// USB_ISR
//-----------------------------------------------------------------------------
//
//
// This is the top level USB ISR. All endpoint interrupt/request
// handlers are called from this function.
//
// Handler routines for any configured interrupts should be
// added in the appropriate endpoint handler call slots.
//
//-----------------------------------------------------------------------------
#pragma vector=0x43
__interrupt void USB_ISR ()
{
   BYTE bCommonInt, bInInt, bOutInt;

   // Read interrupt registers
   UREAD_BYTE(CMINT, bCommonInt);
   UREAD_BYTE(IN1INT, bInInt);
   UREAD_BYTE(OUT1INT, bOutInt);

   // Check for reset interrupt
   if (bCommonInt & rbRSTINT)
   {
      // Call reset handler
     USBReset();
      M_State = ST_WAIT_DEV;
   }

   // Check for Endpoint0 interrupt
   if (bInInt & rbEP0)
   {
      // Call Endpoint0 handler
      Endpoint0();
   }

   // Endpoint1 IN
   if (bInInt & rbIN1)
   {
         if (M_State == ST_RX_FILE)    // Ack Transmit complete, go to RX state
         {
           M_State = (ST_TX_ACK);
         }
         if (M_State == ST_TX_FILE)    // File block transmit complete,
		                               // go to TX state
         {
           // Go to Idle when done
           M_State = (BlocksWrote == NumBlocks) ? ST_IDLE_DEV : ST_TX_FILE;
         }
   }

   // Endpoint2 OUT
   if (bOutInt & rbOUT1)
   {
      // Call Endpoint2 OUT handler
      BulkOrInterruptOut(&gEp2OutStatus);

      M_State = (M_State == ST_IDLE_DEV) ? ST_RX_SETUP : ST_RX_FILE;
   }

   State_Machine();
}

//-----------------------------------------------------------------------------
// Support Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Endpoint0
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   : None
//
//-----------------------------------------------------------------------------
void Endpoint0 ()
{
   BYTE bTemp = 0;
   BYTE bCsr1, uTxBytes;

   UWRITE_BYTE(INDEX, 0);                 // Target ep0
   UREAD_BYTE(E0CSR, bCsr1);

   // Handle Setup End
   if (bCsr1 & rbSUEND)                   // Check for setup end
   {                                      // Indicate setup end serviced
      UWRITE_BYTE(E0CSR, rbSSUEND);
      gEp0Status.bEpState = EP_IDLE;      // ep0 state to idle
      M_State = ST_IDLE_DEV;              // ported from usb_file.c
   }

   // Handle sent stall
   if (bCsr1 & rbSTSTL)                   // If last state requested a stall
   {                                      // Clear Sent Stall bit (STSTL)
      UWRITE_BYTE(E0CSR, 0);
      gEp0Status.bEpState = EP_IDLE;      // ep0 state to idle
      M_State = ST_IDLE_DEV;              // ported from usb_file.c
   }

   // Handle incoming packet
   if (bCsr1 & rbOPRDY)
   {
      // Read the 8-byte command from Endpoint0 FIFO
      FIFORead(0, 8, (BYTE*)&gEp0Command);

/*      // Byte-swap the wIndex field
      bTemp = gEp0Command.wIndex.c[1];
      gEp0Command.wIndex.c[1] = gEp0Command.wIndex.c[0];
      gEp0Command.wIndex.c[0] = bTemp;

      // Byte-swap the wValue field
      bTemp = gEp0Command.wValue.c[1];
      gEp0Command.wValue.c[1] = gEp0Command.wValue.c[0];
      gEp0Command.wValue.c[0] = bTemp;

      // Byte-swap the wLength field
      bTemp = gEp0Command.wLength.c[1];
      gEp0Command.wLength.c[1] = gEp0Command.wLength.c[0];
      gEp0Command.wLength.c[0] = bTemp;*/

      // Decode received command
      switch (gEp0Command.bmRequestType & CMD_MASK_COMMON)
      {
         case  CMD_STD_DEV_OUT:           // Standard device requests
            // Decode standard OUT request
            switch (gEp0Command.bRequest)
            {
               case SET_ADDRESS:
                  SetAddressRequest();
                  break;
               case SET_FEATURE:
                  SetFeatureRequest();
                  break;
               case CLEAR_FEATURE:
                  ClearFeatureRequest();
                  break;
               case SET_CONFIGURATION:
                  SetConfigurationRequest();
                  break;
               case SET_INTERFACE:
                  SetInterfaceRequest();
                  break;
               // All other OUT requests not supported
               case SET_DESCRIPTOR:
               default:
                  gEp0Status.bEpState = EP_ERROR;
                  break;
            }
            break;

         // Decode standard IN request
         case CMD_STD_DEV_IN:
            switch (gEp0Command.bRequest)
            {
               case GET_STATUS:
                  GetStatusRequest();
                  break;
               case GET_DESCRIPTOR:
                  GetDescriptorRequest();
                  break;
               case GET_CONFIGURATION:
                  GetConfigurationRequest();
                  break;
               case GET_INTERFACE:
                  GetInterfaceRequest();
                  break;
               // All other IN requests not supported
               case SYNCH_FRAME:
               default:
                  gEp0Status.bEpState = EP_ERROR;
                  break;
            }
            break;
         // All other requests not supported
         default:
            gEp0Status.bEpState = EP_ERROR;
      }

      // Write E0CSR according to the result of the serviced out packet
      bTemp = rbSOPRDY;
      if (gEp0Status.bEpState == EP_ERROR)
      {
         bTemp |= rbSDSTL;                // Error condition handled
                                          // with STALL
         gEp0Status.bEpState = EP_IDLE;   // Reset state to idle
      }

      UWRITE_BYTE(E0CSR, bTemp);
   }

   bTemp = 0;                             // Reset temporary variable

   // If state is transmit, call transmit routine
   if (gEp0Status.bEpState == EP_TX)
   {
      // Check the number of bytes ready for transmit
      // If less than the maximum packet size, packet will
      // not be of the maximum size
      if (gEp0Status.uNumBytes <= EP0_MAXP)
      {
         uTxBytes = gEp0Status.uNumBytes;
         gEp0Status.uNumBytes = 0;        // update byte counter
         bTemp |= rbDATAEND;              // This will be the last
                                          // packet for this transfer
         gEp0Status.bEpState = EP_IDLE;   // Reset endpoint state
      }

      // Otherwise, transmit maximum-length packet
      else
      {
         uTxBytes = EP0_MAXP;
         gEp0Status.uNumBytes -= EP0_MAXP;// update byte counter
      }

      // Load FIFO
      FIFOWrite(0, uTxBytes, (BYTE const __code *)gEp0Status.pData);

      // Update data pointer
      gEp0Status.pData = (BYTE const __code *)gEp0Status.pData + uTxBytes;

      // Update Endpoint0 Control/Status register
      bTemp |= rbINPRDY;                  // Always transmit a packet
                                          // when this routine is called
                                          // (may be zero-length)

      UWRITE_BYTE(E0CSR, bTemp);          // Write to Endpoint0 Control/Status
   }

}

//-----------------------------------------------------------------------------
// BulkOrInterruptOut
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters   :
// 1) PEP_STATUS pEpOutStatus
//

⌨️ 快捷键说明

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