📄 usb_int.c
字号:
void USB_Polling(void)
{
asm {
LD X, _Token_Index
JREQ _End_EP0_Polling
CALL (Token_Routines, X) // process particular token
_Check_Token_OverRun:
SIM // Disable all interrupt
LD X, _Token_OverRun
JREQ _Update_EP0_State
CLR _Token_OverRun
RIM // Enable all interrupt
CALL USB_SETUP_Stage // Process the overrun SETUP token
JRT _Check_Token_OverRun
_Update_EP0_State:
CALL Change_EP0_State // Now we are interrupt protected
CLR _Token_Index // Clear the Token after process
RIM // Enable all interrupt
_End_EP0_Polling:
}
_Check_Non_EP0_Events();
}
#endif // USB_POLLING_MODEL
#ifndef USB_POLLING_MODEL
void Call_Non_EP0_Interrupt(void)
{
// unsigned char EPx = USBSR & 0x27;
// if (EPx == 0x21) {
if (ValBit(EP1TXR, 3)) {
ClrBit(EP1TXR, 3);
#ifdef DECLARE_EP1
_USB_EP1_XEvent();
#endif
}
#ifdef MCU_ST7265
// else if (EPx == 0x01) {
else if (ValBit(EP1RXR, 3)) {
ClrBit(EP1RXR, 3);
#ifdef DECLARE_EP1
_USB_EP1_REvent();
#endif
}
#endif
// else if (EPx == 0x22) {
else if (ValBit(EP2TXR, 3)) {
ClrBit(EP2TXR, 3);
#ifdef DECLARE_EP2
_USB_EP2_XEvent();
#endif
}
// else if (EPx == 0x02) {
else if (ValBit(EP2RXR, 3)) {
ClrBit(EP2RXR, 3);
#ifdef DECLARE_EP2
_USB_EP2_REvent();
#endif
}
#ifdef MCU_ST7SCR
// else if (EPx == 0x23) {
else if (ValBit(EP3TXR, 3)) {
ClrBit(EP3TXR, 3);
#ifdef DECLARE_EP3
_USB_EP3_XEvent();
#endif
}
// else if (EPx == 0x24) {
else if (ValBit(EP4TXR, 3)) {
ClrBit(EP4TXR, 3);
#ifdef DECLARE_EP4
_USB_EP4_XEvent();
#endif
}
// else if (EPx == 0x25) {
else if (ValBit(EP5TXR, 3)) {
ClrBit(EP5TXR, 3);
#ifdef DECLARE_EP5
_USB_EP5_XEvent();
#endif
}
#endif // MCU_ST7SCR
}
/*-----------------------------------------------------------------------------
ROUTINE NAME : INT_USB - Interrupt model
DESCRIPTION : Comes from the USB cell.
-----------------------------------------------------------------------------*/
#pragma TRAP_PROC
void INT_USB(void)
{
// Check the SETUP overrun event first
// This is the one of two events that can interrupt USB state machine
asm {
BTJF USBISTR,#5,_No_Setup_OverRun
// Process SETUP overrun interrupt
BRES USBISTR,#5 // clear SOVR bit
LD A, _Token_Index // check USB state machine is in idle
// JREQ impossible_error // Impossible to get SETUP overrun when machine is in idle
_SETUP_Recv:
#ifdef CUT09
////////These 2 lines are done by H/W
LD X, #MAX_PACKET_SIZE
LD CNT0RXR, X
#endif
LD X, #SETUP_INDEX
#ifdef SETUP_PREEMPTIVE
CP A, #STATUS_IN_INDEX
// When we are in status stage process
// mark down this setup token and return to status stage process
JRUGE _Mark_OverRun
// when we are not in status stage process
LD A, Token_Stack // give away the current token process
LD S, A // by change the stack pointer
JRT _Reenter_Token_Branch
#endif
_Mark_OverRun:
LD _Token_OverRun, X // Save the token and return immediately
IRET
_No_Setup_OverRun:
LD A, _Token_Index // check USB state machine is in idle
JREQ _No_Nest_Events // Not in idle, this is an normal interrupt
// Check the CTR event, this is the another event that can interrupt USB state machine
BTJT EP0R, #7, _Yes_Setup_INT
JP _Non_EP0_Interrupt // Check non-EP0 interrupt
_Yes_Setup_INT:
BRES EP0R, #7 // Clear CTR0 bit
// Assertion
// LD A, USBSR
// AND A, #0xC0
// CP A, #0xC0
// JREQ _SETUP_Recv
// JRT impossible_error ; The event must be a SETUP, otherwise it is an error
JRT _SETUP_Recv
impossible_error:
HALT
IRET
}
// Below code checks all non nest interrupt events
// Check the events on EP0 first
asm {
_No_Nest_Events:
BTJF EP0R,#7,_Non_CTR_Int
LD A, USBSR // identify the Status Stage as earlier as here
CP A, #$0C0
JREQ _SETUP_Stage // a SETUP token, can not be a Status Stage
XOR A, sUSB_vSetup
JRPL _Data_Stage // Same direction, not a Stagus Stage
// This is a status stage
BTJF USBSR, #7, _Status_OUT_Stage
_Status_IN_Stage:
LD A, #$0B1
LD EP0R, A // STALL Recv and Enable Xmit
LD X, #STATUS_IN_INDEX
JRT _Token_Branch
_Status_OUT_Stage:
LD A, #$093
LD EP0R, A // STALL Xmit and Enable Recv
LD X, #STATUS_OUT_INDEX
JRT _Token_Branch
_SETUP_Stage:
LD X, #SETUP_INDEX
JRT _Token_Branch
_Data_Stage:
LD A, USBSR
JRMI _Data_In_Stage
_Data_Out_Stage:
LD X, #DATA_OUT_INDEX
LD A, #MAX_PACKET_SIZE // Since we have to set the CNT0RXR in _Token_Branch
SUB A, CNT0RXR // in order to allow a SETUP comes in after clear CTR0
LD _vUSB_Data_OUT_Len, A // read the length of data out stage here
JRT _Token_Branch
_Data_In_Stage:
LD X, #DATA_IN_INDEX
_Token_Branch:
BRES EP0R, #7 // Clear CTR0 bit
#ifdef CUT09
////////These 2 lines will be done by H/W
LD A, #MAX_PACKET_SIZE
LD CNT0RXR, A
#endif
PUSH Y
LD A, _R_Z
PUSH A
LD A, _LEX:1
PUSH A
LD A, _LEX
PUSH A
LD A, _SEX:1
PUSH A
LD A, _SEX
PUSH A // Save all registers
LD A, USBIMR
PUSH A // save the interrupt mask
LD A, #0xA0 // Turn off all the interrupt source
LD USBIMR, A // Leave SETUP overrun & CTR only
#ifdef SETUP_PREEMPTIVE // Save STACK pointer so that we can come back when SETUP overrun
LD A, S
LD Token_Stack, A
#endif
_Reenter_Token_Branch:
LD _Token_Index, X
LD A, #0x08
PUSH A
POP CC // change the interrupt level from 2 to 1
CALL (Token_Routines, X)
SIM // protect the following 3 instructions to be interrupted
CLR A
PUSH A
POP CC // change the interrupt level back to 2
// When SETUP overrun happens during processing status stage
// _Token_OverRun remembers the event
// These two lines are useful only after status stage
LD X, _Token_OverRun
CLR _Token_OverRun
TNZ X
JRNE _Reenter_Token_Branch
CALL Change_EP0_State // Now we are interrupt protected
CLR _Token_Index
POP A
LD USBIMR, A // restore the USB interrupt mask
// Check _Non_EP0_Events, see if we have non-EP0 events during process EP0 events
CALL _Check_Non_EP0_Events
JRT Int_Return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_Non_CTR_Int:
}
if (USBISTR & USBIMR & IMR_ERR) { // ERROR IT
USBISTR &= ~IMR_ERR; // Clear ERR bit
return; // Just clear the status and do nothing
}
asm {
PUSH Y
LD A, _R_Z
PUSH A
LD A, _LEX:1
PUSH A
LD A, _LEX
PUSH A
LD A, _SEX:1
PUSH A
LD A, _SEX
PUSH A
BTJF USBISTR,#7,_Non_CTR // test if other endpoint interrupts
CALL Call_Non_EP0_Interrupt
_Non_CTR:
}
if (USBISTR & USBIMR & IMR_SUSP) { // SUSPEND IT
ClrBit(USBISTR, ISTR_SUSP); // clear SUSP bit
USBCTLR |= 0x02; // set FSUSP bit
USERIT(USER_Suspend);
}
if (USBISTR & USBIMR & IMR_RESET) { // RESET IT
USBISTR = 0x00; // Clear ISTR register
USB_Reset();
}
if (USBISTR & USBIMR & IMR_SOF) { // SOF IT
USERIT(USER_SOF);
USBISTR &= ~IMR_SOF; // clear SOF bit (5cy)
}
asm {
Int_Return:
POP A
LD _SEX, A
POP A
LD _SEX:1, A
POP A
LD _LEX, A
POP A
LD _LEX:1, A
POP A
LD _R_Z, A
POP Y
}
}
#endif // Interrupt model
/*-----------------------------------------------------------------------------
ROUTINE NAME : INT_EndSusp
DESCRIPTION : External Interrupt
-----------------------------------------------------------------------------*/
#pragma TRAP_PROC SAVE_REGS
void INT_EndSusp(void)
{
USBCTLR &= ~0x02; // reset FSUSP bit to wakeup the USB
ClrBit(USBISTR, ISTR_ESUSP); // clear ESUSP bit
USERIT(USER_ESuspend);
}
/**************** (c) 2000 STMicroelectronics *******************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -