📄 f32x_usb_isr.c
字号:
//-----------------------------------------------------------------------------
// F32x_USB_USBISR.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: 32X000013
// Target: C8051F32x
// Tool chain: Keil C51 7.50 / Keil EVAL C51
// Silicon Laboratories IDE version 2.6
// Command Line: See Readme.txt
// Project Name: F32x_USB_Bulk
//
//
// Release 1.3
// -All changes by GP
// -21 NOV 2005
// -Changed revision number to match project revision
// No content changes to this file
// -Modified file to fit new formatting guidelines
// -Changed file name from usb_isr.c
//
//
// Release 1.2
// -Initial Revision (JS/CS/JM)
// -XX OCT 2003
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "c8051F320.h"
#include "F32x_USB_Registers.h"
#include "F32x_USB_Structs.h"
#include "F32x_USB_Main.h"
#include "F32x_USB_Descriptors.h"
#include "F32x_USB_Config.h"
#include "F32x_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
code BYTE Pg0 _at_ 0x1400;
code BYTE Pg1 _at_ 0x1600;
code BYTE Pg2 _at_ 0x1800;
code BYTE Pg3 _at_ 0x1A00;
code BYTE Pg4 _at_ 0x1C00;
code BYTE Pg5 _at_ 0x1E00;
code BYTE Pg6 _at_ 0x2000;
code BYTE Pg7 _at_ 0x2200;
code BYTE Pg8 _at_ 0x2400;
code BYTE Pg9 _at_ 0x2600;
code BYTE Pg10 _at_ 0x2800;
code BYTE Pg11 _at_ 0x2A00;
code BYTE Pg12 _at_ 0x2C00;
code BYTE Pg13 _at_ 0x2E00;
code BYTE Pg14 _at_ 0x3000;
code BYTE Pg15 _at_ 0x3200;
code BYTE Pg16 _at_ 0x3400;
code BYTE Pg17 _at_ 0x3600;
code BYTE Pg18 _at_ 0x3800;
code BYTE Pg19 _at_ 0x3A00;
idata BYTE* 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
data BYTE* ReadIndex;
// code const BYTE Serial1[0x0A] = {0x0A,0x03,'A',0,'B',0,'C',0,'D',0};
// Serial Number Defintion
code BYTE LengthFile[3] _at_ 0x1200;
// {Length(Low Byte), Length(High Byte), Number of Blocks}
sbit Led1 = P2^2; // LED='1' means ON
sbit Led2 = P2^3; // 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.
//
//-----------------------------------------------------------------------------
void USB_ISR () interrupt 8
{
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 & rbOUT2)
{
// 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*)gEp0Status.pData);
// Update data pointer
gEp0Status.pData = (BYTE*)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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -