📄 usb_isr.c
字号:
//-----------------------------------------------------------------------------
// F32x_USB_ISR.c
//-----------------------------------------------------------------------------
// Copyright 2005 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// Source file for USB firmware. Includes top level ISR with Setup,
// and Endpoint data handlers. Also includes routine for USB suspend,
// reset, and procedural stall.
//
//
// How To Test: See Readme.txt
//
//
// FID: 32X000023
// 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_Interrupt
//
//
// Release 1.3
// -All changes by GP
// -22 NOV 2005
// -Changed revision number to match project revision
// -Modified file to fit new formatting guidelines
// -Changed file name from USB_ISR.c
// -Removed extraneous code that was commented out
// -Added USB Suspend code
//
// Release 1.0
// -Initial Revision (DM)
// -08 NOV 2002
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "c8051F320.h"#include "USB_Register.h"
#include "USB_Main.h"
#include "USB_Descriptor.h"
//-----------------------------------------------------------------------------
// Global Externs
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
unsigned char * usb_dptr; /* pointer to first empty location in buffer (Rx) or to the first char to transmit (Tx) */
unsigned char usb_ep0_dcntT; /* data count to transmit */
unsigned char usb_ep0_dcntR; /* data count to receive */
unsigned char usb_ep2_dcntT; /* data count to transmit */
unsigned char usb_ep2_dcntR; /* data count to receive */
BYTE USB_State; // Holds the current USB State
// def. in F32x_USB_Main.h
setup_buffer Setup; // Buffer for current device request
unsigned int DataSize; // Size of data to return
unsigned int DataSent; // Amount of data sent so far
BYTE* DataPtr; // Pointer to data to return
// Holds the status for each endpoint
BYTE Ep_Status[5] = {EP_IDLE, EP_IDLE, EP_IDLE, EP_IDLE, EP_IDLE};
BYTE receive_ep0;
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Usb_ISR
//-----------------------------------------------------------------------------
//
// Called after any USB type interrupt, this handler determines which type
// of interrupt occurred, and calls the specific routine to handle it.
//
//-----------------------------------------------------------------------------
void Usb_ISR(void) interrupt 8 // Top-level USB ISR{
BYTE bCommon, bIn, bOut;
POLL_READ_BYTE(CMINT, bCommon); // Read all interrupt registers POLL_READ_BYTE(IN1INT, bIn); // this read also clears the register
POLL_READ_BYTE(OUT1INT, bOut);
{
if (bCommon & rbRSUINT) // Handle Resume interrupt
{
Usb_Resume();
} if (bCommon & rbRSTINT) // Handle Reset interrupt
{
Usb_Reset();
} if (bIn & rbEP0) // Handle Setup packet received
{ // or packet transmitted if Endpoint 0
Handle_Setup(); // is transmit mode
} if (bIn & rbIN2) // Handle In Packet sent, put new data
{ // on endpoint 1 fifo
Handle_In2();
} if (bOut & rbOUT2) // Handle Out packet received, take data
{ // off endpoint 2 fifo
Handle_Out2();
}
if( bIn & rbIN3)
{
Handle_In3();
}
if (bOut & rbOUT3)
{
Handle_Out3();
}
if (bCommon & rbSUSINT) // Handle Suspend interrupt
{
Usb_Suspend();
}
}
}
//-----------------------------------------------------------------------------
// Support Routines for ISR
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Usb_Reset
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// - Set state to default
// - Clear Usb Inhibit bit
//
//-----------------------------------------------------------------------------
void Usb_Reset(void)
{
USB_State = DEV_DEFAULT; // Set device state to default
POLL_WRITE_BYTE(POWER, 0x01); // Clear usb inhibit bit to enable USB
// suspend detection
Ep_Status[0] = EP_IDLE; // Set default Endpoint Status
Ep_Status[1] = EP_HALT;
Ep_Status[2] = EP_HALT;
Ep_Status[3] = EP_HALT;
Ep_Status[4] = EP_HALT;
receive_ep0 = 0;
}
//-----------------------------------------------------------------------------
// Handle_Setup
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// - Decode Incoming Setup requests
// - Load data packets on fifo while in transmit mode
//
//-----------------------------------------------------------------------------
void Handle_Setup(void)
{
BYTE ControlReg,TempReg; // Temporary storage for EP control register
POLL_WRITE_BYTE(INDEX, 0); // Set Index to Endpoint Zero
POLL_READ_BYTE(E0CSR, ControlReg); // Read control register
if (Ep_Status[0] == EP_ADDRESS) // Handle Status Phase of Set Address command
{
POLL_WRITE_BYTE(FADDR, Setup.wValue.c[LSB]);
Ep_Status[0] = EP_IDLE;
}
if (ControlReg & rbSTSTL) // If last packet was a sent stall, reset
{ // STSTL bit and return EP0 to idle state
POLL_WRITE_BYTE(E0CSR, 0);
Ep_Status[0] = EP_IDLE;
return;
}
if (ControlReg & rbSUEND) // If last setup transaction was ended prematurely then set
{
POLL_WRITE_BYTE(E0CSR, rbDATAEND);
POLL_WRITE_BYTE(E0CSR, rbSSUEND); // Serviced Setup End bit and return EP0
Ep_Status[0] = EP_IDLE; // to idle state
}
if (Ep_Status[0] == EP_IDLE) // If Endpoint 0 is in idle mode
{
if (ControlReg & rbOPRDY) // Make sure that EP 0 has an Out Packet ready from host
{ // although if EP0 is idle, this should always be the case
if( receive_ep0 == 0)
{
Fifo_Read(FIFO_EP0, 8, (BYTE *)&Setup);
// Get Setup Packet off of Fifo, it is currently Big-Endian
// Compiler Specific - these next three statements swap the
// bytes of the setup packet words to Big Endian so they
// can be compared to other 16-bit values elsewhere properly
if(Setup.bmRequestType == 0xC0 ) //MYBDM命令
{
command_buffer[0] = Setup.bmRequestType;
command_buffer[1] = Setup.bRequest;
command_buffer[2] = Setup.wValue.c[MSB];
command_buffer[3] = Setup.wValue.c[LSB];
command_buffer[4] = Setup.wIndex.c[MSB];
command_buffer[5] = Setup.wIndex.c[LSB];
command_buffer[6] = Setup.wLength.c[MSB];
command_buffer[7] = Setup.wLength.c[LSB];
DataPtr = command_buffer; // Can have a maximum of 255 strings
if (Ep_Status[0] != EP_STALL)
{
POLL_WRITE_BYTE(E0CSR, rbSOPRDY); // Set Serviced Setup packet, put endpoint in transmit
Ep_Status[0] = EP_TX; // mode and reset Data sent counter
DataSent = 0;
}
}
else if(Setup.bmRequestType == 0x40)
{
command_buffer[0] = Setup.bmRequestType;
command_buffer[1] = Setup.bRequest;
command_buffer[2] = Setup.wValue.c[MSB];
command_buffer[3] = Setup.wValue.c[LSB];
command_buffer[4] = Setup.wIndex.c[MSB];
command_buffer[5] = Setup.wIndex.c[LSB];
command_buffer[6] = Setup.wLength.c[MSB];
command_buffer[7] = Setup.wLength.c[LSB];
usb_ep0_dcntR = command_buffer[6];
if(usb_ep0_dcntR == 0)
{
USB_ep0_rx(); /* the routine will not copy any data, but will launch command execution and status frame transmit */
/* this is cleaner as this code is in one place only */
}
else
{
receive_ep0 = 1;
usb_dptr = command_buffer+6; /* first 5 bytes stored already starting from position 1 */
POLL_WRITE_BYTE(E0CSR, rbSOPRDY); // Set Serviced Setup packet, put endpoint in transmit
DataSent = 0;
}
/* data to follow, set-up pointer */
}
else
{
Setup.wValue.i = Setup.wValue.c[MSB] + 256*Setup.wValue.c[LSB];
Setup.wIndex.i = Setup.wIndex.c[MSB] + 256*Setup.wIndex.c[LSB];
Setup.wLength.i = Setup.wLength.c[MSB] + 256*Setup.wLength.c[LSB];
switch(Setup.bRequest) // Call correct subroutine to handle each kind of
{ // standard request
case GET_STATUS:
Get_Status();
break;
case CLEAR_FEATURE:
Clear_Feature();
break;
case SET_FEATURE:
Set_Feature();
break;
case SET_ADDRESS:
Set_Address();
break;
case GET_DESCRIPTOR:
Get_Descriptor();
break;
case GET_CONFIGURATION:
Get_Configuration();
break;
case SET_CONFIGURATION:
Set_Configuration();
break;
case GET_INTERFACE:
Get_Interface();
break;
case SET_INTERFACE:
Set_Interface();
break;
default:
Force_Stall(); // Send stall to host if invalid request
break;
}
}
}
else // receive_ep0 = 1;
{
USB_ep0_rx();
}
}
}
if (Ep_Status[0] == EP_TX) // See if the endpoint has data to transmit to host
{
if (!(ControlReg & rbINPRDY)) // Make sure you don't overwrite last packet Endpoint 0 transmit mode
{
receive_ep0 = 0;
POLL_READ_BYTE(E0CSR, ControlReg); // Read control register
if ((!(ControlReg & rbSUEND)) || (!(ControlReg & rbOPRDY)))
// Check to see if Setup End or Out Packet received, if so
// do not put any new data on FIFO
{
TempReg = rbINPRDY; // Add In Packet ready flag to E0CSR bitmask
// Break Data into multiple packets if larger than Max Packet
if (DataSize >= EP0_PACKET_SIZE)
{
Fifo_Write(FIFO_EP0, EP0_PACKET_SIZE, (BYTE *)DataPtr);// Put Data on Fifo
DataPtr += EP0_PACKET_SIZE; // Advance data pointer
DataSize -= EP0_PACKET_SIZE; // Decrement data size
DataSent += EP0_PACKET_SIZE; // Increment data sent counter
}
else // If data is less than Max Packet size or zero
{
Fifo_Write(FIFO_EP0, DataSize, (BYTE *)DataPtr); // Put Data on Fifo
TempReg |= rbDATAEND; // Add Data End bit to bitmask
Ep_Status[0] = EP_IDLE; // Return EP 0 to idle state
}
if (DataSent == Setup.wLength.i)
// This case exists when the host requests an even multiple of
// your endpoint zero max packet size, and you need to exit
// transmit mode without sending a zero length packet
{
TempReg |= rbDATAEND; // Add Data End bit to mask
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -