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

📄 bulkcmd.c

📁 SdCard_V2.1TinyFatFs.rar是单片机实现SD卡功能的FAT文件系统
💻 C
字号:
/*
**********************************************************************************************
* Project:	FS7805 SD CARD READER
* File:		main.c
* Contents: 
*           The main function is SD and MMC card reader.
*
* $Date: 12/15/06    Derek    V1.0  
*  
* Coments: This is the SD/MMC card reader firmware.
*		   When read sector,the 512 pingpong FIFO mechanism
*		   is used to improve performance.But when write sector,
*		   only single FIFO is used.
*
* Copyright (c) 2006 Fameg, Inc. All rights reserved
*
* 
***********************************************************************************************
*/
#include "include\Include.h"

/*************************************************
   Global Variables
*************************************************/
xdata PCMD_BLOCK_WRAPPER BlockWrapper;  
BYTE CmdStatus = COMMAND_PASSED;
BYTE BulkState = CBW_GET_COMPLETED;
bool ScsiCmdSTALLed = false;
BYTE ScsiLun;
xdata UINT32 SectorStart  = 0;
xdata UINT16 SectorCount    = 0;  
xdata UINT32 WrapperTag = 0;
xdata UINT32 UsbDmaTotalLength = 0;
bit FirstWrite = false;

extern bit BusResetFlag ;

/*************************************************
   Local Variables
*************************************************/
static bit BulkCmdRunning = false;
/*************************************************
   For pingpong FIFO control
*************************************************/
volatile BYTE    SW_IN_FIFO_Toggle = 0;
volatile INT16U  FIFO_ADDRESS_IN;
volatile BYTE    SW_OUT_FIFO_Toggle = 0;
volatile INT16U  FIFO_ADDRESS_OUT;

/*
*********************************************************************************************************
*                                             BulkFreeBuffer()
*
* Description: Clear FIFO_FULL bit that get data,set FIFO_TOG and 
*				and SW_OUT_FIFO_Toggle value for next OUT transaction.
*
* Arguments  : none
*
* Returns    : none
*********************************************************************************************************
*/
void BulkFreeBuffer(void)
{
	if(FIFO_ADDRESS_OUT    == DMA_FIFOA0)//if data in DMA_FIFOA0
    {
		EPAFIFOCS = (EPAFIFOCS | bmFIFO_TOG_WE) | (bmFIFO_TOG);//set FIFO_TOG
        EPAFIFOCS = (EPAFIFOCS | bmFIFO0_FULL_WE) & (~bmFIFO0_FULL);//clear FIFO0_FULL bit
		SW_OUT_FIFO_Toggle = 1;//set SW_OUT_FIFO_Toggle value
    }
    else                // FULL_1 = 1
    {
		EPAFIFOCS = (EPAFIFOCS | bmFIFO_TOG_WE) & (~bmFIFO_TOG);//
        EPAFIFOCS = (EPAFIFOCS | bmFIFO1_FULL_WE) & (~bmFIFO1_FULL);
		SW_OUT_FIFO_Toggle = 0;
    }

  	BulkSetDmaOut();
}
//----------------------------------------------------------------------------
// Wait OUT Packet.
//----------------------------------------------------------------------------
void BulkWaitOutDataReady() //
{
  while (1)
  {
    while ((EPINT & bmEPAINT) == 0);	
    // Clear OUT IRQ.
    EPINT&=~bmEPAINT;
    if (!BulkOutTogErr())
      break;  
  }  
}	

//----------------------------------------------------------------------------
void BulkReportHandle()
{
  	if (BulkCmdRunning) 
	{
    	BulkPrepareCSW(CmdStatus);
	}
}

#pragma OPTIMIZE(4)
/*
*********************************************************************************************************
*                                     BulkSetDmaIn()
*
* Description: Send data to host.
*
* Arguments  : DmaLen,IN packet length.
*
* Returns    : none
*********************************************************************************************************
*/
void BulkSetDmaIn(UINT16 DmaLen)
{	 
    if (FIFO_ADDRESS_IN == DMA_FIFOB0)//If DMA_FIFOB0 is selected.
    {
		EPBFIFOCS   = (EPBFIFOCS | bmFIFO0_FULL_WE) | bmFIFO0_FULL;//2007.01.09
    	EPBCNT0L    = DmaLen & 0xFF;                       // Write count low byte
    	EPBCNTH     = (DmaLen >> 8) | bmCNT0HWEN;          // Write count high byte
		SW_IN_FIFO_Toggle = 1;
    }
    else
    {
		EPBFIFOCS   = (EPBFIFOCS | bmFIFO1_FULL_WE) | bmFIFO1_FULL;//2007.01.09
    	EPBCNT1L    = DmaLen & 0xFF;                       // Write count low byte
    	EPBCNTH     = ((DmaLen >> 8) << 4) | bmCNT1HWEN;   // Write count high byte
		SW_IN_FIFO_Toggle = 0;
    }

    EPBCS       = EPBCS | bmEP_RXTXEN;  // Enable RXTX

}
//------------------------------------
//
//------------------------------------
void SelectInFifo(void)
{
    if ((!(EPBFIFOCS & bmFIFO0_FULL)) && (!(EPBFIFOCS & bmFIFO1_FULL)))
    {
        if (SW_IN_FIFO_Toggle==0)//根据软件toggle位来判断从哪个FIFO 取数据。
        {
            FIFO_ADDRESS_IN= DMA_FIFOB0;
        }
        else
        {
            FIFO_ADDRESS_IN= DMA_FIFOB1;
        }
    }
    else if (!(EPBFIFOCS & bmFIFO0_FULL))
    {
        FIFO_ADDRESS_IN= DMA_FIFOB0;
    }
    else if (!(EPBFIFOCS & bmFIFO1_FULL))
    {
        FIFO_ADDRESS_IN= DMA_FIFOB1;
    }
}
//----------------------------------------------------------------------------
// Description: Select one of PINGPONG FIFOS for IN transaction.
//
//----------------------------------------------------------------------------
void  SetBulkInFull (void)
{
    while ((EPBFIFOCS & bmFIFO0_FULL) && (EPBFIFOCS & bmFIFO1_FULL));
	SelectInFifo();//
}

//----------------------------------------------------------------------------
// Description: 专门处理读扇区,对bus reset做了特别处理.
//
//----------------------------------------------------------------------------
void SetBulkInFullForReadSector(void)
{
    while ((EPBFIFOCS&bmFIFO0_FULL)&&(EPBFIFOCS & bmFIFO1_FULL)&&((STINT&bmUSBRSTINT)==0));
//等待至少一个FIFO_FULL为0,或者BUS RESET的发生~!2007.01.22
	if(STINT&bmUSBRSTINT) {
		BusResetDeal();
		BusResetFlagCnt = 1;
		return;
	}
	SelectInFifo();//
}
//----------------------------------------------------------------------------
// Description: Check which one of PINGPONG FIFOS the OUT packet is in.
//
//----------------------------------------------------------------------------
void SelectOutFifo(void)
{
	if ((EPAFIFOCS & bmFIFO0_FULL) && (EPAFIFOCS & bmFIFO1_FULL))
    {                                        // FULL_0 = 1 and FULL_1 = 1
        if (SW_OUT_FIFO_Toggle == 0)//如果两个FULL位都是1,根据软件toggle位判断.
        {
            FIFO_ADDRESS_OUT    = DMA_FIFOA0;
        }
        else
        {
            FIFO_ADDRESS_OUT    = DMA_FIFOA1;
        }
    }
    else if (EPAFIFOCS & bmFIFO0_FULL)      // FULL_0 = 1
    {
        FIFO_ADDRESS_OUT    = DMA_FIFOA0;
    }
    else if (EPAFIFOCS & bmFIFO1_FULL)      // FULL_1 = 1
    {
        FIFO_ADDRESS_OUT    = DMA_FIFOA1;
    }

}
#pragma OPTIMIZE(4)
//----------------------------------------------------------------------------
// Prepare CSW
//----------------------------------------------------------------------------
void BulkPrepareCSW(BYTE Status)
{
  PCMD_STATUS_WRAPPER StatusWrapper;
     
  BulkCmdRunning = false;

  SetBulkInFull();

  StatusWrapper = (CMD_STATUS_WRAPPER xdata *)(FIFO_ADDRESS_IN);
  // 1. Set CSW. 
  StatusWrapper->Sign = CSW_SIGNATURE;
  StatusWrapper->Tag  = WrapperTag;
  StatusWrapper->DataResidueLen = 0; 
  StatusWrapper->Status = Status;
  // 2. Set DMA related parameters and enable.
  BulkSetDmaIn(CSW_LENGTH);
  // 3. Wait for replying CSW.
  BulkState = CSW_REPLY_COMPLETED;

}

//----------------------------------------------------------------------------
void InitBulkPipe()
{
  BulkState = CBW_GET_COMPLETED;    
  CmdStatus = COMMAND_PASSED;

  // Init Scsi Used Params.
  ScsiInit();
}  

//----------------------------------------------------------------------------
void UsbBulkIntHandler(BYTE IntEvent)
{
    STATUS Status;
    bool GoodCBW = true;	
    UINT16 CmdLen;

    if(IntEvent & bmEPAINT)
	{
		if(BusResetFlag)//如果有bus reset发生
		{     
			//BulkState = CBW_GET_COMPLETED;    
	        //CmdStatus = COMMAND_PASSED;

			Status = SdStopCmd();
			SdCtrlReset();
			BusResetFlag = false;
		} 
	}
  
  	switch (BulkState)
	{
        case CBW_GET_COMPLETED:
        case CSW_REPLY_COMPLETED:

            BulkState = CBW_GET_COMPLETED;

            if((IntEvent & bmEPAINT)==0) //
            {
				break;
			 }
			SelectOutFifo();//Derek 12.26
			if(FIFO_ADDRESS_OUT == DMA_FIFOA0) 
			{ //Derek 12.26
				((TDataCast *)&CmdLen)->ucByte[0]   = EPACNTH & 0x07;
            	((TDataCast *)&CmdLen)->ucByte[1]   = EPACNT0L;
			} else {
				((TDataCast *)&CmdLen)->ucByte[0]   = (EPACNTH & 0x70) >> 4;
                ((TDataCast *)&CmdLen)->ucByte[1]   = EPACNT1L;
			}
	        
			if(BulkOutTogErr())	//是否发生DATA toggle错误
            {
                BulkFreeBuffer();
				break;
            }

            if((CmdLen != CBW_LENGTH) && 		 //CBW必须是31或32字节
               (CmdLen != CBW_LENGTH_98))
            {
                BulkFreeBuffer();
				break;
            }

            BulkCmdRunning = true;
            ScsiCheckCmd();   
  
            break;
    
        case BULK_DMA_IN_COMPLETED:   

            if((IntEvent & bmEPBINT) == 0)
                break;

            if(SectorCount == 0)		   
            {
                BulkPrepareCSW(CmdStatus);
            }
            else
            {	
                Status = ReadNextSector();

                if(Status != STATUS_SUCCESS)
                {
                    CmdStatus = COMMAND_FAILED;	
                    SetSenseDataRd(Status);
                    BulkInStall();
                    BulkState = STALL_IN_COMPLETED;
                }
            }
            break;

        case BULK_DMA_OUT_COMPLETED:

            if((IntEvent & bmEPAINT) == 0)
                break;

            Status = STATUS_SUCCESS;

		   if(BulkOutTogErr())
            {
				SelectOutFifo();//SelectOutfifo()和BulkFreeBuffer配对使用!切记!
                BulkFreeBuffer();	           
                break;
            }

            if(ScsiDetectWriteProtect(ScsiLun))
            {
                Status = STATUS_WRITE_PROTECT;
                CmdStatus = COMMAND_FAILED; 
				SelectOutFifo();//SelectOutfifo()和BulkFreeBuffer配对使用!切记!
				BulkFreeBuffer(); 
            }
            else
            {
                if(FirstWrite)
                {
                    Status = WriteSector();
                    FirstWrite = false;
                }
                else
                    Status = WriteNextSector();

            }

            if(Status != STATUS_SUCCESS)
            {
                 CmdStatus = COMMAND_FAILED;
                 SetSenseDataWr(Status);
	             BulkInStall();
                 BulkState = STALL_IN_COMPLETED; 
                 break;   	
            }

            if(SectorCount == 0)
                BulkPrepareCSW(CmdStatus);
            break;           
  
        case STALL_IN_COMPLETED: 	   //读写过程有错后,进入此状态
            if (IntEvent & bmEPAINT)   // Keep receving out packets.
            {	SelectOutFifo();		//SelectOutfifo()和BulkFreeBuffer配对使用!切记!
                BulkFreeBuffer();		//Derek 2007.01.11
            }			 
            if(EPBCS & bmTX0_SESTALL)   //如果IN EP的STALL位被置1
            {
                if(CmdStatus == PHASE_ERROR)
                    CmdStatus = COMMAND_PASSED; 

                BulkState = CBW_GET_COMPLETED; 

                ScsiCmdSTALLed = true;	//STALL标志变量置1
                
                // Set RXTXEN to receive next OUT packet.
                if(!(EPACS & bmEP_RXTXEN))
                    BulkSetDmaOut(); //允许OUT 端点再次接收数据,为下次传输做准备
            } 
            break;  
   
        default:
            BulkInStall();
            BulkState = STALL_IN_COMPLETED;    	 
            break;   
    }  
}
//-----------------------
//用作BUS RESET后的处理
//-----------------------
void BusResetDeal(void)//2007.01.22
{
	STINT   = STINT & (~bmUSBRSTINT);
    while (!(USBGCTRL & bmHS_DETECTED));           // detect USB speed
    HighSpeed       = USBGCTRL & bmSPEED;          // High speed
	//无论低速高速,reset后都要将FIFO_TOGGLE位清零。
	if (HighSpeed)
	{
		EPAFIFOCS = 0xF0;				//06.08.28
		EPBFIFOCS = 0xF0;				//06.08.28
	}else 
	{ //如果是低速主机接口-06.08.28//Derek
		EPAFIFOCS = 0xF2;				//06.08.28
		EPBFIFOCS = 0xF2;				//06.08.28
	} 
	SW_RST |= bmUSB_RST;	//USB software reset Derek 10.23
	UsbInit();				//重新配置端点属性
	BusResetFlag = true;    //Derek 09.06
	SW_IN_FIFO_Toggle  = 0; //12.29 software toggle bit reset
	SW_OUT_FIFO_Toggle = 0;
}  

⌨️ 快捷键说明

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