f34x_usb_isr.c
来自「8051试验程序 基础教材」· C语言 代码 · 共 861 行 · 第 1/2 页
C
861 行
//-----------------------------------------------------------------------------
// F34x_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: 34X000007
// Target: C8051F34x
// Command Line: See Readme.txt
// Project Name: F34x_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 <ioC8051F340.h>
#include "F34x_USB_Registers.h"
#include "F34x_USB_Structs.h"
#include "F34x_USB_Main.h"
#include "F34x_USB_Descriptors.h"
#include "F34x_USB_Config.h"
#include "F34x_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 & 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 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
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?