📄 f3xx_usb0_interruptserviceroutine.c
字号:
/* Copyright (c) 2007 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is confidential property of
* Nordic Semiconductor. The use, copying, transfer or disclosure
* of such information is prohibited except by express written
* agreement with Nordic Semiconductor.
*/
/** @file
*
* Functions for handling USB interrupts. This file is originally a template
* from a SiLabs Application Note. It has been adapted to satisfy the needs of
* this application. Documentation blocks for automatical generaion of
* documentation have not been added. However, the source code has useful
* comments.
*
* @author Runar Kjellhaug
* @author Eirik Midttun
*
* @addtogroup usb_code
* @{
*/
//-----------------------------------------------------------------------------
// F3xx_USB0_InterruptServiceRoutine.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: 32X000000
// Target: C8051F32x
// Tool chain: Keil C51 7.50 / Keil EVAL C51
// Silicon Laboratories IDE version 2.6
// Command Line: See Readme.txt
// Project Name:
//
//
// Release 1.2
// -Changes by PD
// -Added SendPacket ()
// -Added EP_RX conditional statement to Endpoint 0 Handler
//
// Release 1.0
// -Initial Revision (DM)
// -08 NOV 2002
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f320.h>
#include <stdint.h>
#include <stdbool.h>
#include "nordic_common.h"
#include "usb_regs.h"
#include "f3xx_usb0_interruptserviceroutine.h"
#include "usb_desc.h"
#include "f3xx_usb0_reporthandler.h"
//-----------------------------------------------------------------------------
// Global Variable Definitions
//-----------------------------------------------------------------------------
uint8_t USB0_STATE; // Holds the current USB State
// def. in F3xx_USB0_InterruptServiceRoutine.h
setup_buffer SETUP; // Buffer for current device
// request information
bool ep1_sent, ep2_sent, ep3_sent;
xdata uint16_t DATASIZE; // Size of data to return
xdata uint16_t DATASENT; // Amount of data sent so far
xdata uint8_t* DATAPTR; // Pointer to data to return
uint8_t EP_STATUS[4] = {EP_IDLE, EP_HALT, EP_HALT, EP_HALT}; // Holds the status for each endpoint
extern xdata BufferStructure in_buffer, out_buffer;
//-----------------------------------------------------------------------------
// 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 INTERRUPT_USB0 // Top-level USB ISR
{
uint8_t 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_Control(); // is in transmit mode
}
if(bIn & rbIN1) // Handle In Packet sent, put new data
{ // on endpoint 1 fifo
ep1_sent=true;
Handle_In(1);
}
if(bOut & rbOUT1) // Handle Out packet received, take
{ // data off endpoint 2 fifo
Handle_Out1();
}
if(bIn & rbIN2) // Handle In Packet sent, put new data
{ // on endpoint 1 fifo
ep2_sent=true;
Handle_In(2);
}
if(bIn & rbIN3) // Handle In packet received, take
{ // data off endpoint 2 fifo
ep3_sent=true;
Handle_In(3);
}
if(bCommon & rbSUSINT) // Handle Suspend interrupt
{
Usb_Suspend();
}
}
//-----------------------------------------------------------------------------
// Support Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Usb_Reset
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// - Set state to default
// - Clear Usb Inhibit bit
//
//-----------------------------------------------------------------------------
void Usb_Reset (void)
{
USB0_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;
ep1_sent=ep2_sent=ep3_sent=true;
}
//-----------------------------------------------------------------------------
// Handle_Control
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// - Decode Incoming SETUP requests
// - Load data packets on fifo while in transmit mode
//
//-----------------------------------------------------------------------------
void Handle_Control(void)
{
uint8_t ControlReg; // 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 Addresscommand
{
POLL_WRITE_BYTE (FADDR, SETUP.wValue.c[cLSB]);
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
Fifo_Read (FIFO_EP0, 8, (uint8_t *)&SETUP);
// Get SETUP Packet out 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
SETUP.wValue.i = SETUP.wValue.c[cMSB] + 256*SETUP.wValue.c[cLSB];
SETUP.wIndex.i = SETUP.wIndex.c[cMSB] + 256*SETUP.wIndex.c[cLSB];
SETUP.wLength.i = SETUP.wLength.c[cMSB] + 256*SETUP.wLength.c[cLSB];
if( (SETUP.bmRequestType & ~0x80) == DSC_HID) // Intercept HID class-specific requests
{
switch (SETUP.bRequest)
{
case GET_REPORT:
Get_Report();
break;
case SET_REPORT:
Set_Report();
break;
case GET_IDLE:
Get_Idle();
break;
case SET_IDLE:
Set_Idle();
break;
case GET_PROTOCOL:
Get_Protocol();
break;
case SET_PROTOCOL:
Set_Protocol();
break;
default:
Force_Stall(); // Send stall to host if invalid
break; // request
}
}
else
{
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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -