📄 usb_isr.c
字号:
//-----------------------------------------------------------------------------
// USB_ISR.c
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "USB_Type.h"
#include "USB_Configuration.h"
#include "USB_Register.h"
#include "USB_Standard_Requests.h"
#include "USB_Class_Requests.h"
#include "USB_CDC_UART.h"
#include "FIFO_RW.h"
//#define ALLOCATE_VARS
#include "USB_ISR.h"
//-----------------------------------------------------------------------------
// configuration conditions
//-----------------------------------------------------------------------------
#if (defined USE_EP1_OUT) && !(defined ENABLE_EP1_OUT_ISO)
#define USE_EP1_OUT_STATUS
#endif
#if (defined USE_EP2_OUT) && !(defined ENABLE_EP2_OUT_ISO)
#define USE_EP2_OUT_STATUS
#endif
#if (defined USE_EP3_OUT) && !(defined ENABLE_EP3_OUT_ISO)
#define USE_EP3_OUT_STATUS
#endif
#if (defined USE_EP1_IN) && !(defined ENABLE_EP1_IN_ISO)
#define USE_EP1_IN_STATUS
#endif
#if (defined USE_EP2_IN) && !(defined ENABLE_EP2_IN_ISO)
#define USE_EP2_IN_STATUS
#endif
#if (defined USE_EP3_IN) && !(defined ENABLE_EP3_IN_ISO)
#define USE_EP3_IN_STATUS
#endif
#ifdef ENABLE_EP1_OUT_INTERRUPT
#define EP1_OUT_INTEN rbOUT1E
#else
#define EP1_OUT_INTEN 0
#endif
#ifdef ENABLE_EP2_OUT_INTERRUPT
#define EP2_OUT_INTEN rbOUT2E
#else
#define EP2_OUT_INTEN 0
#endif
#ifdef ENABLE_EP3_OUT_INTERRUPT
#define EP3_OUT_INTEN rbOUT3E
#else
#define EP3_OUT_INTEN 0
#endif
#ifdef ENABLE_EP1_IN_INTERRUPT
#define EP1_IN_INTEN rbIN1E
#else
#define EP1_IN_INTEN 0
#endif
#ifdef ENABLE_EP2_IN_INTERRUPT
#define EP2_IN_INTEN rbIN2E
#else
#define EP2_IN_INTEN 0
#endif
#ifdef ENABLE_EP3_IN_INTERRUPT
#define EP3_IN_INTEN rbIN3E
#else
#define EP3_IN_INTEN 0
#endif
#ifdef ENABLE_SOF_INTERRUPT
#define SOF_INTEN rbSOFE
#else
#define SOF_INTEN 0
#endif
#ifdef ENABLE_SUSPEND_RESUME
// #define SUSPEND_RESUME_INTEN (rbSUSINTE | rbRSUINTE)
#define SUSPEND_RESUME_INTEN (rbSUSINTE)
#else
#define SUSPEND_RESUME_INTEN 0
#endif
#define EP_OUT_INTEN (EP1_OUT_INTEN | EP2_OUT_INTEN | EP3_OUT_INTEN)
#define EP_IN_INTEN (EP1_IN_INTEN | EP2_IN_INTEN | EP3_IN_INTEN)
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
BYTE USB_State; // Hold current usb device state
Tsetup_buffer Setup; // Buffer for current device request
bit setup_handled; // flag that indicates setup stage is handled or not
UINT DataSize; // Size of data to return
BYTE* DataPtr; // Pointer to data to return
// Holds the status for each endpoint
volatile BYTE Ep_Status0 = EP_IDLE;
#ifdef USE_EP1_OUT_STATUS
volatile bit Ep_StatusOUT1 = EP_HALT;
#endif
#ifdef USE_EP2_OUT_STATUS
volatile bit Ep_StatusOUT2 = EP_HALT;
#endif
#ifdef USE_EP3_OUT_STATUS
volatile bit Ep_StatusOUT3 = EP_HALT;
#endif
#ifdef USE_EP1_IN_STATUS
volatile bit Ep_StatusIN1 = EP_HALT;
#endif
#ifdef USE_EP2_IN_STATUS
volatile bit Ep_StatusIN2 = EP_HALT;
#endif
#ifdef USE_EP3_IN_STATUS
volatile bit Ep_StatusIN3 = EP_HALT;
#endif
// FIFO status of endpoints
volatile bit IN1_FIFO_empty = TRUE;
volatile bit IN2_FIFO_empty = TRUE;
volatile bit IN3_FIFO_empty = TRUE;
volatile bit OUT1_FIFO_loaded = FALSE;
volatile bit OUT2_FIFO_loaded = FALSE;
volatile bit OUT3_FIFO_loaded = FALSE;
// function pointer for the request callback function at the end of control OUT transfer
bit (*USB_request_callback)( void );
//-----------------------------------------------------------------------------
// Static Variables in this file
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Local function prototypes
//-----------------------------------------------------------------------------
static void Handle_Setup(void); // Handle setup packet on Endpoint 0
static void Usb_Reset(void); // Called after USB bus reset
static void Handle_SOF(void);
static void Handle_Out1(void); // Handle out packet on Endpoint 1
static void Handle_Out2(void); // Handle out packet on Endpoint 2
static void Handle_Out3(void); // Handle out packet on Endpoint 3
static void Handle_In1(void); // Handle in packet on Endpoint 1
static void Handle_In2(void); // Handle in packet on Endpoint 2
static void Handle_In3(void); // Handle in packet on Endpoint 3
//-----------------------------------------------------------------------------
// Usb0_Init
//-----------------------------------------------------------------------------
//
// - Initialize USB0
// - Enable USB0 interrupts
// - Enable USB0 transceiver
// - Enable USB0 with suspend detection
//-----------------------------------------------------------------------------
void Usb0_Init(void)
{
POLL_WRITE_BYTE(POWER, 0x08); // Force Asynchronous USB Reset
// USB Interrupt enable flags are reset by USB bus reset
POLL_WRITE_BYTE(IN1IE, rbEP0E); // Enable EP 0 interrupt, disable EP1-3 IN interrupt
POLL_WRITE_BYTE(OUT1IE, 0x00); // Disable EP 1-3 OUT interrupts
POLL_WRITE_BYTE(CMIE, rbRSTINTE | SUSPEND_RESUME_INTEN); // Enable Reset and Suspend interrupts
USB0XCN = 0xE0; // Enable transceiver; select full speed
POLL_WRITE_BYTE(CLKREC, 0x80); // Enable clock recovery, single-step mode
// disabled
#ifdef ENABLE_SUSPEND_RESUME
// Enable USB0 by clearing the USB Inhibit bit
POLL_WRITE_BYTE(POWER, 0x01); // and enable suspend detection
#else
// Enable USB0 by clearing the USB Inhibit bit
POLL_WRITE_BYTE(POWER, 0x00);
#endif
}
//-----------------------------------------------------------------------------
// 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;
#if (EP_OUT_INTEN != 0)
BYTE bOut;
#endif
POLL_READ_BYTE(CMINT, bCommon); // Read all interrupt registers
POLL_READ_BYTE(IN1INT, bIn); // this read also clears the register
#if (EP_OUT_INTEN != 0)
POLL_READ_BYTE(OUT1INT, bOut);
#endif
// Handle Reset interrupt
if (bCommon & rbRSTINT) { Usb_Reset(); }
// Handle EP1-3 interrupt
#ifdef ENABLE_EP1_OUT_INTERRUPT
if (bOut & rbOUT1) { Handle_Out1(); }
#endif
#ifdef ENABLE_EP2_OUT_INTERRUPT
// if (bOut & rbOUT2) { Handle_Out2(); }
if (bOut & rbOUT2) { OUT2_FIFO_loaded = TRUE; }
#endif
#ifdef ENABLE_EP3_OUT_INTERRUPT
// if (bOut & rbOUT3) { Handle_Out3(); }
if (bOut & rbOUT3) { OUT3_FIFO_loaded = TRUE; }
#endif
#ifdef ENABLE_EP1_IN_INTERRUPT
// if (bIn & rbIN1) { Handle_In1(); }
if (bIn & rbIN1) { IN1_FIFO_empty = TRUE; }
#endif
#ifdef ENABLE_EP2_IN_INTERRUPT
// if (bIn & rbIN2) { Handle_In2(); }
if (bIn & rbIN2) { IN2_FIFO_empty = TRUE; }
#endif
#ifdef ENABLE_EP3_IN_INTERRUPT
// if (bIn & rbIN3) { Handle_In3(); }
if (bIn & rbIN3) { IN3_FIFO_empty = TRUE; }
#endif
// Handle EP0 interrupt
if (bIn & rbEP0) { Handle_Setup(); }
#ifdef ENABLE_SUSPEND_RESUME
// Handle Suspend interrupt
if (bCommon & rbSUSINT) { Usb_Suspend(); }
// Handle Resume interrupt
// if (bCommon & rbRSUINT) { Usb_Resume(); }
#endif
// SOF interrupt
#ifdef ENABLE_SOF_INTERRUPT
// if (bCommon & rbSOF) { Handle_SOF(); }
if (bCommon & rbSOF) { CDC_Handle_INT_IN(); // Handle Notification endpoint
CDC_Handle_Bulk_IN_ZLP(); } // Send ZLP to bulk IN when required
#endif
}
//-----------------------------------------------------------------------------
// Support Routines for ISR
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SDCC suport
//-----------------------------------------------------------------------------
#if defined SDCC
#pragma nooverlay
#endif // SDCC
//-----------------------------------------------------------------------------
// Usb_Reset
//-----------------------------------------------------------------------------
//
// - Set state to default
// - Clear Usb Inhibit bit
//
//-----------------------------------------------------------------------------
static void Usb_Reset(void)
{
POLL_WRITE_BYTE(IN1IE, rbEP0E | EP_IN_INTEN ); // Enable Ep0 and EP1-3 IN
#if (EP_OUT_INTEN != 0)
POLL_WRITE_BYTE(OUT1IE, EP_OUT_INTEN ); // Enable EP1-3 OUT
#endif
POLL_WRITE_BYTE(CMIE, rbRSTINTE | SUSPEND_RESUME_INTEN | SOF_INTEN); // Enable Reset, Suspend interrupts
POLL_WRITE_BYTE(POWER, 0x01); // Clear usb inhibit bit to enable USB
// suspend detection
USB_State = DEV_DEFAULT; // Set device state to default
Ep_Status0 = EP_IDLE; // Set default Endpoint Status
#ifdef USE_EP1_OUT_STATUS
Ep_StatusOUT1 = EP_HALT;
#endif
#ifdef USE_EP2_OUT_STATUS
Ep_StatusOUT2 = EP_HALT;
#endif
#ifdef USE_EP3_OUT_STATUS
Ep_StatusOUT3 = EP_HALT;
#endif
#ifdef USE_EP1_IN_STATUS
Ep_StatusIN1 = EP_HALT;
#endif
#ifdef USE_EP2_IN_STATUS
Ep_StatusIN2 = EP_HALT;
#endif
#ifdef USE_EP3_IN_STATUS
Ep_StatusIN3 = EP_HALT;
#endif
}
//-----------------------------------------------------------------------------
// Handle_Setup
//-----------------------------------------------------------------------------
//
// - Decode Incoming Setup requests
// - Load data packets on fifo while in transmit mode
//
//-----------------------------------------------------------------------------
static bit send_eq_requested = FALSE; // flag that indicates that the data to send on TX
// equals to the requested by Setup wLength
// KEIL doesn't accept static local bit variable
static 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -