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

📄 mmc.c

📁 S64和VS1003的MP3播放实现的源代码/
💻 C
📖 第 1 页 / 共 2 页
字号:
			xmit_spi(*buff++);
		} while (--wc);
#endif
		
		xmit_spi(0xFF);					/* CRC (Dummy) */
		xmit_spi(0xFF);

		resp = rcvr_spi();				/* Reveive data response */
		if ((resp & 0x1F) != 0x05)
        {
     		/* If not accepted, return with error */
			return FALSE;
        }
	}

	return TRUE;
}
#endif

/*------------------------------*/
/* Send a command packet to MMC */
static BYTE send_cmd (
	BYTE cmd,		/* Command byte */
	DWORD arg		/* Argument */
)
{
	BYTE n, res;

	if (wait_ready() != 0xFF) return 0xFF;

	/* Send command packet */
	xmit_spi(cmd);						/* Command */
	xmit_spi((BYTE)(arg >> 24));		/* Argument[31..24] */
	xmit_spi((BYTE)(arg >> 16));		/* Argument[23..16] */
	xmit_spi((BYTE)(arg >> 8));			/* Argument[15..8] */
	xmit_spi((BYTE)arg);				/* Argument[7..0] */
	xmit_spi(0x95);						/* CRC (valid for only CMD0 in SPI mode) */

	/* Receive command response */
	if (cmd == CMD12) rcvr_spi();		/* Skip a stuff byte when stop reading */

	n = 100;							/* Wait for a valid response in timeout of 10 attempts */
	do
    {
		res = rcvr_spi();
    } while ((res & 0x80) && --n);      /* MSB 1: error */

	//iprintf("res: %i\n", res);
	return res;			/* Return with the response value */
}

/*=======================================================================*/
/* Public Functions                                                      */
/*=======================================================================*/

/*-----------------------*/
/* Initialize Disk Drive */
DSTATUS MMC_disk_initialize (void)
{
	//BYTE n;

	init_spi();

	Stat |= STA_NOINIT;

	if (!(Stat & STA_NODISK)) 
    {
#if 0
		n = 10;						/* Dummy clock */
		do
        {
			rcvr_spi();
        }while (--n);
#endif
		SELECT();			/* CS = L */
		if (send_cmd(CMD0, 0) == 1) 
        {			/* Enter Idle state */
			Timer = 100;						/* Wait for card ready in timeout of 1 sec */
			while (Timer && send_cmd(CMD1, 0));
			if (Timer) 
            {
                Stat &= ~STA_NOINIT;		/* When device goes ready, clear STA_NOINIT */
            }
		}
		DESELECT();			/* CS = H */
		rcvr_spi();			/* Idle (Release DO) */
	}
	// set speed
	if_spiSetSpeed(SPI_DIV);     /* SPI CK = F_CPU / SPI_DIV */

	return Stat;
}

/*----------------*/
/* Shutdown       */
DSTATUS MMC_disk_shutdown (void)
{
	return 0;
}

/*--------------------*/
/* Return Disk Status */

DSTATUS MMC_disk_status (void)
{
	return Stat;
}

/*----------------*/
/* Read Sector(s) */
DRESULT MMC_disk_read (
	BYTE *buff,			/* Data buffer to store read data */
	DWORD sector,		/* Sector number (LBA) */
	BYTE count			/* Sector count (1..255) */
)
{
    if (!count) return RES_PARERR;

	if (Stat & STA_NOINIT) return RES_NOTRDY;
	if (!count) return RES_PARERR;

	sector *= 512;		/* LBA --> byte address */

	SELECT();			/* CS = L */

	if (count == 1) {	/* Single block read */
		//puts("doing single block read");
		if ((send_cmd(CMD17, sector) == 0)	/* READ_SINGLE_BLOCK */
			&& rcvr_datablock(buff, (BYTE)(512/2)))
        {
			count = 0;
        }
	}
	else 
    {				/* Multiple block read */
		//puts("doing multi-block read");
		if (send_cmd(CMD18, sector) == 0) 
        {	/* READ_MULTIPLE_BLOCK */
			do 
            {
				if (!rcvr_datablock(buff, (BYTE)(512/2))) break;
				buff += 512;
			} while (--count);
			send_cmd(CMD12, 0);				/* STOP_TRANSMISSION */
		}
	}

	DESELECT();			/* CS = H */
	rcvr_spi();			/* Idle (Release DO) */

	return count ? RES_ERROR : RES_OK;
}



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

#if _READONLY == 0
DRESULT MMC_disk_write (
	const BYTE *buff,	/* Data to be written */
	DWORD sector,		/* Sector number (LBA) */
	BYTE count			/* Sector count (1..255) */
)
{
    if (!count) return RES_PARERR;

	if (Stat & STA_NOINIT) return RES_NOTRDY;
	if (Stat & STA_PROTECT) return RES_WRPRT;
	if (!count) return RES_PARERR;
	sector *= 512;		/* LBA --> byte address */

	SELECT();			/* CS = L */

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

	DESELECT();			/* CS = H */
	rcvr_spi();			/* Idle (Release DO) */

	return count ? RES_ERROR : RES_OK;
}
#endif

/*--------------------------*/
/* Miscellaneous Functions  */
DRESULT MMC_disk_ioctl (
	BYTE ctrl,		/* Control code */
	void *buff		/* Buffer to send/receive data block */
)
{
	DRESULT res;
	BYTE n, csd[16], *ptr = buff;
	WORD csm, csize;

	if (Stat & STA_NOINIT) return RES_NOTRDY;

	SELECT();		/* CS = L */

	res = RES_ERROR;
	switch (ctrl) 
    {
		case GET_SECTOR_COUNT :	/* Get number of sectors on the disk (unsigned long) */
			if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16/2)) 
            {
				/* Calculate disk size */
				csm = 1 << (((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2);
				csize = ((WORD)(csd[8] & 3) >> 6) + (WORD)(csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
				*(DWORD*)ptr = (DWORD)csize * csm;
				res = RES_OK;
			}
			break;

		case MMC_GET_CSD :	/* Receive CSD as a data block (16 bytes) */
			if ((send_cmd(CMD9, 0) == 0)	/* READ_CSD */
				&& rcvr_datablock(ptr, 16/2))
            {
				res = RES_OK;
            }
			break;

		case MMC_GET_CID :	/* Receive CID as a data block (16 bytes) */
			if ((send_cmd(CMD10, 0) == 0)	/* READ_CID */
				&& rcvr_datablock(ptr, 16/2))
            {
				res = RES_OK;
            }
			break;

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

		default:
			res = RES_PARERR;
	}

	DESELECT();			/* CS = H */
	rcvr_spi();			/* Idle (Release DO) */

	return res;
}

/*---------------------------------------*/
/* Device timer interrupt procedure      */
/* This must be called in period of 10ms */
void disk_timerproc (void)
{
	BYTE n = 0;

	n = Timer;						/* 100Hz decrement timer */
	if (n) Timer = --n;
}

/*---------------------------------------------------------*/
/* User Provided Timer Function for FatFs module           */
/*---------------------------------------------------------*/
/* This is a real time clock service to be called from     */
/* FatFs module. Any valid time must be returned even if   */
/* the system does not support a real time clock.          */
DWORD get_fattime ()
{
	return	((2006UL-1980) << 25)	// Year = 2006
			| (2UL << 21)			// Month = Feb
			| (9UL << 16)			// Day = 9
			| (22U << 11)			// Hour = 22
			| (30U << 5)			// Min = 30
			| (0U >> 1)				// Sec = 0
			;
}

⌨️ 快捷键说明

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