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

📄 u08usb.c

📁 MC68HC08JB8 的USB驱动源程序,开发环境是Code wayyior HC08
💻 C
字号:
//============================================================================
// File: U08USB.C
// Func: USB Implementation Module for USB08 Demo Application
// Ver.: 1.01
// Auth: (C)2000,2001 by Oliver Thamm, MCT Elektronikladen GbR
//       http://hc08web.de/usb08
// Rem.: View/Edit this File with TAB-Size=4
//============================================================================


#include "u08usb.h"				// Definitions for USB Data Types & Constants
#include "u08desc.c"			// const USB Descriptor Data

//-- Source Code Option - set as required by Hardware! -----------------------
//
#define USB_IPUE	1			// Internal Pull-up Enable
								// 1=Enable	(use build-in Pull-up Resistor)
								// 0=Disable (external Pull-up required)
//-- Variables ---------------------------------------------------------------
#pragma DATA_SEG SHORT MY_ZEROPAGE
volatile uchar USB_State;

#define MAX_TXBUF_SIZE 16		// must be 2^x!
volatile uchar TxBuffer[MAX_TXBUF_SIZE];
volatile uchar TxBuf_RdIdx;
volatile uchar TxBuf_WrIdx;

#define MAX_RXBUF_SIZE 16		// must be 2^x!
volatile uchar RxBuffer[MAX_RXBUF_SIZE];
volatile uchar RxBuf_RdIdx;
volatile uchar RxBuf_WrIdx;

volatile uchar SuspendCounter;

setup_buffer SetupBuffer;
uchar SetupSize;
const uchar * SetupDataPtr;

uchar R0Sequence;	// DATA0/1 Flag for EP0 Rx
uchar R2Sequence;	// DATA0/1 Flag for EP2 Rx
#pragma DATA_SEG DEFAULT
//----------------------------------------------------------------------------

// Force STALL Condition for EP0 (both IN and OUT)
// as a Response to an invalid SETUP Request
// Flags will be auto-cleared by the next SETUP Token
//
void forceSTALL() {
	UCR3 |= BM_OSTALL0 + BM_ISTALL0;
	}

//----------------------------------------------------------------------------

#define ENDPOINT_HALT	0x00
#define RT_ENDPOINT		0x02


// CLEAR_FEATURE Standard Device Request Handler
// called by handleSETUP();
//
void clearFeature() {

	if( SetupBuffer.wValue.hi ||
		SetupBuffer.wIndex.hi ||
		SetupBuffer.wLength.hi ||
		SetupBuffer.wLength.lo)	// check 0-fields
		forceSTALL();
	else if((SetupBuffer.bmRequestType == RT_ENDPOINT) &&
		(SetupBuffer.wValue.lo == ENDPOINT_HALT) &&
		((SetupBuffer.wIndex.lo==0x81) || (SetupBuffer.wIndex.lo==0x02))) {
		// clear EP1/2 Force STALL Bit
		if(SetupBuffer.wIndex.lo == 0x81) { // EP1
			UCR1 &= ~(BM_T1SEQ+BM_STALL1);	// clear STALL, Sequence = DATA0
			}
		else { // EP2
			UCR2 &= ~BM_STALL2;				// clear STALL
			R2Sequence = 0;					// Sequence = DATA0
			}
		// prepare to send empty DATA1 at next IN Transaction
		UCR0 = BM_T0SEQ + BM_TX0E + 0;
		}
	else forceSTALL();
	}

//----------------------------------------------------------------------------


// SET_ADDRESS Standard Device Request Handler
// called by handleSETUP();
//
void setAddress() {

	if(	SetupBuffer.wIndex.hi ||
		SetupBuffer.wIndex.lo ||
		SetupBuffer.wLength.hi ||
		SetupBuffer.wLength.lo ||
		SetupBuffer.wValue.hi ||
		(SetupBuffer.wValue.lo & 0x80))
		forceSTALL();
	else {
		// prepare to send empty DATA1 at next IN Transaction
		UCR0 = BM_T0SEQ + BM_TX0E + 0;
		}
	}

//----------------------------------------------------------------------------


// SET_CONFIGURATION Standard Device Request Handler
// called by handleSETUP();
//
void setConfiguration() {

	if(	SetupBuffer.wIndex.hi ||
		SetupBuffer.wIndex.lo ||
		SetupBuffer.wLength.hi ||
		SetupBuffer.wLength.lo ||
		SetupBuffer.wValue.hi ||
		(SetupBuffer.wValue.lo > 1) ||
		(USB_State == US_DEFAULT)) {
		forceSTALL();
		}
	else {
		if(SetupBuffer.wValue.lo > 0) {
			// no need to remember the Configuration Value
			// since we support only one Configuration anyway
			USB_State = US_CONFIGURED;
			// Activate Interrupt Endpoints, reset STALL and DATA-Toggle
			UCR1 = BM_TX1E + 0;	// EP1 Tx Enable, Data Size is 0
			UCR2 = BM_RX2E;		// EP2 Rx Enable
			}
		else {
			// Zero means: go back to Adressed State
			USB_State = US_ADDRESSED;
			UCR1 = 0;			// deactivate EP1
			UCR2 = 0;			// deactivate EP2
			}
		// prepare to send empty DATA1 at next IN Transaction
		UCR0 = BM_T0SEQ + BM_TX0E + 0;
		}
	}

//----------------------------------------------------------------------------


// GET_DESCRIPTOR Standard Device Request Handler
// called by handleSETUP();
//
void getDescriptor() {

	uchar n;
	uchar *dest;

	switch(SetupBuffer.wValue.hi) {

		case DT_DEVICE:			// Get Device Descriptor
			SetupDataPtr = (uchar *)&DeviceDesc;
			SetupSize = DeviceDesc.bLength;
			break;

		case DT_CONFIGURATION:	// Get Configuration Descriptor
			SetupDataPtr = (uchar *)&ConfigDesc;
			SetupSize = ConfigDesc.wTotalLength.lo;
			break;

		case DT_STRING:			// Get String Descriptor
			// ### Table Index Boundary should be checked
			SetupDataPtr = StringDescTable[SetupBuffer.wValue.lo];
			SetupSize = *SetupDataPtr;
			break;

		default:
			forceSTALL();
			break;
		}

	if( SetupBuffer.wValue.hi == DT_DEVICE ||
		SetupBuffer.wValue.hi == DT_CONFIGURATION ||
		SetupBuffer.wValue.hi == DT_STRING) {

		// check if requested Length is less than Descriptor Length
		if((SetupBuffer.wLength.lo < SetupSize) && (SetupBuffer.wLength.hi == 0))
			SetupSize = SetupBuffer.wLength.lo;
		// copy (up to) 8 Bytes to EP0 Data Registers
		n = 0;
		dest = (uchar *)&UE0D0;
		while(SetupSize!=0 && n<8) {
			*dest = *SetupDataPtr;
			dest++;
			SetupDataPtr++;
			SetupSize--;
			n++;
			}
		// prepare to send n Bytes as DATA1 at next IN Transaction
		// Rem: RX0E (currently disabled) will be re-enabled at end of handleSETUP()
		UCR0 = BM_T0SEQ + BM_TX0E + n;
		// check if this is the last DATA packet to send
		if(n < 8) SetupBuffer.bRequest = REQUEST_COMPLETE;
		}
	}

//----------------------------------------------------------------------------

void handleSETUP() {

	UCR0 &= ~BM_RX0E;			// Deactivate EP0 Receiver
	UIR2 = BM_RXD0FR;			// Reset EP0 Receive Flag

	SetupBuffer = *(setup_buffer *)(&UE0D0);

	if(USR0 != 0x48) {			// SETUP Transaction must be DATA0 with Size=8
		forceSTALL();			// otherwise we have an Error Condition
		}
	else {						// now we will check the Request Type
		if((SetupBuffer.bmRequestType & 0x60) != 0) {
			forceSTALL();		// Non-Standard Requests will not be handled!
			}
		else {					// Standard Request Decoder:
			switch(SetupBuffer.bRequest) {
				case CLEAR_FEATURE:		// 1
					clearFeature();
					break;
				case SET_ADDRESS:		// 5
					setAddress();
					break;
				case GET_DESCRIPTOR:	// 6
					getDescriptor();
					break;
				case SET_CONFIGURATION:	// 9
					setConfiguration();
					break;
				default:
					forceSTALL();
					break;
				}
			}
		}
	UCR0 |= BM_RX0E;			// Activate EP0 Receiver
	}

//----------------------------------------------------------------------------

void handleOUT() {

	UCR0 &= ~(BM_RX0E+BM_TX0E);	// Deactivate EP0 Receiver + Transmitter
	UIR2 = BM_RXD0FR;			// Reset EP0 Receive Flag

	// OUT Transactions over EP0 appear as Status Stage
	// of a Standard Device Request only

	UCR0 |= BM_RX0E;			// Activate EP0 Receiver
	}

//----------------------------------------------------------------------------

void handleIN() {

	uchar n;
	uchar *dest;

	UCR0 &= ~BM_TX0E;			// Deactivate EP0 Transmitter
	UIR2 = BM_TXD0FR;			// Reset EP0 Transmit complete Flag

	switch(SetupBuffer.bRequest) {
		case SET_ADDRESS:
			UADDR = SetupBuffer.wValue.lo | BM_USBEN;
			if(SetupBuffer.wValue.lo != 0) USB_State = US_ADDRESSED;
			else USB_State = US_DEFAULT;
			SetupBuffer.bRequest = REQUEST_COMPLETE;
			break;
		case GET_DESCRIPTOR:
			// copy (up to) 8 Bytes to EP0 Data Registers
			n = 0;
			dest = (uchar *)&UE0D0;
			while(SetupSize!=0 && n<8) {
				*dest = *SetupDataPtr;
				dest++;
				SetupDataPtr++;
				SetupSize--;
				n++;
				}
			// prepare to send n Bytes at next IN Transaction
			// toggle DATA0/1
			UCR0 = ((UCR0^BM_T0SEQ) & BM_T0SEQ) + BM_TX0E + BM_RX0E + n;
			// check if this is the last DATA packet to send
			if(n < 8) SetupBuffer.bRequest = REQUEST_COMPLETE;
			break;
		case CLEAR_FEATURE:
		case SET_CONFIGURATION:
			// nothing to do - handshake finished
			SetupBuffer.bRequest = REQUEST_COMPLETE;
			break;
		case REQUEST_COMPLETE:
			// Request is finished - just clear the TXD0F Flag (see above)
			// and do not re-enable EP0 Transmitter, since there is no more
			// data to send
			break;
		default:
			forceSTALL();
			break;
		}
	}

//----------------------------------------------------------------------------

// handle IN Packet Transmit complete over EP1
//
void handleIN1() {

	uchar n;
	uchar volatile *dest;

	UCR1 &= ~BM_TX1E;			// Deactivate EP1 Transmitter
	UIR2 = BM_TXD1FR;			// Reset EP1 Transmit complete Flag

	// refill EP1 Tx Data Buffer
	n = 0;
	dest = &UE1D0;
	while((TxBuf_RdIdx != TxBuf_WrIdx) && n<8) {
		*dest = TxBuffer[TxBuf_RdIdx];
		TxBuf_RdIdx = (TxBuf_RdIdx+1) & (MAX_TXBUF_SIZE-1);
		dest++;
		n++;
		}
	// Activate EP1 Transmitter to send n Bytes
	UCR1 = ((UCR1^BM_T1SEQ) & BM_T1SEQ) + BM_TX1E + n;
	}

//----------------------------------------------------------------------------

// handle OUT Packet received over EP2
//
void handleOUT2() {

	uchar n;
	uchar newIdx;
	uchar volatile *src;

	UCR2 &= ~BM_RX2E;			// Deactivate EP2 Receiver
	UIR2 = BM_RXD2FR;			// Reset EP2 Receive Flag

	// ### Sender's DATA Toggle should be checked!

	// read out EP2 Rx Data Buffer
	src = &UE2D0;
	n = USR1 & BM_RP2SIZ;		// Check Transfer Size
	while(n) {
		newIdx = (RxBuf_WrIdx+1) & (MAX_RXBUF_SIZE-1);
		while(newIdx == RxBuf_RdIdx)
			;	// wait if TxBuffer is full
		RxBuffer[RxBuf_WrIdx] = *src;
		RxBuf_WrIdx = newIdx;
		src++;
		n--;
		}
	UCR2 = BM_RX2E;				// Activate EP2 Receiver
	}

//----------------------------------------------------------------------------

void initUSB() {

	UADDR = BM_USBEN + 0;		// USB enable, default address
	UCR0 = 0;					// reset EP0
	UCR1 = 0;					// reset EP1
	UCR2 = 0;					// reset EP2
	UCR3 = BM_TX1STR +			// clear TX1ST Flag
		   USB_IPUE*BM_PULLEN;	// enable/disable internal Pull-up
	UCR4 = 0;					// USB normal operation
	UIR0 = 0;					// disable Interrupts
	UIR2 = 0xff;				// clear all Flags in UIR1
	R0Sequence = 0;				// EP0 Rx starts with DATA0
	R2Sequence = 0;				// EP2 Rx starts with DATA0
	USB_State = US_POWERED;		// powered, but not yet reset
	TxBuf_RdIdx = 0;			// reset Buffer Indexes
	TxBuf_WrIdx = 0;
	RxBuf_RdIdx = 0;
	RxBuf_WrIdx = 0;
	}

//----------------------------------------------------------------------------

uchar getUSB() {

	uchar c;

	while(RxBuf_RdIdx == RxBuf_WrIdx)
		;	// wait if RxBuffer is empty
	c = RxBuffer[RxBuf_RdIdx];
	RxBuf_RdIdx = (RxBuf_RdIdx+1) & (MAX_RXBUF_SIZE-1);
	return c;
	}

//----------------------------------------------------------------------------

void putUSB(uchar c) {

	uchar newIdx;

	newIdx = (TxBuf_WrIdx+1) & (MAX_TXBUF_SIZE-1);
	while(newIdx == TxBuf_RdIdx)
		;	// wait if TxBuffer is full
	TxBuffer[TxBuf_WrIdx] = c;
	TxBuf_WrIdx = newIdx;
	}

//----------------------------------------------------------------------------

// USB Interrupt Handler
// All Interrupt Sources of the JB8's integrated USB peripheral
// will be treated by this ISR
//

interrupt void isrUSB() {

	if(UIR1 & BM_EOPF) {		// End of Packet detected?
		SuspendCounter = 0;				// reset 3ms-Suspend Counter
		UIR2 = BM_EOPFR;				// reset EOP Intr Flag
		}
	else if(UIR1 & BM_RXD0F) {	// has EP0 received some data?
		if(USR0 & BM_SETUP)				// was it a SETUP Packet?
			handleSETUP();
		else							// or a normal OUT Packet
			handleOUT();
		}
	else if(UIR1 & BM_TXD0F) {	// has EP0 sent Data?
		handleIN();
		}
	else if(UIR1 & BM_TXD1F) {	// has EP1 sent Data?
		handleIN1();
		}
	else if(UIR1 & BM_RXD2F) {	// has EP2 received Data?
		handleOUT2();
		}
	else if(UIR1 & BM_RSTF) {	// USB Reset Signal State detected?
		initUSB();						// Soft Reset of USB Systems
		UCR3 |= BM_ENABLE1+BM_ENABLE2;	// Enable EP1 and EP2
		UIR0 = BM_TXD0IE + BM_RXD0IE +	// EP0 Rx/Tx Intr Enable and
			   BM_TXD1IE + BM_RXD2IE +	// EP1 Tx and EP2 Rx Intr Enable
			   BM_EOPIE;				// and End-of-Packet Intr Enable
		UCR0 |= BM_RX0E;				// EP0 Receive Enable
		USB_State = US_DEFAULT;			// Device is powered and reset
		}
	}

//============================================================================

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -