⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_int.c

📁 HID-Ukey底层源码实现(st72651芯片) windows上层驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
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 + -