www.pudn.com > Test_rtl8019_SRAM.zip > mmc.c, change:2009-09-03,size:10288b


/*####################################################################################### 
Connect AVR to MMC/SD  
 
Copyright (C) 2004 Ulrich Radig 
 
Bei Fragen und Verbesserungen wendet euch per EMail an 
 
mail@ulrichradig.de 
 
oder im Forum meiner Web Page : www.ulrichradig.de 
 
Dieses Programm ist freie Software. Sie können es unter den Bedingungen der  
GNU General Public License, wie von der Free Software Foundation veröffentlicht,  
weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder  
(nach Ihrer Option) jeder späteren Version.  
 
Die Veröffentlichung dieses Programms erfolgt in der Hoffnung,  
daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,  
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT  
FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.  
 
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem  
Programm erhalten haben.  
Falls nicht, schreiben Sie an die Free Software Foundation,  
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.  
#######################################################################################*/ 
 
#include <stdio.h> 
#include <string.h>	 
#include <avr/io.h>	 
#include <avr/eeprom.h>	 
 
#include "EtherBaz_Define.h" 
#include "mmc.h" 
#include "spi_def.h" 
#include "fat.h" 
 
//############################################################################ 
//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE) 
U08 mmc_init() 
//############################################################################ 
{ 
	U08 Timeout = 0; 
	U08 a, b; 
	 
	//Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde 
//	SPI_DDR &=~(1<<SPI_DI);			//Setzen von Pin MMC_DI auf Input 
//	SPI_DDR |= (1<<SPI_Clock);		//Setzen von Pin MMC_Clock auf Output 
//	SPI_DDR |= (1<<SPI_DO);			//Setzen von Pin MMC_DO auf Output 
//	SPI_DDR |= (1<<MMC_CS);			//Setzen von Pin MMC_Chip_Select auf Output 
	//SPI_DDR |= (1<<SPI_SS); 
	SPI_PORT |= (1<<MMC_CS);		//Setzt den Pin MMC_Chip_Select auf High Pegel 
 
	for(a=0;a<200;a++) 
	 { 
 	  nop(); 
	 };		//Wartet eine kurze Zeit 
 
	#if SPI_Mode 
		//Aktiviren des SPI - Bus, Clock = Idel LOW 
		//SPI Clock teilen durch 128 
		SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); //Enable SPI, SPI in Master Mode	 
		SPSR = (1<<SPI2X); 
	#endif 
	 
	//Initialisiere MMC/SD-Karte in den SPI-Mode 
	for (b = 0;b<0x0f;b++) //Sendet min 74+ Clocks an die MMC/SD-Karte 
	 { 
	  SPI_write_byte(0xff); 
	 } 
	 
	//Sendet Commando CMD0 an MMC/SD-Karte 
	U08 CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95}; 
	while(mmc_write_command (CMD) !=1) 
	{ 
	 if (Timeout++ > 200) 
	  { 
	   return(1); //Abbruch bei Commando1 (Return Code1) 
	  } 
	} 
	//Sendet Commando CMD1 an MMC/SD-Karte 
	Timeout = 0; 
	CMD[0] = 0x41;//Commando 1 
	CMD[5] = 0xFF; 
	while( mmc_write_command (CMD) !=0) 
	{ 
	 if (Timeout++ > 100) 
	  { 
	   return(2); //Abbruch bei Commando2 (Return Code2) 
	  } 
	} 
	#if SPI_Mode 
		//SPI Bus auf max Geschwindigkeit 
		SPCR &= ~((1<<SPR0) | (1<<SPR1)); 
		SPSR = SPSR|(1<<SPI2X); 
	#endif 
	 
	//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv) 
	MMC_Disable(); 
	return(0); 
} 
 
//############################################################################ 
//Sendet ein Commando an die MMC/SD-Karte 
U08 mmc_write_command (U08 *cmd) 
//############################################################################ 
{ 
	U08 tmp = 0xff; 
	U16 Timeout = 0; 
	U8 a; 
 
	//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)  
	MMC_Disable(); 
 
	//sendet 8 Clock Impulse 
	SPI_write_byte(0xFF); 
 
	//set MMC_Chip_Select to low (MMC/SD-Karte Aktiv) 
	MMC_Enable(); 
 
	//sendet 6 Byte Commando 
	for (a = 0;a<0x06;a++) //sendet 6 Byte Commando zur MMC/SD-Karte 
	 { 
	  SPI_write_byte(*cmd++); 
	 } 
 
	//Wartet auf ein gültige Antwort von der MMC/SD-Karte 
	while (tmp == 0xff)	 
	 { 
	  tmp = mmc_read_byte(); 
	  if (Timeout++ > 500) 
	   { 
	    break; //Abbruch da die MMC/SD-Karte nicht Antwortet 
	   } 
	 } 
	return(tmp); 
} 
 
//############################################################################ 
//Routine zum Empfangen eines Bytes von der MMC-Karte  
U08 mmc_read_byte (void) 
//############################################################################ 
{ 
	U08 Byte = 0; 
#if SPI_Mode	//Routine für Hardware SPI 
	SPDR = 0xff; 
	while(!(SPSR & (1<<SPIF))){}; 
	Byte = SPDR; 
 
#else			//Routine für Software SPI 
	for (U08 a=8; a>0; a--) //das Byte wird Bitweise nacheinander Empangen MSB First 
		{ 
		SPI_PORT &=~(1<<SPI_Clock); //erzeugt ein Clock Impuls (Low)  
		 
		if (bit_is_set(SPI_Read,SPI_DI) > 0) //Lesen des Pegels von MMC_DI 
				{ 
				Byte |= (1<<(a-1)); 
				} 
			else 
				{ 
				Byte &=~(1<<(a-1)); 
				} 
		SPI_PORT |=(1<<SPI_Clock); //setzt Clock Impuls wieder auf (High)		 
		} 
#endif 
	return (Byte); 
} 
 
 
//############################################################################ 
//Routine zum schreiben eines Blocks(512Byte) auf die MMC/SD-Karte 
U08 mmc_write_sector (U32 addr,U08 *Buffer) 
//############################################################################ 
{ 
	U08 tmp; 
	U16 a; 
	//Commando 24 zum schreiben eines Blocks auf die MMC/SD - Karte 
	U08 cmd[] = {0x58,0x00,0x00,0x00,0x00,0xFF};  
	 
	/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben, 
	  addr wird von Blocks zu Bytes umgerechnet danach werden  
	  diese in das Commando eingefügt*/ 
	   
	addr = addr << 9; //addr = addr * 512 
	 
	cmd[1] = ((addr & 0xFF000000) >>24 ); 
	cmd[2] = ((addr & 0x00FF0000) >>16 ); 
	cmd[3] = ((addr & 0x0000FF00) >>8 ); 
 
	//Sendet Commando cmd24 an MMC/SD-Karte (Write 1 Block/512 Bytes) 
	tmp = mmc_write_command (cmd); 
	if (tmp != 0) 
		{ 
		return(tmp); 
		} 
			 
	//Wartet einen Moment und sendet einen Clock an die MMC/SD-Karte 
	for (a=0;a<100;a++) 
		{ 
		mmc_read_byte(); 
		} 
	 
	//Sendet Start Byte an MMC/SD-Karte 
	SPI_write_byte(0xFE);	 
	 
	//Schreiben des Bolcks (512Bytes) auf MMC/SD-Karte 
	for (a=0;a<512;a++) 
		{ 
		SPI_write_byte(*Buffer++); 
		} 
	 
	//CRC-Byte schreiben 
	SPI_write_byte(0xFF); //Schreibt Dummy CRC 
	SPI_write_byte(0xFF); //CRC Code wird nicht benutzt 
	 
	//Wartet auf MMC/SD-Karte Bussy 
	while (mmc_read_byte() != 0xff){}; 
	 
	//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv) 
	MMC_Disable(); 
	 
return(0); 
} 
 
//############################################################################ 
//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes) 
void mmc_read_block(U08 *cmd,U08 *Buffer,U16 Bytes) 
//############################################################################ 
{	 
 
U16 a; 
 
	//Sendet Commando cmd an MMC/SD-Karte 
	if (mmc_write_command (cmd) != 0) 
			{ 
			 return; 
			} 
 
	//Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte) 
	 
	while (mmc_read_byte() != 0xfe){}; 
 
	//Lesen des Bolcks (normal 512Bytes) von MMC/SD-Karte 
	for (a=0;a<Bytes;a++) 
		{ 
		*Buffer++ = mmc_read_byte(); 
		} 
	//CRC-Byte auslesen 
	mmc_read_byte();//CRC - Byte wird nicht ausgewertet 
	mmc_read_byte();//CRC - Byte wird nicht ausgewertet 
	 
	//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv) 
	MMC_Disable(); 
	 
	return; 
} 
 
//############################################################################ 
//Routine zum lesen eines Blocks(512Byte) von der MMC/SD-Karte 
U08 mmc_read_sector (U32 addr,U08 *Buffer) 
//############################################################################ 
{	 
	//Commando 16 zum lesen eines Blocks von der MMC/SD - Karte 
	U08 cmd[] = {0x51,0x00,0x00,0x00,0x00,0xFF};  
	 
	/*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben, 
	  addr wird von Blocks zu Bytes umgerechnet danach werden  
	  diese in das Commando eingefügt*/ 
	   
	addr = addr << 9; //addr = addr * 512 
 
	cmd[1] = ((addr & 0xFF000000) >>24 ); 
	cmd[2] = ((addr & 0x00FF0000) >>16 ); 
	cmd[3] = ((addr & 0x0000FF00) >>8 ); 
 
    mmc_read_block(cmd,Buffer,512); 
 
	return(0); 
} 
 
//############################################################################ 
//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes) 
U08 mmc_read_cid (U08 *Buffer) 
//############################################################################ 
{ 
	//Commando zum lesen des CID Registers 
	U08 cmd[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};  
	 
	mmc_read_block(cmd,Buffer,16); 
 
	return(0); 
} 
 
//############################################################################ 
//Routine zum lesen des CSD Registers von der MMC/SD-Karte (16Bytes) 
U08 mmc_read_csd (U08 *Buffer) 
//############################################################################ 
{	 
	//Commando zum lesen des CSD Registers 
	U08 cmd[] = {0x49,0x00,0x00,0x00,0x00,0xFF}; 
	 
	mmc_read_block(cmd,Buffer,16); 
 
	return(0); 
} 
 
 
 
// *********************************************************** 
//  Odczyt i obliczenie pojemnoœci karty w sektorach 
// *********************************************************** 
uint32 MMC_SD_ReadCapacity() 
{ 
	uint8 r1; 
	uint16 i; 
	uint16 temp; 
//	uint8 buffer[16]; 
	uint32 Capacity; 
 
	//Commando zum lesen des CSD Registers 
	U08 cmd[] = {0x49,0x00,0x00,0x00,0x00,0xFF}; 
	mmc_read_block(cmd,mmc_scratch,16); 
 
/*********************************/ 
//	C_SIZE 
	i = mmc_scratch[6]&0x03; 
	i<<=8; 
	i += mmc_scratch[7]; 
	i<<=2; 
	i += ((mmc_scratch[8]&0xc0)>>6); 
 
/**********************************/ 
//  C_SIZE_MULT 
 
	r1 = mmc_scratch[9]&0x03; 
	r1<<=1; 
	r1 += ((mmc_scratch[10]&0x80)>>7); 
 
 
/**********************************/ 
// BLOCKNR 
 
	r1+=2; 
 
	temp = 1; 
	while(r1) 
	{ 
		temp*=2; 
		r1--; 
	} 
	 
	Capacity = ((uint32)(i+1))*((uint32)temp); 
 
///////////////////////// 
// READ_BL_LEN 
 
	i = mmc_scratch[5]&0x0f; 
 
/*************************/ 
//BLOCK_LEN 
 
	temp = 1; 
	while(i) 
	{ 
		temp*=2; 
		i--; 
	} 
/************************/ 
 
 
/************** formula of the capacity ******************/ 
// 
//  memory capacity = BLOCKNR * BLOCK_LEN 
//	 
//	BLOCKNR = (C_SIZE + 1)* MULT 
// 
//           C_SIZE_MULT+2 
//	MULT = 2 
// 
//               READ_BL_LEN 
//	BLOCK_LEN = 2 
/**********************************************/ 
 
//The final result 
	 
	Capacity *= (uint32)temp;	  
	return Capacity;		 
}