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

📄 msd.c

📁 PIC18F4550 SD CARD USB
💻 C
📖 第 1 页 / 共 3 页
字号:
/*********************************************************************
 *
 *             Microchip USB C18 Firmware -  MSD Version 1.0
 *
 *********************************************************************
 * FileName:        msd.c
 * Dependencies:    See INCLUDES section below
 * Processor:       PIC18
 * Compiler:        C18 2.40
 * Company:         Microchip Technology, Inc.
 *
 * Software License Agreement
 *
 * The software supplied herewith by Microchip Technology Incorporated
 * (the 揅ompany? for its PICmicro?Microcontroller is intended and
 * supplied to you, the Company抯 customer, for use solely and
 * exclusively on Microchip PICmicro Microcontroller products. The
 * software is owned by the Company and/or its supplier, and is
 * protected under applicable copyright laws. All rights are reserved.
 * Any use in violation of the foregoing restrictions may subject the
 * user to criminal sanctions under applicable laws, as well as to
 * civil liability for the breach of the terms and conditions of this
 * license.
 *
 * THIS SOFTWARE IS PROVIDED IN AN 揂S IS?CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 * Author               Date        Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Gurinder Singh       05/31/05    Original.
 ********************************************************************/
 
/** I N C L U D E S **************************************************/
#include <p18cxxx.h>
#include "system\typedefs.h"
#include "system\usb\usb.h"
#include<string.h>

#ifdef USB_USE_MSD

/** V A R I A B L E S ************************************************/
#pragma udata
byte MSD_State;			// Takes values MSD_WAIT, MSD_DATA_IN or MSD_DATA_OUT
USB_MSD_CBW gblCBW;	
byte gblCBWLength;
SDCSTATE gblFlag;
RequestSenseResponse gblSenseData;
byte *ptrNextData;
/* 
 * Number of Blocks and Block Length are global because 
 * for every READ_10 and WRITE_10 command need to verify if the last LBA 
 * is less than gblNumBLKS	
 */	
DWORD gblNumBLKS=0x00,gblBLKLen=0x00;	

/* Standard Response to INQUIRY command stored in ROM 	*/
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",	// this is the T10 assigned Vendor ID
	"Mass Storage    ",
	"0001"
};

/** P R I V A T E  P R O T O T Y P E S ***************************************/

void MSDCommandHandler(void);
void MSDInquiryHandler(void);
void MSDReadCapacityHandler(void);
void MSDReadHandler(void);
void MSDWriteHandler(void);
void MSDModeSenseHandler(void);
void MSDMediumRemovalHandler(void);
void MSDRequestSenseHandler(void);
void MSDTestUnitReadyHandler(void);
void MSDVerifyHandler(void);
void MSDStopStartHandler(void);
byte IsMeaningfulCBW(void);
byte IsValidCBW(void);
void PrepareCSWData(void);
void SendData(byte*, byte);
void SendCSW(void);
void ResetSenseData(void);
void MSDDataIn(void);
void MSDDataOut(void);

extern SDC_Error MediaInitialize(SDCSTATE*);
extern void SocketInitialize(void);
extern SDC_Error SectorRead(dword, byte*);
extern SDC_Error SectorWrite(dword, byte*);
extern SDC_Error CSDRead(void);
extern int DetectSDCard (void);
extern byte IsWriteProtected(void);

/** D E C L A R A T I O N S **************************************************/
#pragma code

/** C L A S S  S P E C I F I C  R E Q ****************************************/


/******************************************************************************
 * 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 received on the control endpoint EP0
 *
 * Note:            None
 *****************************************************************************/	
void USBCheckMSDRequest(void)
{
	switch(SetupPkt.bRequest)
    {
	    case MSD_RESET:
	    	ctrl_trf_session_owner = MUID_MSD;
	    	mDisableEP1to15();                          // See usbdrv.h
	    	if (UEP1bits.EPSTALL==1) {
	 			UEP1bits.EPSTALL = 0;
	    		MSDInitEP();
	    	}
			UIRbits.STALLIF = 0;
	   	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)
}
/******************************************************************************
 * Function:        void ProcessIO(void)
 *
 * PreCondition:    MSDInitEP() and SDCardInit() have beed called.
 *		    MSDInitEP() is called from USBStdSetCfgHandler(void)(usb9.c)
 *		    SDCardInit() is called from InitializeSystem() in main.c
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This routine is called in continuous loop from main.c
 *		    All the Bulk Transport Commands on EndPoint 1 are
 *                  handled here. MSD_State holds the current state of the
 *                  Mass Storage Module.
 *		    In MSD_WAIT State - Wait for a Command Block Wrapper (CBW)
 *                  on EP1. If a valid and meaningful CBW is received,
 *		    depending on the command received MSD_State is changed to 
 *		    MSD_DATA_IN if data is to be sent to host (for all commands
 *                  other than WRITE_10)
 *                  MSD_DATA_OUT if host is expected to send data (only in case
 *                  of WRITE_10). At the end of Data Transfer Command Status
 *                  Wrapper (CSW) is sent by calling SendCSW()
 *
 * Note:            None
 *****************************************************************************/	
void ProcessIO(void)
{
	byte i;
	dword size;

    if((usb_device_state < CONFIGURED_STATE)||(UCONbits.SUSPND==1)) return;

	if (MSD_State==MSD_DATA_IN) {
		/* Send Data to Host */	
		if(gblCBW.dCBWDataTransferLength==0) 
		{
			/* Finished sending the data send the Status */
			/* SendCSW() send the csw and sets the state to wait */
			SendCSW(); 
			if ((msd_csw.bCSWStatus==0x00)&&(gblCBW.CBWCB[0]==INQUIRY)) {
				/* Turn on the MSD LED when we have successfully*/
                /*responded to the INQUIRY Command             */
        		STMSDLED=1;
			}
		}	
		else 
		{ 				
			/* Still have data to Send */
			MSDDataIn();
		}
		return;	
	}	
	if (MSD_State==MSD_DATA_OUT) {			
		/* Receive data from Host*/
		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
		}
		/*
		* Note that MSD_DATA_OUT State is reached only for the WRITE_10 COMMAND
		* Also note that this code is reached in MSD_DATA_OUT State only after
		*  we have read the required amount of data from the host
		* This procsssing is done in WriteCommandHandler because we have
		* limited buffer space. We read from host in 64Bytes chunks
		* (size of MSD_BD_OUT), fill the msd_buffer(512B) and write the
        *  data into the SDCard
		*/ 
		return;
	}
	if((MSD_BD_OUT.Stat.UOWN==_UCPU) && (MSD_State==MSD_WAIT)) {
		/* If the CPU owns the BD OUT (we)and the MSD_State is WAIT*/
		/* Copy the received cbw into the gblCBW */
		gblCBW.dCBWSignature=msd_cbw.dCBWSignature;					
		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;		// 3 MSB are zero
    	for (i=0;i<msd_cbw.bCBWCBLength;i++)
    		gblCBW.CBWCB[i]=msd_cbw.CBWCB[i];
	    gblCBWLength=MSD_BD_OUT.Cnt;				   // Length of CBW
	    	
		if (IsValidCBW()) {
			if (IsMeaningfulCBW()) {
				PrepareCSWData();
				/* If direction is device to host*/
				if (gblCBW.bCBWFlags==0x80)
					MSD_State=MSD_DATA_IN;
				else if (gblCBW.bCBWFlags==0x00) {
					/* If direction is host to device*/
					/* prepare to read data in msd_buffer */
					MSD_BD_OUT.Cnt=MSD_OUT_EP_SIZE;
    				MSD_BD_OUT.ADR=(byte*)&msd_buffer[0];
    				MSD_State=MSD_DATA_OUT;
				}
				/* Decode and process the valid and meaningful CBW received */
				MSDCommandHandler();									
			}
			/* NOTE:
			 * In case when the received CBW is not valid or meaningful,
             * one can take action  such as Stall the EP1 and go through reset
			 * recovery or turn on error LED etc.
			 */ 
		}
	   /* 
		* NOTE: Call after every read or write on nonEP0 EP 
	 	* Basically, toggles DTS and gives ownership to SIE
		*/
		mUSBBufferReady(MSD_BD_OUT);
		/* clears the TRNIF */
		USBDriverService();
	}
}

/******************************************************************************
 * Function:        void MSDInitEP(void)
 *
 * PreCondition:    None 
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This routine is called from USBStdSetCfgHandler(void)
 *                  Initializes the Bulk-In and Bulk-Out endpoints MSD_BD_IN
 *		    and MSD_BD_OUT Size = 64B (See usbmmap.c and
 *		    usbdefs_std_dsc.h for endpoint definitions)
 *
 * Note:            None
 *****************************************************************************/	
 
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 (size) 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
    
    
}//end MSDInitEP

/******************************************************************************
 * Function:        void SDCardInit(void)
 *
 * PreCondition:    None 
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    gblFlag is updated according to result of Intialization
 *                  MSD_State is set to MSD_WAIT 
 *
 * Overview:        This routine is called from InitializeSystem() in main.c
 *                  It initializes the SD card if there is some error in
 *                  initialization all the LEDs are turned ON.
 *                  Also, set the MSD_State = MSD_WAIT
 *
 * Note:            None
 *****************************************************************************/	
	
void SDCardInit(void) 
{
	SDC_Error status;
	SocketInitialize();
    mInitAllLEDs();
    status=MediaInitialize(&gblFlag);
    if (status) { 
	    /* If there was some error, turn on all leds */
	    mLED_1_On(); mLED_2_On(); mLED_3_On(); mLED_4_On();
	    gblFlag.isSDMMC=0;
	} else gblFlag.isSDMMC=1; 		
	MSD_State=MSD_WAIT;
 }    

/******************************************************************************
 * Function:        void MSDCommandHandler(void)
 *
 * PreCondition:    None 
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This routine is called from ProcessIO()
 *                  when the MSD_State = MSD_WAIT. This function decodes the CBW
 *                  Command and takes appropriate action.If the CBW command is
 *                  not supported the Sense Data is set, CSW status
 *                  is set to Command Failed (bCSWStatus=01h)
 *
 * Note:            None
 *****************************************************************************/	
	
void MSDCommandHandler(void)		// In reality it is to read from EP1
{	
	switch(gblCBW.CBWCB[0]) {
    	case INQUIRY:
        	MSDInquiryHandler();
        break;
        case READ_CAPACITY:

⌨️ 快捷键说明

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