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

📄 msdnotworking.c

📁 PIC18F4550 SD CARD USB
💻 C
📖 第 1 页 / 共 2 页
字号:
/** I N C L U D E S **********************************************************/
#include <p18cxxx.h>

#include "system\typedefs.h"
#include "system\usb\usb.h"
#include "fileio.h"
//#include "system\sdcard\sdcard.h" 

#include<string.h>

//#ifndef MSD_H
//#include "system\usb\class\msd\msd.h"

#ifdef USB_USE_MSD
//#define USB_USE_MSD

#define mLED_Both_On()          {mLED_2_On();mLED_3_On();}
#define CSD_SIZE 16
extern CSD gblCSDReg;					// declared in sdcard.c
extern SDC_Error RMediaInitialize(SDCSTATE*);
extern SDC_Error sdcardinitialize(void);
extern SDC_Error MediaInitialize();
extern void SocketInitialize(void);
extern byte MediaDetect(void);
extern void DetectSDCard(void); 
extern SDC_Error SECTORread(dword, byte*);
extern SDC_Error CSDread(byte*);
extern CETYPE StartupCard(DISK *, byte *, CARDSTATUS *);
dword ConvertLBASector(dword LBA);

// Global Variable for keeping state of the MSD firmware
byte MSD_State;
byte MSD_Data;
USB_MSD_CBW gblCBW;
byte gblCBWLength;
SDCSTATE gblFlag;
RequestSenseResponse gblSenseData;
byte *ptrNextData;
dword dataLen;
FILE	gblFile;							// The global file structure
DISK	gblDisk;							// The global disk structure
CARDSTATUS gblCardStatus;
DWORD gblNumBLKS=0x00,gblBLKLen=0x00;		// made global because need to verify if the last lba is less than gblNumBLKS
											// for every read and write command		
dword gblLBA=0x269;

const rom InquiryResponse inq_resp = {
	0x00,				// peripheral device is connected, direct access block device
	0x80,               // removable
	0x04,				// version = 00=> does not conform to any standard, 4=> SPC-2
	0x02,				// response is in format specified by SPC-2
	0x20,				// n-4 = 36-4=32= 0x20
	0x00,				// sccs etc.
	0x00,				// bque=1 and cmdque=0, indicates simple queueing 00 is obsolete, 
						// but as in case of other device, we are just using 00
	0x00,				// 00 obsolete, 0x80 for basic task queueing
	"Microchp",
	"Ma$$ Storage    ",
	"0001"
};

/**************************************************
Initialize the SD Card
***************************************************/
	
void MSInit(void) 
{
	SDC_Error status;
	SocketInitialize();
    mInitAllLEDs();
    status=RMediaInitialize(&gblFlag);
    if (status) { mLED_1_On(); mLED_2_On(); mLED_3_On(); mLED_4_On();}		// If there was some error, turn on all leds 
	MSD_State=MSD_WAIT;
	
 }    
 
 
/******************************************************************************
 * Function:        void USBCheckMSDRequest(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This routine handles the standard RESET and GET_MAX_LUN command requests on control endpoint
 *
 * Note:            None
 *****************************************************************************/	
void USBCheckMSDRequest(void)
{
	//mLED_2_On();
	//if(SetupPkt.Recipient != RCPT_INTF) return;
    //if(SetupPkt.bIntfID != MSD_INTF_ID) return;
    //if(SetupPkt.RequestType != CLASS) return;
    switch(SetupPkt.bRequest)
    {
	    case MSD_RESET:
	    	ctrl_trf_session_owner = MUID_MSD;
	    	mDisableEP1to15();                          // See usbdrv.h
	    	//MSDInitEP();
	    	// mLED_2_On();
	    	if (UEP1bits.EPSTALL==1) {
		    	//USBPrepareForNextSetupTrf();        // Firmware work-around
	    		UEP1bits.EPSTALL = 0;
	    		mLED_3_On();
	    		MSDInitEP();
	    	}
			UIRbits.STALLIF = 0;
			/*
			MSD_UEP = EP_OUT_IN|HSHK_EN;                // Enable 2 data pipes
    		MSD_BD_OUT.Cnt=sizeof(msd_cbw);
    		MSD_BD_OUT.ADR=(byte*)&msd_cbw;
    		MSD_BD_OUT.Stat._byte = _USIE|_DTSEN;	//usbmmap.h owner SIE, DAT0 expected next, data toggle sunc enable
   			MSD_BD_IN.ADR = (byte*)&msd_buffer[0];      // Set buffer address    
    		MSD_BD_IN.Stat._byte = _UCPU;   // Set status CPU owns Data1 expected next
    		*/
	    	break;
	    case GET_MAX_LUN:
	    	ctrl_trf_session_owner = MUID_MSD;
	    	CtrlTrfData._byte[0] = MAX_LUN;
	    	wCount._word = 1;
	    	pSrc.bRam = (unsigned char*)&CtrlTrfData;
	    	usb_stat.ctrl_trf_mem = _RAM;
	    	break;
    }	//end switch(SetupPkt.bRequest)
}

void sendCSW(void)
{
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_csw;
	MSD_BD_IN.Cnt=MSD_CSW_SIZE;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();	
	//while(mMSDRxIsBusy());
	MSD_BD_OUT.Cnt=sizeof(msd_cbw);		
    MSD_BD_OUT.ADR=(byte*)&msd_cbw;			// in MSD_DATA_OUT state the address was changed to point tomsd_buffer
   	MSD_State=MSD_WAIT;
}

void sendData(byte* dataAddr, byte dataSize)
{
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=dataAddr;
	MSD_BD_IN.Cnt=dataSize;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
}

void MSDDataIn(void)
{
	byte i;
	dword size;
	// Case (status==0) and (data to be sent > MSD_IN_EP_SIZE)
	if ((msd_csw.bCSWStatus==0x00)&&(msd_csw.dCSWDataResidue>=MSD_IN_EP_SIZE)) {
		// write next chunk of data to EP Buffer and send
		sendData(ptrNextData,MSD_IN_EP_SIZE);
		gblCBW.dCBWDataTransferLength-=	MSD_IN_EP_SIZE;
		msd_csw.dCSWDataResidue-=MSD_IN_EP_SIZE;
		ptrNextData+=MSD_IN_EP_SIZE;
	} else {
		if (msd_csw.bCSWStatus!=0x0) { // error path status!=0
			size=mMin(MSD_IN_EP_SIZE,gblCBW.dCBWDataTransferLength);
			for (i=0;i<size;i++) msd_buffer[i]=0;	// prepare 0 data
			if (gblCBW.dCBWDataTransferLength > MSD_IN_EP_SIZE) {	// Case (status!=0) and (data to be sent > MSD_IN_EP_SIZE)
				// write next chunk of data to EP Buffer and send
				sendData((byte*)&msd_buffer[0],MSD_IN_EP_SIZE);
				gblCBW.dCBWDataTransferLength -= MSD_IN_EP_SIZE;
				msd_csw.dCSWDataResidue-=MSD_IN_EP_SIZE;
			} else {				// Case (status!=0) and (data to be sent < MSD_IN_EP_SIZE)
				// write next chunk of data to EP Buffer and send
				sendData((byte*)&msd_buffer[0],gblCBW.dCBWDataTransferLength);
				gblCBW.dCBWDataTransferLength = 0;			// we have sent 0s for what was expected by host
				msd_csw.dCSWDataResidue -= gblCBW.dCBWDataTransferLength;
			}
		} else { 					// Case (status ==0) and (data to be sent < MSD_IN_EP_SIZE)
			// write next chunk of data to EP Buffer and send
			sendData(ptrNextData,msd_csw.dCSWDataResidue);
			gblCBW.dCBWDataTransferLength -= msd_csw.dCSWDataResidue ;	// we have sent all the data that was expected by host
			msd_csw.dCSWDataResidue = gblCBW.dCBWDataTransferLength;
			gblCBW.dCBWDataTransferLength = 0;							// in case the host expected more than what we had to send
																		// setting DataTransferLength=0 will ensure sending CSW		
		}
	}
	//mUSBBufferReady(MSD_BD_IN);
	//USBDriverService();
}

void MSDDataOut(void) 
{
	while(mMSDRxIsBusy());
	// We can only read 64 bytes at a time;
	dataLen+=MSD_BD_OUT.Cnt;
	//if(MSD_BD_OUT.Cnt==MSD_OUT_EP_SIZE) {
	ptrNextData+=MSD_BD_OUT.Cnt;
	MSD_BD_OUT.ADR=(byte*)ptrNextData; // else need not update the pointer as that will be last chunk
	if (dataLen==0x0200)
		MSD_BD_OUT.ADR=(byte*)&msd_buffer[0];
	
	//}
		// if we have received data in excess of what host was to send
	//if (gblCBW.dCBWDataTransferLength<MSD_BD_OUT.Cnt) {
	//	msd_csw.bCSWStatus=0x02;
	//	gblCBW.dCBWDataTransferLength=0;
	//} else {
		gblCBW.dCBWDataTransferLength-=MSD_BD_OUT.Cnt;
		msd_csw.dCSWDataResidue-=MSD_BD_OUT.Cnt;
	//}
	mUSBBufferReady(MSD_BD_OUT);
	USBDriverService();
}

void ProcessIO(void)
{
	byte i;
	dword size;
		
	if (MSD_State==MSD_DATA_IN) {
		// Send data to host
		if(gblCBW.dCBWDataTransferLength==0) { sendCSW(); }	// finished sending the data send the status
		else 				// still have data to send
			MSDDataIn();	// else dCBWDataTransferLength==0
		return;	
	}	
	if (MSD_State==MSD_DATA_OUT) {
		if(gblCBW.dCBWDataTransferLength==0) { 	// finished receiving the data prepare and send the status
		  	//if ((msd_csw.bCSWStatus==0x00)&&(msd_csw.dCSWDataResidue!=0)) 
		  	//	msd_csw.bCSWStatus=0x02;
			sendCSW();	// sends the csw and sets the state to wait
			ptrNextData=(byte*)&msd_buffer[0];
		} else {
			mLED_1_On(); mLED_2_On();
		}
			//else { // else of if DataTransferLength == 0
			// basically the code will not come here because only place the OUT transaction is required (i think!!)
			// is write and during processing of the data itself, the OUT data is read
			//MSDDataOut();
		//}
		return;
	}
	if(!MSD_BD_OUT.Stat.UOWN)				// If the CPU owns the BD OUT
	{
		if (MSD_State==MSD_WAIT) {
			gblCBW.dCBWSignature=msd_cbw.dCBWSignature;				// copy the received cbw into the gblCBW
			gblCBW.dCBWTag=msd_cbw.dCBWTag;
			gblCBW.dCBWDataTransferLength=msd_cbw.dCBWDataTransferLength;
    		gblCBW.bCBWFlags=msd_cbw.bCBWFlags;
    		gblCBW.bCBWLUN=msd_cbw.bCBWLUN;
	    	gblCBW.bCBWCBLength=msd_cbw.bCBWCBLength;				// Here most significant 3bits are zero
    		for (i=0;i<msd_cbw.bCBWCBLength;i++)
    			gblCBW.CBWCB[i]=msd_cbw.CBWCB[i];
	    	gblCBWLength=MSD_BD_OUT.Cnt;							// Length of command block wrapper	
			mUSBBufferReady(MSD_BD_OUT);							// call after every read or write on nonEP0 EP,
																			// toggles DTS and gives ownership to SIE
			USBDriverService();										// clears the TRNIF					
	    	if (isValidCBW()) {
				if (isMeaningfulCBW()) {
					prepareCSWData();
					if (gblCBW.bCBWFlags==0x80)
						MSD_State=MSD_DATA_IN;
					else if (gblCBW.bCBWFlags==0x00) {
						// prepare to read data in msd_buffer
						MSD_BD_OUT.Cnt=MSD_OUT_EP_SIZE;
    					MSD_BD_OUT.ADR=(byte*)&msd_buffer[0];
    					dataLen=0x0;
    					ptrNextData=(byte*)&msd_buffer[0];
						MSD_State=MSD_DATA_OUT;
					}
					// do this before because we may read data in write command

					MSDCommandHandler();									// decode and process the CBW
					
					// If dCBWDataTransferLength=0&&dCSWDataResidue!=0 dCSWStatus=0x02
					// else nothing go to data transfer state
					
					
				} else {	// else of isMeaningfulCBW
					;
					// Stall EP1 ??
				}
					
			} else {  // else of isValidCBW
				;
				// Stall EP1
			}
		
		} 
	}
	
}

	
void MSDCommandHandler(void)		// In reality it is to read from EP1
{	
	switch(gblCBW.CBWCB[0]) {
    	case INQUIRY:
        	MSDInquiryHandler();
        break;
        /* case READ_FORMAT_CAPACITY:				// will be handled in default case, whenever upsupported command is received
            MSDReadFormatCapacityHandler();
        break;*/        	
        case READ_CAPACITY:
		    MSDReadCapacityHandler();            
        break;
		case READ_10:
        	MSDReadHandler();
	    break;
    	case WRITE_10:
    	   	MSDWriteHandler();
		break;
        case REQUEST_SENSE:
		   	MSDRequestSenseHandler();
        break;
	    case MODE_SENSE:
	    	MSDModeSenseHandler();
    	break;
		case PREVENT_ALLOW_MEDIUM_REMOVAL:
		   	MSDMediumRemovalHandler();
        break;
		case TEST_UNIT_READY:
		   	MSDTestUnitReadyHandler();
        break;
		case VERIFY:
		   	MSDVerifyHandler();
        break;
		case STOP_START:
		   	MSDStopStartHandler();
        break;
		default:
        	ResetSenseData();
			gblSenseData.SenseKey=S_ILLEGAL_REQUEST;
			gblSenseData.ASC=ASC_INVALID_COMMAND_OPCODE;
			gblSenseData.ASCQ=ASCQ_INVALID_COMMAND_OPCODE;
			msd_csw.bCSWStatus=0x01;
			msd_csw.dCSWDataResidue=0x00;
 		break;
	} // end switch	
	// MSD_State=MSD_WAIT;
	ptrNextData=(byte*)&msd_buffer[0];
}

byte isValidCBW() 
{
	if ((gblCBWLength!=0x1f)||(gblCBW.dCBWSignature!=0x43425355)) return FALSE;
	else return TRUE;
}

byte isMeaningfulCBW()
{
	// 3msb bits of CBWCBLength are reserved and must be 0, 4msb bits of CBWLUN	are reserved and must be 0		
	// valid CBWCBLength is between 1 and 16B
	// flags only msb indicates data direction rest must be 0
	if ((gblCBW.bCBWLUN<=0x0f)&&(gblCBW.bCBWCBLength<=0x10)&&(gblCBW.bCBWCBLength>=0x01)&&(gblCBW.bCBWFlags==0x00|gblCBW.bCBWFlags==0x80)) 
		return TRUE;
	else return FALSE;	
	
}
		
void prepareCSWData()
{
	// prepare the tag and signature. 
	// Residue and Status we will get after decoding and executing the command
	msd_csw.dCSWTag=gblCBW.dCBWTag;
	msd_csw.dCSWSignature=0x53425355;
}

void MSDInquiryHandler(void)
{
	byte i;
	byte *buffer;

⌨️ 快捷键说明

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