Пример #1
0
DSTATUS disk_initialize (void)
{
	BYTE n, cmd, ty, buf[4];
	UINT tmr;


//	INIT_PORT();
	mmc_spi_InitSocket();

//	CS_H();
	mmc_spi_SetCardDeselect();
	skip_mmc(10);			/* Dummy clocks */

	ty = 0;
	if (send_cmd(CMD0, 0) == 1) {			/* Enter Idle state */
		if (send_cmd(CMD8, 0x1AA) == 1) {	/* SDv2 */
			for (n = 0; n < 4; n++) buf[n] = rcvr_mmc();	/* Get trailing return value of R7 resp */
			if (buf[2] == 0x01 && buf[3] == 0xAA) {			/* The card can work at vdd range of 2.7-3.6V */
				for (tmr = 1000; tmr; tmr--) {				/* Wait for leaving idle state (ACMD41 with HCS bit) */
					if (send_cmd(ACMD41, 1UL << 30) == 0) break;
//					DLY_US(1000);
					mmc_spi_SetTimer(1);
					while( mmc_spi_CheckTimer() ) {}
				}
				if (tmr && send_cmd(CMD58, 0) == 0) {		/* Check CCS bit in the OCR */
					for (n = 0; n < 4; n++) buf[n] = rcvr_mmc();
					ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;	/* SDv2 (HC or SC) */
				}
			}
		} else {							/* SDv1 or MMCv3 */
			if (send_cmd(ACMD41, 0) <= 1) 	{
				ty = CT_SD1; cmd = ACMD41;	/* SDv1 */
			} else {
				ty = CT_MMC; cmd = CMD1;	/* MMCv3 */
			}
			for (tmr = 1000; tmr; tmr--) {			/* Wait for leaving idle state */
				if (send_cmd(ACMD41, 0) == 0) break;
//				DLY_US(1000);
				mmc_spi_SetTimer(1);
				while( mmc_spi_CheckTimer() ) {}
			}
			if (!tmr || send_cmd(CMD16, 512) != 0)			/* Set R/W block length to 512 */
				ty = 0;
		}
	}
	CardType = ty;
	release_spi();

//	return ty ? 0 : STA_NOINIT;

	if ( !ty ) return STA_NOINIT;

	mmc_spi_SetTransClock();
	return 0;
}
Пример #2
0
DRESULT disk_readp (
	BYTE *buff,		/* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */
	DWORD lba,		/* Sector number (LBA) */
	WORD ofs,		/* Byte offset to read from (0..511) */
	WORD cnt		/* Number of bytes to read (ofs + cnt mus be <= 512) */
)
{
	DRESULT res;
	BYTE d;
	WORD bc, tmr;


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

	res = RES_ERROR;
	if (send_cmd(CMD17, lba) == 0) {		/* READ_SINGLE_BLOCK */

		tmr = 1000;
		do {							/* Wait for data packet in timeout of 100ms */
//			DLY_US(100);
			mmc_spi_Wait100us();
			d = rcvr_mmc();
		} while (d == 0xFF && --tmr);

		if (d == 0xFE) {				/* A data packet arrived */
			bc = 514 - ofs - cnt;

			/* Skip leading bytes */
			if (ofs) skip_mmc(ofs);

			/* Receive a part of the sector */
//			if (buff) {	/* Store data to the memory */
				do
					*buff++ = rcvr_mmc();
				while (--cnt);
//			} else {	/* Forward data to the outgoing stream */
//				do {
//					d = rcvr_mmc();
//					FORWARD(d);
//				} while (--cnt);
//			}

			/* Skip trailing bytes and CRC */
			skip_mmc(bc);

			res = RES_OK;
		}
	}

	release_spi();

	return res;
}
Пример #3
0
static
BYTE send_cmd (
	BYTE cmd,		/* Command byte */
	DWORD arg		/* Argument */
)
{
	BYTE n, res;


	if (cmd & 0x80) {	/* ACMD<n> is the command sequense of CMD55-CMD<n> */
		cmd &= 0x7F;
		res = send_cmd(CMD55, 0);
		if (res > 1) return res;
	}

#if AXI_SPI
	XStatus Status = XSpi_SetSlaveSelect(&Spi, 0);
	if(Status != XST_SUCCESS) {
   		xil_printf("Failure Slave Select 0\r\n");
   		xil_printf("Status = %d\r\n", Status);
	}
	rcvr_mmc();
	Status = XSpi_SetSlaveSelect(&Spi, 1);
	if(Status != XST_SUCCESS) {
   		xil_printf("Failure Slave Select 1\r\n");
	}
	rcvr_mmc();
#else
	/* Select the card */
	CS_H(); rcvr_mmc();
	CS_L(); rcvr_mmc();
#endif

	/* Send a command packet */
	xmit_mmc(cmd);					/* Start + Command index */
	xmit_mmc((BYTE)(arg >> 24));	/* Argument[31..24] */
	xmit_mmc((BYTE)(arg >> 16));	/* Argument[23..16] */
	xmit_mmc((BYTE)(arg >> 8));		/* Argument[15..8] */
	xmit_mmc((BYTE)arg);			/* Argument[7..0] */
	n = 0x01;						/* Dummy CRC + Stop */
	if (cmd == CMD0) n = 0x95;		/* Valid CRC for CMD0(0) */
	if (cmd == CMD8) n = 0x87;		/* Valid CRC for CMD8(0x1AA) */
	xmit_mmc(n);

	/* Receive a command response */
	n = 10;								/* Wait for a valid response in timeout of 10 attempts */
	do {
		res = rcvr_mmc();
	} while ((res & 0x80) && --n);

	return res;			/* Return with the response value */
}
Пример #4
0
static
void release_spi (void)
{
//	CS_H();
	mmc_spi_SetCardDeselect();
	rcvr_mmc();
}
Пример #5
0
DRESULT disk_writep (
	const BYTE *buff,	/* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */
	DWORD sa			/* Number of bytes to send, Sector number (LBA) or zero */
)
{
	DRESULT res;
	WORD bc, tmr;
	static WORD wc;


	res = RES_ERROR;

	if (buff) {		/* Send data bytes */
		bc = (WORD)sa;
		while (bc && wc) {		/* Send data bytes to the card */
			xmit_mmc(*buff++);
			wc--; bc--;
		}
		res = RES_OK;
	} else {
		if (sa) {	/* Initiate sector write process */
			if (!(CardType & CT_BLOCK)) sa *= 512;	/* Convert to byte address if needed */
			if (send_cmd(CMD24, sa) == 0) {			/* WRITE_SINGLE_BLOCK */
				xmit_mmc(0xFF); xmit_mmc(0xFE);		/* Data block header */
				wc = 512;							/* Set byte counter */
				res = RES_OK;
			}
		} else {	/* Finalize sector write process */
			bc = wc + 2;
			while (bc--) xmit_mmc(0);	/* Fill left bytes and CRC with zeros */
			if ((rcvr_mmc() & 0x1F) == 0x05) {	/* Receive data resp and wait for end of write process in timeout of 300ms */
				for (tmr = 10000; rcvr_mmc() != 0xFF && tmr; tmr--)	/* Wait for ready (max 1000ms) */
//					DLY_US(100);
					mmc_spi_Wait100us();
				if (tmr) res = RES_OK;
			}
			release_spi();
		}
	}

	return res;
}
Пример #6
0
static
BYTE send_cmd (		/* Returns command response (bit7==1:Send failed)*/
	BYTE cmd,		/* Command byte */
	DWORD arg		/* Argument */
)
{
	BYTE n, d, buf[6];


	if (cmd & 0x80) {	/* ACMD<n> is the command sequense of CMD55-CMD<n> */
		cmd &= 0x7F;
		n = send_cmd(CMD55, 0);
		if (n > 1) return n;
	}

	/* Select the card and wait for ready */
	deselect();
	if (!SPI_select()) return 0xFF;

	/* Send a command packet */
	buf[0] = 0x40 | cmd;			/* Start + Command index */
	buf[1] = (BYTE)(arg >> 24);		/* Argument[31..24] */
	buf[2] = (BYTE)(arg >> 16);		/* Argument[23..16] */
	buf[3] = (BYTE)(arg >> 8);		/* Argument[15..8] */
	buf[4] = (BYTE)arg;				/* Argument[7..0] */
	n = 0x01;						/* Dummy CRC + Stop */
	if (cmd == CMD0) n = 0x95;		/* (valid CRC for CMD0(0)) */
	if (cmd == CMD8) n = 0x87;		/* (valid CRC for CMD8(0x1AA)) */
	buf[5] = n;
	xmit_mmc(buf, 6);

	/* Receive command response */
	if (cmd == CMD12) rcvr_mmc(&d, 1);	/* Skip a stuff byte when stop reading */
	n = 10;								/* Wait for a valid response in timeout of 10 attempts */
	do
		rcvr_mmc(&d, 1);
	while ((d & 0x80) && --n);

	return d;			/* Return with the response value */
}
Пример #7
0
static
int rcvr_datablock (	/* 1:OK, 0:Failed */
	BYTE *buff,			/* Data buffer to store received data */
	UINT btr			/* Byte count */
)
{
	BYTE d[2];
	UINT tmr;


	for (tmr = 1000; tmr; tmr--) {	/* Wait for data packet in timeout of 100ms */
		rcvr_mmc(d, 1);
		if (d[0] != 0xFF) break;
		//DLY_US(100);
	}
	if (d[0] != 0xFE) return 0;		/* If not valid data token, return with error */

	rcvr_mmc(buff, btr);			/* Receive the data block into buffer */
	rcvr_mmc(d, 2);					/* Discard CRC */

	return 1;						/* Return with success */
}
Пример #8
0
static
BYTE send_cmd (
	BYTE cmd,		/* Command byte */
	DWORD arg		/* Argument */
)
{
	BYTE n, res;


	if (cmd & 0x80) {	/* ACMD<n> is the command sequense of CMD55-CMD<n> */
		cmd &= 0x7F;
		res = send_cmd(CMD55, 0);
		if (res > 1) return res;
	}

	/* Select the card */
	CS_H(); rcvr_mmc();
	CS_L(); rcvr_mmc();

	/* Send a command packet */
	XMIT_MMC(cmd);					/* Start + Command index */
	XMIT_MMC((BYTE)(arg >> 24));	/* Argument[31..24] */
	XMIT_MMC((BYTE)(arg >> 16));	/* Argument[23..16] */
	XMIT_MMC((BYTE)(arg >> 8));		/* Argument[15..8] */
	XMIT_MMC((BYTE)arg);			/* Argument[7..0] */
	n = 0x01;						/* Dummy CRC + Stop */
	if (cmd == CMD0) n = 0x95;		/* Valid CRC for CMD0(0) */
	if (cmd == CMD8) n = 0x87;		/* Valid CRC for CMD8(0x1AA) */
	XMIT_MMC(n);

	/* Receive a command response */
	n = 10;								/* Wait for a valid response in timeout of 10 attempts */
	do {
		res = rcvr_mmc();
	} while ((res & 0x80) && --n);

	return res;			/* Return with the response value */
}
Пример #9
0
static
int xmit_datablock (	/* 1:OK, 0:Failed */
	const BYTE *buff,	/* 512 byte data block to be transmitted */
	BYTE token			/* Data/Stop token */
)
{
	BYTE d[2];


	if (!wait_ready()) return 0;

	d[0] = token;
	xmit_mmc(d, 1);				/* Xmit a token */
	if (token != 0xFD) {		/* Is it data token? */
		xmit_mmc(buff, 512);	/* Xmit the 512 byte data block to MMC */
		rcvr_mmc(d, 2);			/* Xmit dummy CRC (0xFF,0xFF) */
		rcvr_mmc(d, 1);			/* Receive data response */
		if ((d[0] & 0x1F) != 0x05)	/* If not accepted, return with error */
			return 0;
	}

	return 1;
}
Пример #10
0
static
void release_spi (void)
{
#if AXI_SPI
	XStatus Status = XSpi_SetSlaveSelect(&Spi, 1);
	if(Status != XST_SUCCESS) {
   		xil_printf("Failure Slave Select release_spi\r\n");
	}

	//DLY_US(1);
#else
	CS_H();
	rcvr_mmc();
#endif
}
Пример #11
0
static
void skip_mmc (
	WORD n		/* Number of bytes to skip */
)
{
	do {
		rcvr_mmc();
	} while (--n);

//	DI_H();	/* Send 0xFF */
//
//	do {
//		CK_H(); CK_L();
//		CK_H(); CK_L();
//		CK_H(); CK_L();
//		CK_H(); CK_L();
//		CK_H(); CK_L();
//		CK_H(); CK_L();
//		CK_H(); CK_L();
//		CK_H(); CK_L();
//	} while (--n);
}
Пример #12
0
DRESULT disk_readp (
	BYTE *buff,		/* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */
	DWORD sector,	/* Sector number (LBA) */
	UINT offset,	/* Byte offset to read from (0..511) */
	UINT count		/* Number of bytes to read (ofs + cnt mus be <= 512) */
)
{
        BYTE *buff_sec = buffer;
	DRESULT res;
	BYTE d;
	UINT bc, tmr;

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

	// check if sector is already in sector buffer
	if(buffer_sector == sector) {
	  buff_sec += offset;  // skip to requested bytes
	  while(count--)
	    *buff++ = *buff_sec++;

	  return RES_OK;
	}

	res = RES_ERROR;
	if (send_cmd(CMD17, sector) == 0) {		/* READ_SINGLE_BLOCK */

		tmr = 1000;
		do {							/* Wait for data packet in timeout of 100ms */
			DLY_US(100);
			d = rcvr_mmc();
		} while (d == 0xFF && --tmr);

		if (d == 0xFE) {				/* A data packet arrived */
			bc = 512 - offset - count;

			/* Skip leading bytes (store in buffer only) */
			while(offset--)
			  *buff_sec++ = rcvr_mmc();

			/* Receive a part of the sector */
			if (buff) {	/* Store data to the memory */
			    do
			        *buff_sec++ = *buff++ = rcvr_mmc();
			    while (--count);
			} else {	/* Forward data to the outgoing stream */
				do {
					*buff_sec++ = d = rcvr_mmc();
					FORWARD(d);
				} while (--count);
			}

			/* Skip trailing bytes (store in buffer only) */
			while(bc--)
			  *buff_sec++ = rcvr_mmc();
			
			/* and skip crc */
			skip_mmc(2);

			buffer_sector = sector;
			res = RES_OK;
		}
	}

	release_spi();

	return res;
}
Пример #13
0
static
void release_spi (void)
{
	CS_H();
	rcvr_mmc();
}
Пример #14
0
DRESULT disk_readp (
	BYTE *buff,		/* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */
	DWORD lba,		/* Sector number (LBA) */
	WORD ofs,		/* Byte offset to read from (0..511) */
	WORD cnt		/* Number of bytes to read (ofs + cnt mus be <= 512) */
)
{

#if 0
	xil_printf("\n\n");
	xil_printf("lba = %d\n", lba);
	xil_printf("ofs = %d\n", ofs);
	xil_printf("cnt = %d\n", cnt);
#endif


	typedef struct LRUEntry {
		bool valid;
		DWORD lba_key;
		BYTE buffer[512];
		struct LRUEntry* more_recently_used;
		struct LRUEntry* less_recently_used;
	} LRUEntry;

#define NUM_LRU_ENTRIES 2 // At least 2
	static LRUEntry* least_recently_used_entry = 0;
	static LRUEntry* most_recently_used_entry = 0;
	static LRUEntry read_buff_lru[NUM_LRU_ENTRIES];

	static BYTE write_buff[512];
	// Init once.
	if(!write_buff[0]){
		memset(write_buff, 0xff, 512);

		// 0 is most recent and NUM_LRU_ENTRIES-1 is least recent.
		read_buff_lru[0].valid = false;
		read_buff_lru[0].more_recently_used = NULL;
		read_buff_lru[0].less_recently_used = &read_buff_lru[1];
		most_recently_used_entry = &read_buff_lru[0];
		for(int i = 1; i < NUM_LRU_ENTRIES-1; i++){
			read_buff_lru[i].valid = false;
			read_buff_lru[i].more_recently_used = &read_buff_lru[i-1];
			read_buff_lru[i].less_recently_used = &read_buff_lru[i+1];
		}
		read_buff_lru[NUM_LRU_ENTRIES-1].valid = false;
		read_buff_lru[NUM_LRU_ENTRIES-1].more_recently_used = &read_buff_lru[NUM_LRU_ENTRIES-2];
		read_buff_lru[NUM_LRU_ENTRIES-1].less_recently_used = NULL;
		least_recently_used_entry = &read_buff_lru[NUM_LRU_ENTRIES-1];
	}

	// Search for entry...
	for(int i = 0; i < NUM_LRU_ENTRIES; i++){
		if(read_buff_lru[i].valid && read_buff_lru[i].lba_key == lba){
		 	if(buff){
		 		memcpy(buff, read_buff_lru[i].buffer + ofs, cnt);
		 	}
		 	LRUEntry* curr_entry = &read_buff_lru[i];

		 	// Update LRU list.
		 	if(curr_entry != most_recently_used_entry){
				if(curr_entry == least_recently_used_entry){
					least_recently_used_entry = curr_entry->more_recently_used;
					least_recently_used_entry->less_recently_used = NULL;
				}
				most_recently_used_entry->more_recently_used = curr_entry;
				curr_entry->less_recently_used = most_recently_used_entry;
				curr_entry->more_recently_used = NULL;
				most_recently_used_entry = curr_entry;
		 	}
		 	return RES_OK;
		}
	}

	// Took least recently used entry to read to it.
	// Update LRU list.
	LRUEntry* curr_entry = least_recently_used_entry;
	// Setting new least recently used.
	least_recently_used_entry = curr_entry->more_recently_used;
	least_recently_used_entry->less_recently_used = NULL;
	// Prepending new most recently used.
	most_recently_used_entry->more_recently_used = curr_entry;
	curr_entry->less_recently_used = most_recently_used_entry;
	curr_entry->more_recently_used = NULL;
	most_recently_used_entry = curr_entry;

	curr_entry->valid = true;
	curr_entry->lba_key = lba;
	BYTE* read_buff = curr_entry->buffer;


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

	DRESULT res = RES_ERROR;
	if (send_cmd(CMD17, lba) == 0) {		/* READ_SINGLE_BLOCK */
		BYTE d;

		int tmr = 100000;
		do {							/* Wait for data packet in timeout of 100ms */
			DLY_US(1);
			d = rcvr_mmc();
		} while (d == 0xFF && --tmr);

		if (d == 0xFE) {				/* A data packet arrived */
			XStatus Status = XSpi_Transfer(&Spi, write_buff, read_buff, 512);
		 	if(Status != XST_SUCCESS) {
				xil_printf("Error in read transfer\r\n");
				return res;
			}
		 	if(buff){
		 		memcpy(buff, read_buff + ofs, cnt);
		 	}

			res = RES_OK;
		}
	}

	release_spi();

	return res;
}
Пример #15
0
DSTATUS disk_initialize (void)
{
	BYTE n, cmd, ty, buf[4];
	UINT tmr;


#if AXI_SPI
	/*
	 * Initialize the SPI driver so that it's ready to use,
	 * specify the device ID that is generated in xparameters.h.
	 */
	XStatus Status = XSpi_Initialize(&Spi, XPAR_SDCARD_SPI_DEVICE_ID);
	if(Status != XST_SUCCESS) {\
   		xil_printf("Failure INIT\r\n");
		return XST_FAILURE;
	}
	/*
	 * Set the SPI device as a master and in manual slave select mode such
	 * that the slave select signal does not toggle for every byte of a
	 * transfer, this must be done before the slave select is set.
	 */
	Status = XSpi_SetOptions(&Spi, XSP_MASTER_OPTION |
						XSP_MANUAL_SSELECT_OPTION);
	if(Status != XST_SUCCESS) {
   		xil_printf("Failure Options\r\n");
		return XST_FAILURE;
	}

	Status = XSpi_SetSlaveSelect(&Spi, 1);
	if(Status != XST_SUCCESS) {
   		xil_printf("Failure Slave Select\r\n");
		return XST_FAILURE;
	}

	XSpi_Start(&Spi);
	XSpi_IntrGlobalDisable(&Spi);

	DLY_US(1);
#else
	INIT_PORT();

	CS_H();
#endif
	skip_mmc(10);			/* Dummy clocks */

	ty = 0;
	if (send_cmd(CMD0, 0) == 1) {			/* Enter Idle state */
		if (send_cmd(CMD8, 0x1AA) == 1) {	/* SDv2 */
			for (n = 0; n < 4; n++) buf[n] = rcvr_mmc();	/* Get trailing return value of R7 resp */
			if (buf[2] == 0x01 && buf[3] == 0xAA) {			/* The card can work at vdd range of 2.7-3.6V */
				for (tmr = 1000; tmr; tmr--) {				/* Wait for leaving idle state (ACMD41 with HCS bit) */
					if (send_cmd(ACMD41, 1UL << 30) == 0) break;
					DLY_US(1000);
				}
				if (tmr && send_cmd(CMD58, 0) == 0) {		/* Check CCS bit in the OCR */
					for (n = 0; n < 4; n++) buf[n] = rcvr_mmc();
					ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;	/* SDv2 (HC or SC) */
				}
			}
		} else {							/* SDv1 or MMCv3 */
			if (send_cmd(ACMD41, 0) <= 1) 	{
				ty = CT_SD1; cmd = ACMD41;	/* SDv1 */
			} else {
				ty = CT_MMC; cmd = CMD1;	/* MMCv3 */
			}
			for (tmr = 1000; tmr; tmr--) {			/* Wait for leaving idle state */
				if (send_cmd(cmd, 0) == 0) break;
				DLY_US(1000);
			}
			if (!tmr || send_cmd(CMD16, 512) != 0)			/* Set R/W block length to 512 */
				ty = 0;
		}
	}
	CardType = ty;
	release_spi();

	return ty ? 0 : STA_NOINIT;
}