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

📄 msd-b.c

📁 PIC18F4550 SD CARD USB
💻 C
字号:
/** I N C L U D E S **********************************************************/
#include <p18cxxx.h>
#include "system\typedefs.h"
#include "system\usb\usb.h"
#include "io_cfg.h"             // I/O pin mapping
#include<string.h>
//#ifndef MSD_H
//#include "system\usb\class\msd\msd.h"

#ifdef USB_USE_MSD
#define mLED_Both_On()          {mLED_2_On();mLED_3_On();}

extern SDC_Error RMediaInitialize(SDCSTATE*);
extern SDC_Error sdcardinitialize(void);
extern SDC_Error MediaInitialize();

// Global Variable for keeping state of the MSD firmware
byte MSD_State;
USB_MSD_CBW gblCBW;
byte gblCBWLength;
SDCSTATE gblFlag;
/*typedef struct 
{
	unsigned Peripheral_Qualifier:3;
	unsigned Peripheral_DevType:5;
	unsigned RMB:1;						// removable medium bit = 0 means non removable;
	unsigned Resv:7;					// reserved
	byte version;						// version
	unsigned Obsl:2;					//	obsolete			
	unsigned NormACA:1;					// Access control co-ordinator
	unsigned HiSup:1;					// Hierarchical addressing support
	unsigned Response_Data_Format:4;	// 02 indicates response is in format defined by spec
	byte AdditionalLength;				// length in bytes of remaining in standard inquiry data
	unsigned SCCS:1;					// =1 means SCSI target device has embedded storage component
	unsigned ACC:1;						// access controls co-ordinator
	unsigned TGPS:2;					// target group port support 
	unsigned THPC:1;					// third party copy =1 means dev supports 3rd party copy commands e.g. extended write
	unsigned Reserved:2;			
	unsigned Protect:1;					// protection information
	unsigned BQUE:1;					// with CMD queue to indicate full or basic task management model
	unsigned EncServ:1;					// enclosure service
	unsigned VS:1;						
	unsigned multip:1;					// multiport
	unsigned MChngr:1;					// medium changer command to control attached media changer
	unsigned Obs:2;						
	unsigned Addr16:1;					// specific to SPI-5 SCSI parallel interface
	unsigned obslo:2;
	unsigned wbus16:1;					// specific to SPI-5
	unsigned sync:1;					// specific to SPI-5
	unsigned linked:1;					// support of linked command (SAM-3)
	unsigned ob:1;	
	unsigned cmdque:1;					// task management model
	unsigned vs:1;
	char vendorID[8];	
	char productID[16];
	char productRev[4];
} InquiryResponse;*/

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);
    //status=sdcardinitialize();
    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)
{
	
	//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();
	    	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 ProcessIO(void)
{
	byte i;
	if(!MSD_BD_OUT.Stat.UOWN)
	{
		
		if (MSD_State==MSD_DATA_IN) {
			mLED_1_On();mLED_2_On();mLED_3_On();mLED_4_On();
		}
		if (MSD_State==MSD_DATA_OUT) {
			mLED_1On();mLED2_On();mLED_3_On();mLED_4_On();
		}
		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.CB.CBWCB[i]=msd_cbw.CB.CBWCB[i];
	    	gblCBWLength=MSD_BD_OUT.Cnt;							// Length of command block wrapper	
			MSDCommandHandler();										// decode and process the CBW
			mUSBBufferReady(MSD_BD_OUT);							// call after every read or write on nonEP0 EP,
																	// toggles DTS and gives ownership to SIE
			USBDriverService();										// clears the TRNIF
		} 
	}
}

	
void MSDCommandHandler(void)		// In reality it is to read from EP1
{	
	if (isValidCBW()) {
		if (isMeaningfulCBW()) {
			prepareCSWData();
			if (gblCBW.bCBWFlags==0x80)
				MSD_State=MSD_DATA_IN;
			else if (gblCBW.bCBWFlags==0x00)
				MSD_State=MSD_DATA_OUT;
			switch(msd_cbw.CB.Opcode) {
        		case INQUIRY:
        			MSDInquiryHandler();
            	break;
        		case READ_FORMAT_CAPACITY:
        		    MSDReadFormattedCapacityHandler();
        		break;        	
        		case READ_CAPACITY:
		            MSDReadCapacityHandler();            
        	    break;
		        case READ:
        			MSDReadHandler();
	            break;
    		    case WRITE:
		            break;
        		case REQUEST_SENSE:
		        	RequestSenseHandler();
        	    break;
	        	case MODE_SENSE:
    	 	       break;
		        case PREVENT_ALLOW_MEDIUM_REMOVAL:
        			break;
		        case TEST_UNIT_READY:
        			break;
		        case VERIFY:
        			break;
		        case STOP_START:
        			break;
        			/*
		        default:
        			while(mMSDTxIsBusy());
					MSD_BD_IN.ADR=(byte*)&msd_buffer;
					MSD_BD_IN.Cnt=0x0;
					mUSBBufferReady(MSD_BD_IN);
					USBDriverService();
		        	MSDErrorCSW();
        			break;
        			*/
			} // end switch
		} // end isMeaningfulCBW
	} // end isValidCBW
	MSD_State=MSD_WAIT;
}

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()
{
	msd_csw.dCSWTag=gblCBW.dCBWTag;
	msd_csw.dCSWSignature=0x53425355;
}


void RequestSenseHandler(void)
{
	byte i;
	for(i=0;i<18;i++)
		msd_buffer[i]=0;
	msd_buffer[0]=0xf0;
	msd_buffer[2]=0x05;
	msd_buffer[7]=0x0a;
	msd_buffer[12]=0x20;
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_buffer;
	MSD_BD_IN.Cnt=0x12;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	MSDSuccessCSW(0x00);
}
void MSDReadFormattedCapacityHandler(void)
{
	
    //mLED_4_On();
    /*
    msd_csw.dCSWTag=msd_cbw.dCBWTag;
	msd_csw.dCSWSignature=0x53425355;
	msd_csw.dCSWDataResidue=msd_cbw.dCBWDataTransferLength;
	msd_csw.bCSWStatus=0x1;
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_csw;
	MSD_BD_IN.Cnt=0x0;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_csw;
	MSD_BD_IN.Cnt=0x0;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	return;
	*/
	msd_buffer[0]=0x01;		// No of LBAs 246,016 from SD Card manual Page 3-24
	msd_buffer[1]=0x02;
	msd_buffer[2]=0x03;
	msd_buffer[3]=0x04;
	msd_buffer[4]=0x05;		// Block size 512 bytes = 200h
	msd_buffer[5]=0x06;
	msd_buffer[6]=0x07;
	msd_buffer[7]=0x08;
	msd_buffer[8]=0x09;		// Block size 512 bytes = 200h
	msd_buffer[9]=0x10;
	msd_buffer[10]=0x11;
	msd_buffer[11]=0x12;
	while(mMSDTxIsBusy());
    MSD_BD_IN.ADR=(byte*)&msd_buffer[0];
	MSD_BD_IN.Cnt=0x40;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_buffer[64];
	MSD_BD_IN.Cnt=0x40;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_buffer[128];
	MSD_BD_IN.Cnt=0x40;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_buffer[192];
	MSD_BD_IN.Cnt=0x3c;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	MSDSuccessCSW(0x00);
}

void MSDInquiryHandler(void)
{
	byte i;
	byte *buffer;
	memcpypgm2ram((byte *)&msd_buffer[0],(byte *)&inq_resp,sizeof(InquiryResponse));
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_buffer[0];
	MSD_BD_IN.Cnt=0x24;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	MSDSuccessCSW(msd_cbw.dCBWDataTransferLength-0x24);
}

void MSDReadCapacityHandler()
{
	msd_buffer[0]=0x03;		// No of LBAs 246,016 from SD Card manual Page 3-24
	msd_buffer[1]=0x00;
	msd_buffer[2]=0x00;
	msd_buffer[3]=0x00;
	msd_buffer[4]=0x00;		// Block size 512 bytes = 200h
	msd_buffer[5]=0x00;
	msd_buffer[6]=0x02;
	msd_buffer[7]=0x00;
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_buffer[0];
	MSD_BD_IN.Cnt=0x08;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	MSDSuccessCSW(0x00);
}

void MSDReadHandler()
{
	word i;
	SDC_Error status;
	status=RMediaInitialize(&gblFlag);						// media initialize reads the first sector in msd_buffer
	if (status) {mLED_1_On();mLED_2_On();mLED_3_On();mLED_4_On(); return;}
	//status =SECTORread(0L, (byte*)&msd_buffer[0]);
	//if (status) {mLED_1_On();mLED_2_On();mLED_3_On();mLED_4_On(); return;}
    while(mMSDTxIsBusy());
    MSD_BD_IN.ADR=(byte*)&msd_buffer[0];
	MSD_BD_IN.Cnt=0x40;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_buffer[64];
	MSD_BD_IN.Cnt=0x40;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_buffer[128];
	MSD_BD_IN.Cnt=0x40;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_buffer[192];
	MSD_BD_IN.Cnt=0x40;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	while(mMSDTxIsBusy());
    MSD_BD_IN.ADR=(byte*)&msd_buffer[256];
	MSD_BD_IN.Cnt=0x40;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	while(mMSDTxIsBusy());
    MSD_BD_IN.ADR=(byte*)&msd_buffer[320];
	MSD_BD_IN.Cnt=0x40;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	while(mMSDTxIsBusy());
    MSD_BD_IN.ADR=(byte*)&msd_buffer[384];
	MSD_BD_IN.Cnt=0x40;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	while(mMSDTxIsBusy());
    MSD_BD_IN.ADR=(byte*)&msd_buffer[448];
	MSD_BD_IN.Cnt=0x40;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
	MSDSuccessCSW(0x00);
	mLED_4_On();
}
void MSDSuccessCSW(dword residue)
{	
	//mLED_Both_On();
	//msd_cbw_csw.dCSWTag=msd_cbw_csw.dCBWTag;
	//msd_cbw_csw.dCSWSignature._dword=0x53425355;
	//msd_cbw_csw.dCSWDataResidue._dword = 0x0;
	//msd_cbw_csw.bCSWStatus._byte=0x0;
	msd_csw.dCSWTag=msd_cbw.dCBWTag;
	msd_csw.dCSWSignature=0x53425355;
	msd_csw.dCSWDataResidue = residue;
	msd_csw.bCSWStatus=0x0;
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_csw;
	MSD_BD_IN.Cnt=0x0d;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
}

void MSDErrorCSW(void)
{	
	//mLED_1_On();
	msd_csw.dCSWTag=msd_cbw.dCBWTag;
	msd_csw.dCSWSignature=0x53425355;
	msd_csw.dCSWDataResidue=msd_cbw.dCBWDataTransferLength;
	msd_csw.bCSWStatus=0x1;
	while(mMSDTxIsBusy());
	MSD_BD_IN.ADR=(byte*)&msd_csw;
	MSD_BD_IN.Cnt=0x0d;
	mUSBBufferReady(MSD_BD_IN);
	USBDriverService();
}
	
void MSDInHandler(void)
{
	return;	
}

void MSDTxPkt(char *buffer, byte len)
{
	byte i;
    /*
     * Value of len should be equal to or smaller than MSD_INT_IN_EP_SIZE.
     * This check forces the value of len to meet the precondition.
     */
	if(len > MSD_IN_EP_SIZE)
	    len = MSD_IN_EP_SIZE;

   /*
    * Copy data from user's buffer to dual-ram buffer
    */
    for (i = 0; i < len; i++)
    	msd_buffer[i] = buffer[i];
	MSD_BD_IN.ADR=(byte*)&msd_buffer;
    MSD_BD_IN.Cnt = len;
    mUSBBufferReady(MSD_BD_IN);

}//end MSDTxPkt

void MSDInitEP(void)
{   
	mInitAllLEDs();
    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|_DAT0|_DTSEN;	//usbmmap.h owner SIE, DAT0 expected next, data toggle sunc enable
   
    /*
     * Do not have to init Cnt of IN pipes here.
     * Reason:  Number of bytes to send to the host
     *          varies from one transaction to
     *          another. Cnt should equal the exact
     *          number of bytes to transmit for
     *          a given IN transaction.
     *          This number of bytes will only
     *          be known right before the data is
     *          sent.
     */
    MSD_BD_IN.ADR = (byte*)&msd_buffer[0];      // Set buffer address    
    MSD_BD_IN.Stat._byte = _UCPU|_DAT1;   // Set status CPU owns Data1 expected next
    MSD_State=MSD_WAIT;
    
}//end MSDInitEP

⌨️ 快捷键说明

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