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

📄 mmc.c

📁 PIC MMC and FAT Sample code
💻 C
字号:
#DEFINE	mmcCardDetect()	!input(MMC_CD)	// Check for Card Detect (CD)
#DEFINE	mmcWrite				spi_write
#DEFINE	mmcRead				spi_read
#DEFINE	mmcIdle()			spi_read(0xFF)

BOOL mmcDetect() {
	int i;

	if(!mmcCardDetect())
		return FALSE;
	else {
		output_high(MMC_CS);
		input(MMC_CD);
		output_high(MMC_SCLK);
		input(MMC_DO);
		output_high(MMC_DI);

		setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_4 | SPI_XMIT_L_TO_H | SPI_SAMPLE_AT_END);

		// MMC requires at least 74 clock cycles before starting bus operation.
		for(i=0;i<10;i++) { 
			mmcIdle();
		}
	}
}

#SEPARATE
BOOL mmcInit() {
	int i;
	BYTE response;

	debug("\n\r[COMMAND] GO_IDLE_STATE");
	response=mmcSendCmd(MMC_CMD_GO_IDLE_STATE,0x00000000,0x95);
	debug("\n\rResponse=%X\n\r",response);

	response=0xFF;
	for(i=0;i<10;i++) {
		debug("\n\r[COMMAND] SEND_OP_COND");
		response=mmcSendCmd(MMC_CMD_SEND_OP_COND,0x00000000,0x01);
		debug("\n\rResponse=%X\n\r",response);

		if(!response) {
			debug("\n\r*** MMC initialisation successful! ***\n\n\r");
			mmcIdle();
			return TRUE;
		}
	}
	
	debug("\n\rMMC failed to initialise ...\n\r");
	mmcIdle();
	return FALSE;
}

int16 mmcGetSector(DWORD address) {
	return (address>>9);
}

#SEPARATE
BYTE mmcSendCmd(BYTE cmd,DWORD arg,BYTE crc) {
	int i;
	BYTE response;
	BYTE command[6];
	
	command[5]=cmd;
	command[4]=make8(arg,3);
	command[3]=make8(arg,2);
	command[2]=make8(arg,1);
	command[1]=make8(arg,0);
	command[0]=crc;

startcmd:
	mmcIdle();
	output_low(MMC_CS);
	for(i=5;i!=0xFF;i--) {
		mmcWrite(command[i]);
	}

	for(i=0;i<8;i++) {		// Response time may range from one to 8 byte shifts.
		response=spi_read(0xFF);
		if((response==0x00) | (response==0x01)) 
			break;
		else if(response==0x40) {
			debug("\n\rParameter error ...");
			//for(i=0;i<50;i++)
			//	debug("\n\rNext byte : %X",mmcRead(0xFF));
			break;
		}
		else if(response!=0xFF){
			debug("\n\rError Dectected ...",response);
			mmcDumpResponse(response);
			// Ugly way of recovery
			for(i=0;i<250;i++)
				mmcWrite(0xFF);
			output_high(MMC_CS);
			goto startcmd;
		}
	}
	if(response==0xFF) { 
		debug("\n\rResponse Timeout ... \n\r");
		output_high(MMC_CS);
		return FALSE;
	}

	switch(cmd) {
		case MMC_CMD_GO_IDLE_STATE:
		case MMC_CMD_SEND_OP_COND:
		case MMC_CMD_SET_BLOCKLEN:
			output_high(MMC_CS);
			return response;
			break;
		case MMC_CMD_SEND_CSD:
		case MMC_CMD_SEND_CID:
			for(i=0;i<8;i++) {
				response=mmcRead(0xFF);
				if(response!=0xFF)
				break;
			}
			if(response==0xFF) {
				debug("\n\rData Timeout ... \n\r");
				output_high(MMC_CS);
				return FALSE;
			}
			if(response!=MMCSTARTSINGLEREAD)	{
				debug("\n\rInvalid Data START Token : %X ...\n\r",response);
				output_high(MMC_CS);
				return FALSE;
			}
			return 0;
			break;
		case MMC_CMD_SEND_STATUS :
			response=mmcRead(0xFF);
			output_high(MMC_CS);
			return response;
			break;
		case MMC_CMD_READ_SINGLE_BLOCK :
			for(i=0;i<250;i++) {
				delay_us(100);
				response=mmcRead(0xFF);
				if(response!=0xFF)
					break;
			}
			if(response==0xFF) {
				debug("\n\rData Timeout ... \n\r");
				output_high(MMC_CS);
				return FALSE;
			}
			if(response!=MMCSTARTSINGLEREAD)	{
				debug("\n\rInvalid Data START Token : %X ...\n\r",response);
				// Ugly way of recovery
				for(i=0;i<250;i++)
					mmcWrite(0xFF);
				output_high(MMC_CS);
				goto startcmd;
			}
			break;
		case MMC_CMD_WRITE_BLOCK :
			mmcWrite(0xFF);
			mmcWrite(0xFF);
			mmcWrite(MMCSTARTSINGLEWRITE);
			break;
	}
}

void mmcStartSingleRead(DWORD address,DWORD length) {
	mmcSetBlockLength(length);
	mmcSendCmd(MMC_CMD_READ_SINGLE_BLOCK,address,0x01);
}

void mmcEndSingleRead() {
	mmcRead(0xFF);				// 16-bit CRC ignored.
	mmcRead(0xFF);
	output_high(MMC_CS);
}

void mmcStartSingleWrite(WORD sector,BOOL useBuffer) {
	int16 i;
	DWORD address;

	address=(int32)sector*512;
	if(useBuffer) {
		mmcStartSingleRead(address,512);
		for(i=0;i<512;i++)
			mmcWriteBuffer[i]=mmcRead(0xFF);
		mmcEndSingleRead();
	}
	else
		mmcSetBlockLength(512);

	mmcSendCmd(MMC_CMD_WRITE_BLOCK,address,0x01);
}

void mmcEndSingleWrite(BOOL useBuffer) {
	int16 i;
	BYTE response;

	if(useBuffer) {
		for(i=0;i<512;i++) 
			mmcWrite(mmcWriteBuffer[i]);
	}

	mmcWrite(0x00);				// 16-bit CRC ignored.
	mmcWrite(0x00);

	response=mmcRead(0xFF) & 0x0E;
	if(response!=MMCDATAOK) {
		debug("\n\rErroroneous Data Response -> ");
		if(response==MMCCRCERROR)
			debug("CRC Error ...");
		else if (response==MMCWRITEERROR)
			debug("MMC Write Error ...");
		else
			debug("Unexpected Data Response : %X",response);
	}

	while(!mmcRead(0xFF));	// Loop till MMC no longer returns busy signal
	output_high(MMC_CS);
	delay_us(100);
}

void mmcSetBlockLength(DWORD length) {
	mmcSendCmd(MMC_CMD_SET_BLOCKLEN,length,0x01);
}

void mmcWriteSingleByte(DWORD address,BYTE data) {
	mmcStartSingleWrite(mmcGetSector(address),TRUE);
	mmcWriteBuffer[address & 0x000001FF]=data;
	mmcEndSingleWrite(TRUE);
}

BYTE mmcReadSingleByte(DWORD address) {
	BYTE data;

	mmcSetBlockLength(1);
	mmcSendCmd(MMC_CMD_READ_SINGLE_BLOCK,address,0x01);

	data=mmcRead(0xFF);
	mmcRead(0xFF);				// 16-bit CRC ignored.
	mmcRead(0xFF);
	output_high(MMC_CS);

	return data;
}

void mmcDumpResponse(BYTE response) {
	debug("\n\rDumping R1 Response");
	debug("\n\r===================");
	debug("\n\rReserved : %D",bit_test(response,7));
	debug("\n\rParameter Error : %D",bit_test(response,6));
	debug("\n\rAddress Error : %D",bit_test(response,5));
	debug("\n\rErase_Seq_Error : %D",bit_test(response,4));
	debug("\n\rCom CRC Error : %D",bit_test(response,3));
	debug("\n\rIllegal Command : %D",bit_test(response,2));
	debug("\n\rErase Reset : %D",bit_test(response,1));
	debug("\n\rIn Idle State : %D",bit_test(response,0));
}

#SEPARATE 
void mmcDumpCSD() {
	int i;
	BYTE reg[16];

	debug("\n\r[COMMAND] SEND_CSD");
	mmcSendCmd(MMC_CMD_SEND_CSD,0x00000000,0x01);
	for(i=15;i!=0xFF;i--) 
		reg[i]=mmcRead(0xFF);
	output_high(MMC_CS);

	debug("\n\rCard Specific Data (CSD) Register");
	debug("\n\r=================================");
	debug("\n\rCSD_STRUCTURE : %X",(reg[15]&0xC0)>>6);
	debug("\n\rSPEC_VERS : %X",(reg[15]&0x3C)>>2);
	debug("\n\rReserved : %X",reg[15]&0x03);
	debug("\n\rTAAC : %X",reg[14]);
	debug("\n\rNSAC : %X",reg[13]);
	debug("\n\rTRAN_SPEED : %X",reg[12]);
	debug("\n\rCCC : %X%X",(reg[11]&0xF0)>>4,((reg[11]&0x0F)<<4)+((reg[10]&0xF0)>>4));
	debug("\n\rREAD_BL_LEN : %X",reg[10]&0x0F);
	debug("\n\rREAD_BL_PARTIAL : %X",(reg[9]&0x80)>>7);
	debug("\n\rWRITE_BLK_MISALIGN : %X",(reg[9]&0x40)>>6);
	debug("\n\rREAD_BLK_MISALIGN : %X",(reg[9]&0x20)>>5);
	debug("\n\rDSR_IMP : %X",(reg[9]&0x10)>>4);
	debug("\n\rReserved : %X",(reg[9]&0x0C)>>2);
	debug("\n\rC_SIZE : %X%X",((reg[9]&0x03)<<2)+((reg[8]&0xC0)>>6),((reg[8]&0x3F)<<2)+((reg[7]&0xC0)>>6));
	debug("\n\rVDD_R_CURR_MIN : %X",(reg[7]&0x38)>>3);
	debug("\n\rVDD_R_CURR_MAX : %X",reg[7]&0x07);
	debug("\n\rVDD_W_CURR_MIN : %X",(reg[6]&0xE0)>>5);
	debug("\n\rVDD_W_CURR_MAX : %X",(reg[6]&0x1C)>>2);
	debug("\n\rC_SIZE_MULT : %X",((reg[6]&0x03)<<1)+((reg[5]&0x80)>>7));
	debug("\n\rSECTOR_SIZE : %X",(reg[5]&0x7C)>>2);
	debug("\n\rERASE_GRP_SIZE : %X",((reg[5]&0x03)<<3)+((reg[4]&0xE0)>>5));
	debug("\n\rWP_GRP_SIZE : %X",reg[4]&0x1F);
	debug("\n\rWP_GRP_ENABLE : %X",(reg[3]&0x80)>>7);
	debug("\n\rDEFAULT_ECC : %X",(reg[3]&0x60)>>5);
	debug("\n\rR2W_FACTOR : %X",(reg[3]&0x1C)>>2);
	debug("\n\rWRITE_BL_LEN : %X",((reg[3]&0x03)<<2)+((reg[2]&0xC0)>>6));
	debug("\n\rWRITE_BL_PARTIAL : %X",(reg[2]&0x20)>>5);
	debug("\n\rReserved : %X",reg[2]&0x1F);
	debug("\n\rFILE_FORMAT_GROUP : %X",(reg[1]&0x80)>>7);
	debug("\n\rCOPY : %X",(reg[1]&0x40)>>6);
	debug("\n\rPERM_WRITE_PROTECT : %X",(reg[1]&0x20)>>5);
	debug("\n\rTMP_WRITE_PROTECT : %X",(reg[1]&0x10)>>4);
	debug("\n\rFILE_FORMAT : %X",(reg[1]&0x0C)>>2);
	debug("\n\rECC : %X",reg[1]&0x03);
	debug("\n\rCRC : %X",(reg[0]&0xFE)>>1);
	debug("\n\rReserved : %X",reg[0]&0x01);
	debug("\n\r");
}

#SEPARATE 
void mmcDumpCID() {
	int i;
	BYTE reg[16];

	debug("\n\r[COMMAND] SEND_CID");
	mmcSendCmd(MMC_CMD_SEND_CID,0x00000000,0x01);
	for(i=15;i!=0xFF;i--) 
		reg[i]=mmcRead(0xFF);
	output_high(MMC_CS);

	debug("\n\rCard Identification Register(CID)");
	debug("\n\r=================================");
	debug("\n\rManuafacturer ID (MID) : %X%X%X",reg[15],reg[14],reg[13]);
	debug("\n\rProduct Name (PNM) : %C%C%C%C%C%C%C",reg[12],reg[11],reg[10],reg[9],reg[8],reg[7],reg[6]);
	debug("\n\rProduct Revision (PRV) : %D.%D",(reg[5]&0xF0)>>4,reg[5]&0x0F);
	debug("\n\rSerial number (PSN) : %X%X%X",reg[4],reg[3],reg[2]);
	debug("\n\rManufacturing Date Code (MDT) : %D/%D",(reg[1]&0xF0)>>4,reg[1]&0x0F);
	debug("\n\rCRC7 checksum (CRC7) : %X",(reg[0]&0xFE)>>1);
	debug("\n\rReserved : %X",reg[0]&0x01);
	debug("\n\r");
}

BYTE mmcGetStatus() {
	BYTE status;

	debug("\n\r[COMMAND] SEND_STATUS");
	status=mmcSendCmd(MMC_CMD_SEND_STATUS,0x00000000,0x01);

	debug("\n\rSTATUS Register");
	debug("\n\r===============");
	debug("\n\rOut of Range, CSD_Overwrite : %D",bit_test(status,7));
	debug("\n\rErase Param : %D",bit_test(status,6));
	debug("\n\rWP Violation : %D",bit_test(status,5));
	debug("\n\rCard ECC Failed : %D",bit_test(status,4));
	debug("\n\rCC Error : %D",bit_test(status,3));
	debug("\n\rError : %D",bit_test(status,2));
	debug("\n\rWP Erase Skip, Lock/Unlock Cmd Failed : %D",bit_test(status,1));
	debug("\n\rCard is Locked : %D",bit_test(status,0));
	debug("\n\r");

	return status;
}

⌨️ 快捷键说明

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