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

📄 sdmmc.c

📁 SD卡驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
// Simply turn off the card
//
void ShutdownMedia(void)
{
	// close the spi bus
	CloseSPI();

	// deselect the device
	CS_HIGH;

	// Turn off the card
	//MMC_OFF;
}

/******************************************************************************
 * Function:        void SendMMCCmd(BYTE cmd, DWORD address)
 *
 *
 * Input:           None
 *
 * Output:          response            - Response from the card
 *                                      - 0x00 or 0x01 Command received 
 *                                        successfully, else, command failed
 *                  -Bit 0              - In idle state if 1
 *                  -Bit 1              - Erase Reset if 1
 *                  -Bit 2              - Illgal Command if 1
 *                  -Bit 3              - Com CRC Error if 1
 *                  -Bit 4              - Erase Sequence Error if 1
 *                  -Bit 5              - Address Error if 1
 *                  -Bit 6              - Parameter Error if 1
 *                  -Bit 7              - Not used, always '0'
 *
 * Side Effects:    None
 *
 * Overview:        SendMMCCmd prepares the command packet and sends it out
 *                  over the SPI interface. Response data of type 'R1' (see
 *                  SD or MMC product manuals) is returned.
 *
 * Note:            MMC_CS is not set at the end of this function.
 *                  if the command has no data stage, call macro
 *                  mSendMediaCmd_NoData(), it reasserts MMC_CS to 1.
 *                  If the command has a data stage, MMC_CS must be
 *                  reasserted after the data transfer stage is complete.
 *                  See SECTORread and SECTORwrite for examples.
 *****************************************************************************/
MMC_RESPONSE SendMMCCmd(BYTE cmd, DWORD address)
{
	int timeout = 8;
	char index;
	MMC_RESPONSE    response;
	CMD_PACKET  CmdPacket;
//	memset(&response,0,sizeof(SD_RESPONSE));
	CS_LOW;                       //Card Select
	WriteSPI(0xFF);    // delay 8 spi clock
	// Copy over data
	CmdPacket.cmd        = sdmmc_cmdtable[cmd].CmdCode;
	CmdPacket.address    = address;
	CmdPacket.crc        = sdmmc_cmdtable[cmd].CRC;       // Calc CRC here

	CmdPacket.TRANSMIT_BIT = 1;             //Set Tranmission bit

	WriteSPI(0x40|CmdPacket.cmd);                //Send Command
	WriteSPI(CmdPacket.addr3);              //Most Significant Byte
	WriteSPI(CmdPacket.addr2);
	WriteSPI(CmdPacket.addr1);
	WriteSPI(CmdPacket.addr0);              //Least Significant Byte
	WriteSPI(CmdPacket.crc);                //Send CRC

	// see if  we are going to get a response
	if(sdmmc_cmdtable[cmd].responsetype == R1 || sdmmc_cmdtable[cmd].responsetype == R1b)
	{
		do
		{
			response.r1._byte = SPI_RecByte();
			timeout--;
		}while(((response.r1._byte & 0x80)!= 0x00) &&( timeout != 0));
	}
	else if(sdmmc_cmdtable[cmd].responsetype == R2)
	{
		SPI_RecByte();

		response.r2._byte1 = SPI_RecByte();
		response.r2._byte0 = SPI_RecByte();
	}

	if(sdmmc_cmdtable[cmd].responsetype == R1b)
	{
		response.r1._byte = 0x00;

		for(index =0; index < 0xFF && response.r1._byte == 0x00; index++)
		{
			timeout = 0xFFFF;

			do
			{
				response.r1._byte = SPI_RecByte();
				timeout--;
			}while(response.r1._byte == 0x00 && timeout != 0);
		}
	}

	WriteSPI(0xff);                      //Required clocking (see spec)

	// see if we are expecting data or not
	if(!(sdmmc_cmdtable[cmd].moredataexpected))
	{
		CS_HIGH;
	}
	return(response);
}
/******************************************************************************
 * Function:        BYTE SECTORread(DWORD sector_addr, BYTE *buffer)
 *
 * PreCondition:    None
 *
 * Input:           sector_addr - Sector address, each sector contains 512-byte
 *                  buffer      - Buffer where data will be stored, see
 *                                'ram_acs.h' for 'block' definition.
 *                                'Block' is dependent on whether internal or
 *                                external memory is used
 *
 * Output:          See MMC_Error.
 *
 * Side Effects:    None
 *
 * Overview:        SECTORread reads 512 bytes of data from the card starting
 *                  at the sector address specified by sector_addr and stores
 *                  them in the location pointed to by 'buffer'.
 *
 * Note:            The card expects the address field in the command packet
 *                  to be byte address. Therefore the sector_addr must first
 *                  be converted to byte address. This is accomplished by
 *                  shifting the address left 9 times.
 *****************************************************************************/
BYTE SECTORread(DWORD sector_addr, BYTE* buffer)
{
	WORD index;
	MMC_RESPONSE    response;
	BYTE data_token;
	BYTE status = TRUE;
	DWORD	new_addr;

	#ifdef STATUSLED
	STTRIS = OUTPUT;
	STLED = 1;
	#endif

	// send the cmd
	new_addr = sector_addr << SECTOR_SHIFT_BITS;
	response = SendMMCCmd(READ_SINGLE_BLOCK,new_addr);
	// Make sure the command was accepted
	if(response.r1._byte != 0x00)
	{
		response = SendMMCCmd(READ_SINGLE_BLOCK,new_addr);
		if(response.r1._byte != 0x00)
			status = FALSE;
	}
	else
	{
		index = 0x2FF;

		//Now, must wait for the start token of data block
		do
		{
			data_token = ReadMedia();
			index--;
		}while((data_token == MMC_FLOATING_BUS) && (index != 0));

		// Hopefully that zero is the datatoken
		if((index == 0) || (data_token != DATA_START_TOKEN))
		{
			//status = FALSE;
			new_addr = sector_addr <<SECTOR_SHIFT_BITS;
			response = SendMMCCmd(READ_SINGLE_BLOCK,new_addr);
			index = 0x2FF;

			//Now, must wait for the start token of data block
			do
			{
				data_token = ReadMedia();
				index--;
			}while((data_token == MMC_FLOATING_BUS) && (index != 0));
			if((index == 0) || (data_token != DATA_START_TOKEN))
			{
				status = FALSE;
			}
			else
			{	
				goto here;
			}
		}
		else
		{
			here:
			for(index = 0; index < MEDIA_SECTOR_SIZE; index++)		//Reads in 512-byte of data
			{
					buffer[index] = ReadMedia();
				#ifdef 	 DEBUG_SDMMC
					U8toHexString(buffer[index],string);

					if((index % 0x10) == 0x00)
						DEBUG_PRINT("\n\r");

					DEBUG_PRINT_RAM((char*)string);

					DEBUG_PRINT(" ");
				#endif
			}
			// Now ensure CRC
			mReadCRC();					//Read 2 bytes of CRC
			//status = mmcCardCRCError;
		}

		mSend8ClkCycles();				//Required clocking (see spec)
	}

	CS_HIGH;

	#ifdef STATUSLED
	STLED = 0;
	#endif

	return(status);
}//end SECTORread

/******************************************************************************
 * Function:        BYTE SECTORwrite(DWORD sector_addr, BYTE *buffer)
 *
 * PreCondition:    None
 *
 * Input:           sector_addr - Sector address, each sector contains 512-byte
 *                  buffer      - Buffer where data will be read, see
 *                                'ram_acs.h' for 'block' definition.
 *                                'Block' is dependent on whether internal or
 *                                external memory is used
 *
 * Output:          See MMC_Error.
 *
 * Side Effects:    None
 *
 * Overview:        SECTORwrite sends 512 bytes of data from the location
 *                  pointed to by 'buffer' to the card starting
 *                  at the sector address specified by sector_addr.
 *
 * Note:            The card expects the address field in the command packet
 *                  to be byte address. Therefore the sector_addr must first
 *                  be converted to byte address. This is accomplished by
 *                  shifting the address left 9 times.
 *****************************************************************************/
BYTE SECTORwrite(DWORD sector_addr, BYTE* buffer)
{
	WORD index;
    BYTE data_response;
	MMC_RESPONSE    response; 
    BYTE status = TRUE;

	#ifdef STATUSLED
	STTRIS = OUTPUT;
	STLED = 1;
	#endif

	if (sector_addr == 0)
		status = FALSE;
	else
	{
		// send the cmd
		response = SendMMCCmd(WRITE_SINGLE_BLOCK,(sector_addr << SECTOR_SHIFT_BITS));

		// see if it was accepted
		if(response.r1._byte != 0x00)
			status = FALSE;
		else
		{
		                //Send data start token
			WriteSPI(DATA_START_TOKEN);
			for(index = 0; index < 512; index++)                    //Send 512 bytes of dat
			WriteSPI(buffer[index]);
			// calc crc
			mSendCRC();                                 //Send 2 bytes of CRC

			data_response = ReadMedia();                //Read response

			if((data_response & 0x0F) != DATA_ACCEPTED)
			{
				status = FALSE;
			}
			else
			{
				index = 0;				//using i as a timeout counter

				do						//Wait for write completion
				{
					data_response = ReadMedia();
					index++;
				}while((data_response == 0x00) && (index != 0));

				if(index == 0)                                  //if timeout first
					status = FALSE;
			}

			mSend8ClkCycles();
		}

		CS_HIGH;

		#ifdef STATUSLED
		STLED = 0;
		#endif
	} // Not writing to 0 sector

	return(status);
} //end SECTORwrite


/*****************************************************************
 Return the state of the WP Pin
 *****************************************************************/
BYTE WriteProtectState(void)
{
//	return(SD_WE);
	return 0;
}

void Delayms(BYTE milliseconds)
{
	BYTE 	ms;
	DWORD	count;
	
	ms = milliseconds;
	while (ms--)
	{
		count = ((SYSTEM_CLOCK / 28) / 1000) - 5;

		while (count--)
		{
			;
		}
	}
	return;
}


/******************************************************************************
 * Function:        BYTE ReadMedia(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          BYTE    - One byte of data read in from SPI port
 *
 * Side Effects:    None
 *
 * Overview:        ReadMedia reads in one byte of data while sending out 0xFF
 *
 * Note:            Could not use ReadSPI because it initializes SSPBUF to
 *                  0x00. The card expects 0xFF (see spec).
 *****************************************************************************/
BYTE ReadMedia(void)
{
	SPI1BUF = 0xFF;                              //Data Out - Logic ones
	while(!SPI1STATbits.SPIRBF);                     //Wait until cycle complete
	return(SPI1BUF);                             //Return with byte read 
}//end ReadMedia


/******************************************************************************
 * Function:        BYTE StartupCard(DISK *dsk, CARDSTATUS *CardStatus)
 *
 * PreCondition:    SocketInitialize called
 *
 * Input:			dsk			- Disk to be mounted
 *
 * Output:			CE_GOOD				- Disk set up successfully
 *					CE_NOT_PRESENT		- Card not inserted
 *
 * Side Effects:    None
 *
 * Overview:        Startup the SDMMC Card
 *
 * Note:            None
 *****************************************************************************/

BYTE StartupCard(DISK *dsk, CARDSTATUS *CardStatus)
{
	CETYPE	        error;
	MMCSTATE        Flag;
	BYTE *	buffer = gblSDMMCBuf;
	CardStatus->_word = 0x00;

	CardStatus->CS_Reset      = TRUE;

	if((error = DISKmount( dsk, buffer, &Flag)) == CE_GOOD)
	{
		CardStatus->CS_Inserted   = TRUE;

		//set the type and write protect stuff
		CardStatus->CS_SDMMC  = ((Flag.isSDMMC) ? TRUE : FALSE);
		CardStatus->CS_WP     = ((Flag.isWP) ? TRUE : FALSE);
	}
	else
	{
		// there was an issue so turn off the card
		StopCard(dsk, CardStatus);

		CardStatus->CS_Failure = TRUE;
	}

	return(error);
}


/******************************************************************************
 * Function:        BYTE DISKmount ( DISK *dsk, BYTE* b, MMCSTATE *Flag)
 *
 * PreCondition:    SocketInitialize function has been executed.
 *
 * Input:           dsk		- The disk to be mounted
 *					b		- The buffer of to be assigned to the disk
 *					Flag	- Flag structure of card conditions
 *
 * Output:          CE_GOOD 		- Disk mounted
 *					CE_INIT_ERROR	- Initialization error has occured
 *
 * Side Effects:    None
 *
 * Overview:        Will mount only the first partition on the disk/card
 *
 * Note:            None
 *****************************************************************************/

BYTE DISKmount( DISK *dsk, BYTE* b, MMCSTATE *Flag)
{
	BYTE        error = CE_GOOD;

	dsk->mount = FALSE; // default invalid
	dsk->buffer = b;    // assign buffer

	// Initialize the sdmmc card
	if(MediaInitialize() != TRUE)
	{
		error = CE_INIT_ERROR;
	}
	else
	{
		// Load the Master Boot Record (partition)
		error = LoadMBR(dsk);
		if((error) == CE_GOOD)

⌨️ 快捷键说明

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