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

📄 sdc_diskio.c

📁 SPI读SD卡文件系统
💻 C
📖 第 1 页 / 共 2 页
字号:
)
{
	BYTE n, cmd, ty, ocr[4];


	if (drv) return STA_NOINIT;			    /* Supports only single drive */
	if (Stat & STA_NODISK) return Stat;	            /* No card in the socket */
        
        MMC_SPI_Config();
        SPI_LowSpeed();    
	MMC_POWERON();				            /* Force socket power on */

	for (n = 10; n; n--) SPI_ReadWrite_Byte(0xff);	    /* 80 dummy clocks */

	ty = 0;
	if (Send_Command(CMD0, 0) == 1) {			    /* Enter Idle state */
		Timer1 = 200;			        /* Initialization timeout of 2000 msec */
		if (Send_Command(CMD8, 0x1AA) == 1) {	    /* 检查是否支持SDC Ver2 */

			for (n = 0; n < 4; n++) 
                ocr[n] = SPI_ReadWrite_Byte(0xff);	/* Get trailing return value of R7 resp */
            if (ocr[2] == 0x01 && ocr[3] == 0xAA) {			
                /* The card can work at vdd range of 2.7-3.6V */
				/* Wait for leaving idle state (ACMD41 with HCS bit) */
                while (Timer1 && Send_Command(ACMD41, 1UL << 30));  				
                if (Timer1 && Send_Command(CMD58, 0) == 0) {		
                    /* Check CCS bit in the OCR */
					for (n = 0; n < 4; n++)
                        ocr[n] = SPI_ReadWrite_Byte(0xff);
                    /* When CCS bit is set  R/W in block address insted of byte address */
					ty = (ocr[0] & 0x40) ? 12 : 4;
				}
			}
		} else {							
            /* SDSC or MMC */
			if (Send_Command(ACMD41, 0) <= 1) 	{           /* initialize successful will response 0x00 */
                ty = 2; cmd = ACMD41;	/* SDv1 */
			} else {
				ty = 1; cmd = CMD1;		/* MMC */
			}
			while (Timer1 && Send_Command(cmd, 0));			/* Wait for leaving idle state */
			if (!Timer1 || Send_Command(CMD16, 512) != 0)	/* Set R/W block length to 512 */
				ty = 0;
		}
	}
	CardType = ty;	
    SPI_HighSpeed();
    SPI_Release();

	if (ty) {
        /* Initialization succeded */
		Stat &= ~STA_NOINIT;		
	} else {			            
        /* Initialization failed */
		MMC_POWEROFF(); 
	}

	return Stat;
}



/*-----------------------------------------------------------------------*/
/* Get Disk Status                                                       */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
	BYTE drv		/* Physical drive nmuber (0) */
)
{
	if (drv) return STA_NOINIT;		/* Supports only single drive */
	return Stat;
}



/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
	BYTE drv,			/* Physical drive nmuber (0) */
	BYTE *buff,			/* Pointer to the data buffer to store read data */
	DWORD sector,		        /* Start sector number (LBA) */
	BYTE count			/* Sector count (1..255) */
)
{
	if (drv || !count) return RES_PARERR;
	if (Stat & STA_NOINIT) return RES_NOTRDY;

	if (!(CardType & 8)) sector *= 512;	/* Convert to byte address if needed */

	if (count == 1) {	/* Single block read */
		if ((Send_Command(CMD17, sector) == 0)	/* READ_SINGLE_BLOCK */
			&& Receive_DataBlock(buff, 512))
			count = 0;
	}
	else {				/* Multiple block read */
		if (Send_Command(CMD18, sector) == 0) {	/* READ_MULTIPLE_BLOCK */
			do {
				if (!Receive_DataBlock(buff, 512)) break;
				buff += 512;
			} while (--count);
			Send_Command(CMD12, 0);				/* STOP_TRANSMISSION */
		}
	}
	SPI_Release();

	return count ? RES_ERROR : RES_OK;
}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/

#if _READONLY == 0
DRESULT disk_write (
	BYTE drv,			/* Physical drive nmuber (0) */
	const BYTE *buff,	/* Pointer to the data to be written */
	DWORD sector,		/* Start sector number (LBA) */
	BYTE count			/* Sector count (1..255) */
)
{
	if (drv || !count) return RES_PARERR;
	if (Stat & STA_NOINIT) return RES_NOTRDY;
	if (Stat & STA_PROTECT) return RES_WRPRT;

	if (!(CardType & 8)) sector *= 512;	/* Convert to byte address if needed */

	if (count == 1) {	/* Single block write */
		if ((Send_Command(CMD24, sector) == 0)	/* WRITE_BLOCK */
			&& Transmit_DataBlock(buff, 0xFE))
			count = 0;
	}
	else {				/* Multiple block write */
		if (CardType & 6) Send_Command(ACMD23, count);
		if (Send_Command(CMD25, sector) == 0) {	/* WRITE_MULTIPLE_BLOCK */
			do {
				if (!Transmit_DataBlock(buff, 0xFC)) break;
				buff += 512;
			} while (--count);
			if (!Transmit_DataBlock(0, 0xFD))	/* STOP_TRAN token */
				count = 1;                      /* faild */
		}
	}
	SPI_Release();

	return count ? RES_ERROR : RES_OK;
}
#endif /* _READONLY == 0 */



/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

#if _USE_IOCTL != 0
DRESULT disk_ioctl (
	BYTE drv,		/* Physical drive nmuber (0) */
	BYTE ctrl,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	DRESULT res;
	BYTE n, csd[16], *ptr = buff;
	WORD csize;


	if (drv) return RES_PARERR;

	res = RES_ERROR;

	if (ctrl == CTRL_POWER) {
		switch (*ptr) {
		case 0:		/* Sub control code == 0 (POWER_OFF) */
			if (chk_power())
				MMC_POWEROFF(); 		/* Power off */
			res = RES_OK;
			break;
		case 1:		/* Sub control code == 1 (POWER_ON) */
			MMC_POWERON();				/* Power on */
			res = RES_OK;
			break;
		case 2:		/* Sub control code == 2 (POWER_GET) */
			*(ptr+1) = (BYTE)chk_power();
			res = RES_OK;
			break;
		default :
			res = RES_PARERR;
		}
	}
	else {
		if (Stat & STA_NOINIT) return RES_NOTRDY;

		switch (ctrl) {
		case CTRL_SYNC :		/* Make sure that no pending write process */
			MMC_SELECT();
			if (Wait_Ready() == 0xFF)
				res = RES_OK;
			break;

		case GET_SECTOR_COUNT :	/* Get number of sectors on the disk (DWORD) */
			if ((Send_Command(CMD9, 0) == 0) && Receive_DataBlock(csd, 16)) {
				if ((csd[0] >> 6) == 1) {	/* SDC ver 2.00 */
					csize = csd[9] + ((WORD)csd[8] << 8) + 1;
					*(DWORD*)buff = (DWORD)csize << 10;
				} else {					/* SDC ver 1.XX or MMC*/
					n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
					csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
					*(DWORD*)buff = (DWORD)csize << (n - 9);
				}
				res = RES_OK;
			}
			break;

		case GET_SECTOR_SIZE :	/* Get R/W sector size (WORD) */
			*(WORD*)buff = 512;
			res = RES_OK;
			break;

		case GET_BLOCK_SIZE :	/* Get erase block size in unit of sector (DWORD) */
			if (CardType & 4) {			/* SDC ver 2.00 */
				if (Send_Command(ACMD13, 0) == 0) {		/* Read SD status */
					SPI_ReadWrite_Byte(0xff);
					if (Receive_DataBlock(csd, 16)) {				/* Read partial block */
						for (n = 64 - 16; n; n--) SPI_ReadWrite_Byte(0xff);	/* Purge trailing data */
						*(DWORD*)buff = 16UL << (csd[10] >> 4);
						res = RES_OK;
					}
				}
			} else {					/* SDC ver 1.XX or MMC */
				if ((Send_Command(CMD9, 0) == 0) && Receive_DataBlock(csd, 16)) {	/* Read CSD */
					if (CardType & 2) {			/* SDC ver 1.XX */
						*(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
					} else {					/* MMC */
						*(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
					}
					res = RES_OK;
				}
			}
			break;

		case MMC_GET_TYPE :		/* Get card type flags (1 byte) */
			*ptr = CardType;
			res = RES_OK;
			break;

		case MMC_GET_CSD :		/* Receive CSD as a data block (16 bytes) */
			if (Send_Command(CMD9, 0) == 0		/* READ_CSD */
				&& Receive_DataBlock(ptr, 16))
				res = RES_OK;
			break;

		case MMC_GET_CID :		/* Receive CID as a data block (16 bytes) */
			if (Send_Command(CMD10, 0) == 0		/* READ_CID */
				&& Receive_DataBlock(ptr, 16))
				res = RES_OK;
			break;

		case MMC_GET_OCR :		/* Receive OCR as an R3 resp (4 bytes) */
			if (Send_Command(CMD58, 0) == 0) {	/* READ_OCR */
				for (n = 4; n; n--) *ptr++ = SPI_ReadWrite_Byte(0xff);
				res = RES_OK;
			}
			break;

		case MMC_GET_SDSTAT :	/* Receive SD statsu as a data block (64 bytes) */
			if (Send_Command(ACMD13, 0) == 0) {	/* SD_STATUS */
				SPI_ReadWrite_Byte(0xff);
				if (Receive_DataBlock(ptr, 64))
					res = RES_OK;
			}
			break;

		default:
			res = RES_PARERR;
		}

		SPI_Release();
	}

	return res;
}
#endif /* _USE_IOCTL != 0 */

DWORD get_fattime (void)
{
    return 0;  
}
/*-----------------------------------------------------------------------*/
/* Device Timer Interrupt Procedure  (Platform dependent)                */
/*-----------------------------------------------------------------------*/
/* This function must be called in period of 10ms                        */

/*
void disk_timerproc (void)
{
	static BYTE pv;
	BYTE n, s;


	n = Timer1;						    // 100Hz decrement timer
	if (n) Timer1 = --n;
	n = Timer2;
	if (n) Timer2 = --n;

	n = pv;
	pv = SOCKPORT & (SOCKWP | SOCKINS);	// Sample socket switch 

	if (n == pv) {					    // Have contacts stabled? 
		s = Stat;

		if (pv & SOCKWP)			// WP is H (write protected) 
			s |= STA_PROTECT;
		else						// WP is L (write enabled) 
			s &= ~STA_PROTECT;

		if (pv & SOCKINS)			// INS = H (Socket empty) 
			s |= (STA_NODISK | STA_NOINIT);
		else						// INS = L (Card inserted) 
			s &= ~STA_NODISK;

		Stat = s;
	}
}
*/

⌨️ 快捷键说明

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