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

📄 sdi2410.c

📁 HFAT32是我依据FAT标准,按照自己的理解写出来的一个FAT文件系统 特性: 1.HFAT32 是一个小型的嵌入式FAT文件系统,可以方便地在nand flash,RAM和SD Card
💻 C
📖 第 1 页 / 共 2 页
字号:
	int err, try;
	int i, start, end;
	
	if (sector == 0xFFFFFFFF)
	{
		start = 0; end = SDCARD_BUFFER_BLOCK_MAX;
	}
	else
	{
		S_DWORD cluster = (sector+sdcard.part[0].RelativeSec)/(sdcard.BlockLen/SDCARD_FAT_SECTOR_BYTES);
		for (i = 0; i < SDCARD_BUFFER_BLOCK_MAX; i++)
			if (SDCARDClst[i] == cluster)
				break;
		if (i == SDCARD_BUFFER_BLOCK_MAX)
			start = 0, end = 0;
		else
			start = i, end = i+1;
	}
	
	for (i = start; i < end; i++)
	{
		if ((SDCARDFlag[i]&SDCARD_BUFFER_NEEDFLUSH) == SDCARD_BUFFER_NEEDFLUSH)
		{
			try = 3;
			do
			{
				err = sdi_WriteBlock(SDCARDClst[i], SDCARDBuf[i]);
			}while (err && try--);
			if (err)
				return err;
			SDCARDFlag[i] &= ~SDCARD_BUFFER_NEEDFLUSH;
		}
		if (FreeBuffer)
		{
			SDCARDFlag[i] = 0x00;
			SDCARDClst[i] = 0xFFFFFFFF;
		}
	}
	return 0;
}

//sub function define
//
static int sdi_SDcardInit(void)
{
	int err;
	
    // Important notice for MMC test condition
    // Cmd & Data lines must be enabled pull up register
    hai_memset(&sdcard, 0x00, sizeof(sdcard));

    rSDIPRE    = PCLK/(2*SDI_INITIALCLK)-1;	// 400KHz
    rSDICON    = (1<<4)|(1<<1)|1;	// Type B, FIFO reset, clk enable
    rSDIBSIZE  = 0x200;		// 512byte(128word)
    rSDIDTIMER = 0xffff;		// Set timeout count

    for(err = 0; err < 0x1000; err++);  // Wait 74SDCLK for MMC card
	//CMD0: make idle
	if (err = sdi_SendCmd(SDICMD_GO_IDLE_STATE, 0))
		return err;
	//MMC=>CMD1;SD=>ACMD41: make ready
	if (!(err = sdi_ChkMMCOCR()))
		sdcard.CardType = SDT_MMC_CARD;
	else if (!(err = sdi_ChkSDOCR()))
		sdcard.CardType = SDT_SD_CARD;
	else
		return err;
	//CMD2: make identification
	if (err = sdi_MakeIdent())
		return err;
	//CMD3: make stand by
	if (sdcard.CardType == SDT_MMC_CARD)
		sdcard.RCA = 1;
	if (err = sdi_MakeStandby(&sdcard.RCA))//CMD3(MMC:Set RCA, SD:Ask RCA)
		return err;

	if (err = sdi_GetCID(sdcard.RCA, &sdcard.CID))
		return err;
	if (err = sdi_GetCSD(sdcard.RCA, &sdcard.CSD))
		return err;

	//normal clock
	rSDIPRE = PCLK/(2*SDI_NORMALCLK)-1;
	//CMD7: make transfer
	if (err = sdi_CardSelect(sdcard.RCA))
		return err;
	//ACMD6: set bus width
	if (sdcard.CardType != SDT_MMC_CARD)
	{
		sdcard.flag |= SD_BUSW_4BIT;
		if (err = sdi_SetBusWidth(sdcard.RCA, (sdcard.flag&SD_BUSW_MASK)?1:0))
			return err;
	}
	return 0;
}


static int sdi_SendCmd(int rCMD, int rARG)
{
	int state, err = -1;

	rSDICARG = rARG;
	rSDICCON = rCMD|SDICMD_START|SDICMD_HOST;
	
	if(rCMD&SDICMD_WTRSP)
	{
		do
		{
			state = rSDICSTA;
		}while(!((state&0x200)||(state&0x400)));    // Check cmd/rsp end
		
		if((rCMD&SDICMD_IDXMSK)==1 || (rCMD&SDICMD_IDXMSK)==9 || (rCMD&SDICMD_IDXMSK)==41)	// CRC no check
		{
			if((state&0xf00) != 0xa00)
			{
				if((state&0x400)==0x400)
					err = -1;	// Timeout error
			}
		}
		else
		{
			if((state&0x1f00) != 0xa00)
			{
				if((state&0x400)==0x400)
					err = -1;	// Timeout error
				else
					err = -2;	// crc fail
			}
		}
    }   
    else
	{
		do
		{
			state = rSDICSTA;
		}while((state&0x800)!=0x800);	// Check cmd end
    }

	rSDICSTA = state;// Clear cmd end state
	return err;
}

static int sdi_CMD55(S_WORD RCA)
{
	return sdi_SendCmd(SDICMD_WTRSP|SDICMD_APP_CMD, (int)RCA<<16);
}

static int sdi_ChkMMCOCR(void)
{
	int try;

	for(try = 0; try < 9; try++)
	{
		//0xffc000:(OCR:2.6V~3.6V)
		if (!sdi_SendCmd(SDICMD_S_RSP|SDICMD_WTRSP|SDICMD_OP_COND, 0xffc000))
		{
			if(rSDIRSP0 == 0x80ffc000) 
				return 0;	// Success
		}
	}
	return -1;
}

static int sdi_ChkSDOCR(void)
{
    int try, delay;

    for(try = 0; try < 9; try++)
    {
    	if (sdi_CMD55(0))    // Make ACMD
    		continue;
    	//0xff8000 : (OCR:2.7V~3.6V)
		if (!sdi_SendCmd(SDICMD_S_RSP|SDICMD_WTRSP|SDICMD_SD_APP_OP_COND, 0xff8000))
    	{
			if(rSDIRSP0 == 0x80ff8000) 
			    return 0;	// Success	    
		}
		for(delay = 0; delay < 1000; delay++); // Wait Card power up status
    }
	return -1;
}

static int sdi_MakeIdent(void)
{
	int err, try = 3;

	do
	{
		err = sdi_SendCmd(SDICMD_L_RSP|SDICMD_WTRSP|SDICMD_ALL_SEND_CID, 0);
	}while(err && try--);

	return err;
}

static int sdi_MakeStandby(S_WORD *pRCA)
{
	int err, try = 3, arg = (int)*pRCA;

	do
	{// CMD3(MMC:Set RCA, SD:Ask RCA-->SBZ)
		err = sdi_SendCmd(SDICMD_WTRSP|SDICMD_SEND_REL_ADDR, arg<<16);
	}while (err && try--);

	if (err)
		return err;

    if (*pRCA)//MMC
    	;
	else
		*pRCA = (rSDIRSP0&0xFFFF0000)>>16;

    if (rSDIRSP0&0x1e00 != 0x600)  //check if enter stand-by
		err = -1;

	return err;
}

static int sdi_GetCID(S_WORD RCA, SP_CID pCID)
{
	int err, try = 3, val;
	S_BYTE rsp[16];

	do
	{
		err = sdi_SendCmd(SDICMD_L_RSP|SDICMD_WTRSP|SDICMD_SEND_CID, (int)RCA<<16);
	}while(err && try--);
	
	if (err) return err;

	val = rSDIRSP0; HAI_WRITEDWORD(rsp+12, val);
	val = rSDIRSP1; HAI_WRITEDWORD(rsp+ 8, val);
	val = rSDIRSP2; HAI_WRITEDWORD(rsp+ 4, val);
	val = rSDIRSP3; HAI_WRITEDWORD(rsp+ 0, val);

	pCID->MID    = rsp[15];
	pCID->OID[1] = rsp[14];
	pCID->OID[0] = rsp[13];
	pCID->PNM[4] = rsp[12];
	pCID->PNM[3] = rsp[11];
	pCID->PNM[2] = rsp[10];
	pCID->PNM[1] = rsp[ 9];
	pCID->PNM[0] = rsp[ 8];
	pCID->PRV    = rsp[ 7];
	pCID->PSN[3] = rsp[ 6];
	pCID->PSN[2] = rsp[ 5];
	pCID->PSN[1] = rsp[ 4];
	pCID->PSN[0] = rsp[ 3];
	pCID->MDT[1] = rsp[ 2]&0x0F;
	pCID->MDT[0] = rsp[ 1];

	return err;
}

static int sdi_GetCSD(S_WORD RCA, SP_CSD pCSD)
{
	int err, try = 3, val;
	S_BYTE rsp[16];

	do
	{
		err = sdi_SendCmd(SDICMD_L_RSP|SDICMD_WTRSP|SDICMD_SEND_CSD, (int)RCA<<16);
	}while(err && try--);
	
	if (err) return err;

	val = rSDIRSP0; HAI_WRITEDWORD(rsp+12, val);
	val = rSDIRSP1; HAI_WRITEDWORD(rsp+ 8, val);
	val = rSDIRSP2; HAI_WRITEDWORD(rsp+ 4, val);
	val = rSDIRSP3; HAI_WRITEDWORD(rsp+ 0, val);

	sdcard.BlockLen = 512;//temp

	return err;
}

static int sdi_CardSelect(S_WORD RCA)
{
	int err, try = 3;

	do
	{
		err = sdi_SendCmd(SDICMD_WTRSP|SDICMD_SEL_DSEL_CARD, (int)RCA<<16);
	}while (err && try--);

	if(rSDIRSP0&0x1e00 != 0x800)
	    err = -1;

	return err;
}

static int sdi_SetBusWidth(S_WORD RCA, int BUSW)
{
	int err, try = 3;

	do
	{
		if (err = sdi_CMD55(RCA))
			continue;
		err = sdi_SendCmd(SDICMD_WTRSP|SDICMD_SET_BUS_WIDTH, BUSW<<1);
	}while (err && try--);

	return err;
}

static int sdi_ReadBlock(S_DWORD block, S_BYTE *OutBuf)
{
	int err, try = 3;
	int *pOut = (int *)OutBuf;
	int MaxRead = sdcard.BlockLen;
	int BusW = (sdcard.flag&SD_BUSW_MASK)?1:0;

	rSDICON |= (1<<1);// FIFO reset
	rSDIDCON = (1<<19)|(1<<17)|(BusW<<16)|(2<<12)|(1<<0);// Rx after cmd, blk, 4bit bus, Rx start, blk num

	do
	{
		err = sdi_SendCmd(SDICMD_WTRSP|SDICMD_READ_SINGLBLK, block);
	}while (err && try--);

	if (err) return err;

	for (try = 0; try < MaxRead; )
	{
		if((rSDIDSTA&0x20) == 0x20)
		{
		    rSDIDSTA = 0x20;
		    break;
		}
		err = rSDIFSTA;
		if((err&0x1000) == 0x1000)
		{
		    *pOut++ = rSDIDAT;
		    try += 4;
		}
	}

	err = sdi_CheckDATend();
    rSDIDSTA = 0x10;// Clear data Tx/Rx end

	return err;
}

static int sdi_WriteBlock(S_DWORD block, S_BYTE *InBuf)
{
 	int err, try = 3;
	int *pin = (int *)InBuf;
	int MaxWrite = sdcard.BlockLen;
	int BusW = (sdcard.flag&SD_BUSW_MASK)?1:0;

	rSDICON |= (1<<1);// FIFO reset
	rSDIDCON = (1<<20)|(1<<17)|(BusW<<16)|(3<<12)|(1<<0);// Tx after rsp, blk, 4bit bus, Tx start, blk num

	do
	{
		err = sdi_SendCmd(SDICMD_WTRSP|SDICMD_WRITE_SINGLBLK, block);
	}while (err && try--);

	for (try = 0; try < MaxWrite; )
	{
		err = rSDIFSTA;
		if((err&0x2000) == 0x2000) 
		{
		    rSDIDAT = *pin++;
		    try += 4;
		}
	}

	err = sdi_CheckDATend();
    rSDIDSTA = 0x10;// Clear data Tx/Rx end

	return err;
}

static int sdi_CheckDATend(void)
{
    int finish;

	do
	{
    	finish = rSDIDSTA;
    }while(!(finish&0x30));// Chek timeout or data end

    if((finish&0xfc) != 0x10)
    {
        rSDIDSTA = 0xec;// Clear error state
        return -1;
    }
    return 0;
}

static void sdi_IncUseCount(int BufNo)
{
	S_DWORD UseCnt = SDCARDFlag[BufNo]&0x0000FFFF;
	
	UseCnt = (UseCnt<0xFFFF)? (UseCnt+1):(UseCnt);//increase use count
	SDCARDFlag[BufNo] = (SDCARDFlag[BufNo]&0xFFFF0000)|(UseCnt&0x0000FFFF);
}

static int sdi_FindLeastUseCluster(void)
{
	int i = 0, m = 0;
	S_DWORD UseCnt = SDCARDFlag[i]&0x0000FFFF;
	
	for (i = 1; i < SDCARD_BUFFER_BLOCK_MAX; i++)
	{
		if (UseCnt > (SDCARDFlag[i]&0x0000FFFF))
		{
			UseCnt = SDCARDFlag[i]&0x0000FFFF;
			m = i;
		}
	}
	return m;
}


#endif

⌨️ 快捷键说明

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