Esempio n. 1
0
//***************************************************************************
//Function: get cluster entry value from FAT to find out the next cluster in the chain
//or set new cluster entry in FAT
//Arguments: 1. current cluster number, 2. get_set (=GET, if next cluster is to be found or = SET,
//if next cluster is to be set 3. next cluster number, if argument#2 = SET, else 0
//return: next cluster number, if if argument#2 = GET, else 0
//****************************************************************************
unsigned long getSetNextCluster (unsigned long clusterNumber,
                                 unsigned char get_set,
                                 unsigned long clusterEntry)
{
    unsigned int  FATEntryOffset;
    unsigned long *FATEntryValue;
    unsigned long FATEntrySector;
    unsigned char retry = 0;

    //get sector number of the cluster entry in the FAT
    FATEntrySector = unusedSectors + reservedSectorCount + ((clusterNumber * 4) / bytesPerSector) ;
    //get the offset address in that sector number
    FATEntryOffset = (unsigned int) ((clusterNumber * 4) % bytesPerSector);
    //read the sector into a buffer
    while(retry <10)
    {
        if(!SD_readSingleBlock(FATEntrySector)) break;
        retry++;
    }

    //get the cluster address from the buffer
    FATEntryValue = (unsigned long *) &buffer[FATEntryOffset];

    if(get_set == GET) return ((*FATEntryValue) & 0x0fffffff);

    *FATEntryValue = clusterEntry;   //for setting new value in cluster entry in FAT

    SD_writeSingleBlock(FATEntrySector);

    return 0;
}
Esempio n. 2
0
//********************************************************************************************
//Function: to get or set next free cluster or total free clusters in FSinfo sector of SD card
//Arguments: 1.flag:TOTAL_FREE or NEXT_FREE,
//           2.flag: GET or SET
//           3.new FS entry, when argument2 is SET; or 0, when argument2 is GET
//return: -next free cluster, if arg1 is NEXT_FREE & arg2 is GET
//        -total number of free clusters, if arg1 is TOTAL_FREE & arg2 is GET
//        -0xffffffff, if any error or if arg2 is SET
//********************************************************************************************
unsigned long getSetFreeCluster(unsigned char totOrNext, unsigned char get_set, unsigned long FSEntry)
{
    struct FSInfo_Structure *FS = (struct FSInfo_Structure *) &buffer;
    unsigned char error;

    SD_readSingleBlock(unusedSectors + 1);

    if((FS->leadSignature != 0x41615252) || (FS->structureSignature != 0x61417272) || (FS->trailSignature !=0xaa550000))
        return 0xffffffff;


    if(get_set == GET)
    {
        if(totOrNext == TOTAL_FREE) return(FS->freeClusterCount);
        else // when totOrNext = NEXT_FREE
            return(FS->nextFreeCluster);
    }
    else
    {
        if(totOrNext == TOTAL_FREE) FS->freeClusterCount = FSEntry;
        else // when totOrNext = NEXT_FREE
            FS->nextFreeCluster = FSEntry;
        error = SD_writeSingleBlock(unusedSectors + 1);
        return error;   //update FSinfo
    }
    return 0xffffffff;
}
Esempio n. 3
0
/*
  * fct_SDCard.c
 *
 *  Created on: 21 juin 2016
 *      Author: formateur
 */

#include <avr/io.h>
#include <util/delay.h>

#include "../lib/usart.h"
#include "../lib/fct_spi.h"
#include "../lib/fct_SDCard.h"



//******************************************************************
//Function	: to initialize the SD/SDHC card in SPI mode
//Arguments	: none
//return	: unsigned char; will be 0 if no error,
// 			  otherwise the response byte will be sent
//******************************************************************
unsigned char SD_init(void)
{
	unsigned char response, SD_version;
	unsigned int retry=0 ;
	int i=0;

	//Spi init
	spi_init();																/**send init on spi peripheral**/

	for(i=0;i<10;i++){
		SD_CS_ASSERT;														/**set chip select*/
		do
		{
		   response = SD_sendCommand(GO_IDLE_STATE, 0); 					/**send software reset */
		   retry++;
		   if(retry>0x20){
			   //
			  USART0_print("\rpas de carte\n");
			   //
			   return 1;  													/**time out, card not detected*/
		   }


		} while(response != 0x01);											/**response= 0x01 : card in idle state and no error*/

		SD_CS_DEASSERT;
		SPI_transmit (0xff);												/**1st byte transmission  */
		SPI_transmit (0xff);												/**2nd byte transmission */

		retry = 0;															/**reset retries counter*/

		SD_version = 2; //default set to SD compliance with ver2.x;
						//this may change after checking the next command
		do
		{
		response = SD_sendCommand(SEND_IF_COND,0x000001AA); 				/**check power supply status,for SDHC card*/
		retry++;
		if(retry>0xfe)
		   {
			  SD_version = 1;
			  cardType = 1;
			  break;
		   } //time out

		}while(response != 0x01);

		retry = 0;

		do
		{
		response = SD_sendCommand(APP_CMD,0); //CMD55, must be sent before sending any ACMD command
		response = SD_sendCommand(SD_SEND_OP_COND,0x40000000); //ACMD41

		retry++;
		if(retry>0xfe)
		   {
			  USART0_print("\rinitialisation a échoué\n");
			  return 2;  //time out, card initialization failed
		   }

		}while(response != 0x00);


		retry = 0;
		SDHC_flag = 0;

		if (SD_version == 2)
		{
		   do
		   {
			 response = SD_sendCommand(READ_OCR,0);
			 retry++;
			 if(retry>0xfe)
			 {
			   cardType = 0;
			   break;
			 } //time out

		   }while(response != 0x00);

		   if(SDHC_flag == 1) cardType = 2;
		   else cardType = 3;
		}

		//SD_sendCommand(CRC_ON_OFF, OFF); //disable CRC; deafault - CRC disabled in SPI mode
		//SD_sendCommand(SET_BLOCK_LEN, 512); //set block size to 512; default size is 512

		//
		switch (cardType)													/** switch for card type (to check communication with the card)*/
		{
		case 1 :  USART0_print("\rver1.x\n");break;
		case 2 :  USART0_print("\rSDHC\n");break;
		case 3 :  USART0_print("\rver2.x\n");break;
		default : USART0_print("runknown Sd card\n");
		}
		//

	return 0;break;															/**successful return*/
	}
	_delay_ms(1);															/**give some time to end the init*/
	return 0;
}


//******************************************************************
//Function	: to send a command to SD card
//Arguments	: unsigned char (8-bit command value)
// 			  & unsigned long (32-bit command argument)
//return	: unsigned char; response byte
//******************************************************************

unsigned char SD_sendCommand(unsigned char cmd, unsigned long arg)
{
	unsigned char response, retry=0, status;

	//SD card accepts byte address while SDHC accepts block address in multiples of 512
	//so, if it's SD card we need to convert block address into corresponding byte address by
	//multipying it with 512. which is equivalent to shifting it left 9 times
	//following 'if' loop does that

		if(SDHC_flag == 0)
			if(cmd == READ_SINGLE_BLOCK     ||
			   cmd == READ_MULTIPLE_BLOCKS  ||
			   cmd == WRITE_SINGLE_BLOCK    ||
			   cmd == WRITE_MULTIPLE_BLOCKS ||
			   cmd == ERASE_BLOCK_START_ADDR||
			   cmd == ERASE_BLOCK_END_ADDR )
			   {
				 	 arg = arg << 9;
			   }

		SD_CS_ASSERT;

		SPI_transmit(cmd | 0x40); //send command, first two bits always '01'
		SPI_transmit(arg>>24);
		SPI_transmit(arg>>16);
		SPI_transmit(arg>>8);
		SPI_transmit(arg);

		if(cmd == SEND_IF_COND)	 //it is compulsory to send correct CRC for CMD8 (CRC=0x87) & CMD0 (CRC=0x95)
			SPI_transmit(0x87);    //for remaining commands, CRC is ignored in SPI mode
		else
			SPI_transmit(0x95);

		while((response = SPI_receive()) == 0xff) //wait response
			if(retry++ > 0xfe) break; //time out error

		if(response == 0x00 && cmd == 58)  //checking response of CMD58
		{
			  status = SPI_receive() & 0x40;     //first byte of the OCR register (bit 31:24)
			  if(status == 0x40) SDHC_flag = 1;  //we need it to verify SDHC card
			  else SDHC_flag = 0;

			  SPI_receive(); //remaining 3 bytes of the OCR register are ignored here
			  SPI_receive(); //one can use these bytes to check power supply limits of SD
			  SPI_receive();
		}

		SPI_receive(); //extra 8 CLK
		SD_CS_DEASSERT;


	return response; //return state
}

//*****************************************************************
//Function	: to erase specified no. of blocks of SD card
//Arguments	: none
//return	: unsigned char; will be 0 if no error,
// 			  otherwise the response byte will be sent
//*****************************************************************

unsigned char SD_erase (unsigned long startBlock, unsigned long totalBlocks)
{
	unsigned char response;

		response = SD_sendCommand(ERASE_BLOCK_START_ADDR, startBlock); 						/**send address of starting block*/
		if(response != 0x00) 																/**check the SD status: 0x00 - OK (No flags set)*/
		  return response;

		response = SD_sendCommand(ERASE_BLOCK_END_ADDR,(startBlock + totalBlocks - 1));		/**send adress of end block*/
		if(response != 0x00)																/**check the SD status: 0x00 - OK (No flags set)*/
		  return response;

		response = SD_sendCommand(ERASE_SELECTED_BLOCKS, 0); 								/**erase all selected blocks*/
		if(response != 0x00)																/**check SD status: 0x00 - OK (No flags set)*/
		  return response;

	return 0; //normal return
}

//******************************************************************
//Function	: to read a single block from SD card
//Arguments	: none
//return	: unsigned char; will be 0 if no error,
// 			  otherwise the response byte will be sent
//******************************************************************

unsigned char SD_readSingleBlock(unsigned long startBlock)
{
	unsigned char response;
	unsigned int i, retry=0;

		 response = SD_sendCommand(READ_SINGLE_BLOCK, startBlock); 							/**read a Block command*/

		 if(response != 0x00) return response; 												/**check if SD status: 0x00 - OK (no flag activated)*/

		SD_CS_ASSERT;

		retry = 0;
		while(SPI_receive() != 0xfe) 														/**wait for start block to get the 0xfe value*/
		  if(retry++ > 0xfffe){
			  	 	 SD_CS_DEASSERT;
			  	 	 return 1;  } 															/**function output  time-out*/

		for(i=0; i<512; i++) 																/**read every 512 bytes*/
			buffer[i] = SPI_receive();


		SPI_receive(); 																		/**let 8 clock pulses*/
		SD_CS_DEASSERT;

	return 0;
}

//******************************************************************
//Function	: to write to a single block of SD card
//return	: unsigned char; will be 0 if no error,
// 			  otherwise the response byte will be sent
//******************************************************************

unsigned char SD_writeSingleBlock(unsigned long startBlock)
{
	unsigned char response;
	unsigned int i, retry=0;

		 response = SD_sendCommand(WRITE_SINGLE_BLOCK, startBlock); 						/** block's writing command*/

		 if(response != 0x00) return response; 												/**check if SD status: 0x00 - OK (no flag activated)*/

		SD_CS_ASSERT;

		SPI_transmit(0xfe);     															/**send the 0xfe block (page 197 datasheet SD)*/

		for(i=0; i<512; i++)    															/**send the 512 bytes data*/
			SPI_transmit(buffer[i]);

		SPI_transmit(0xff);     //transmit dummy CRC (16-bit), CRC is ignored here
		SPI_transmit(0xff);

		response = SPI_receive();

		if( (response & 0x1f) != 0x05)														 /**response= 0xXXX0AAA1 ; if: {	AAA='010' - data accepted
		                              						 	 																AAA='101'-data rejected due to CRC error
																																AAA='110'-data rejected due to write error
																															}*/
		{
			SD_CS_DEASSERT;
			return response;
		}

		while(!SPI_receive()) 																/**wait for SD card to complete the writing and go to get idle state*/
			if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;}									/**function output time-out*/

		SD_CS_DEASSERT;
		SPI_transmit(0xff);   																/**allow a 8 clock cycles delay before CS line reaffirming*/
		SD_CS_ASSERT;         																/**CS line reaffirming to check if the card is still busy*/

		while(!SPI_receive()) 																/**wait for SD card to complete the writing and go to get idle state*/
			if(retry++ > 0xfffe){
				SD_CS_DEASSERT; return 1;
			}

		SD_CS_DEASSERT;

	return 0;
}



#ifndef FAT_TESTING_ONLY

//***************************************************************************/
//Function	: to read multiple blocks from SD card & send every block to UART
//Arguments	: none
//return	: unsigned char; will be 0 if no error,
// 			  otherwise the response byte will be sent
//****************************************************************************/
unsigned char SD_readMultipleBlock (unsigned long startBlock, unsigned long totalBlocks)
{
unsigned char response;
unsigned int i, retry=0;

retry = 0;

response = SD_sendCommand(READ_MULTIPLE_BLOCKS, startBlock); //write a Block command

if(response != 0x00) return response; //check for SD status: 0x00 - OK (No flags set)

SD_CS_ASSERT;

while( totalBlocks )
{
  retry = 0;
  while(SPI_receive() != 0xfe) //wait for start block token 0xfe (0x11111110)
  if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;} //return if time-out

  for(i=0; i<512; i++) //read 512 bytes
    buffer[i] = SPI_receive();

  SPI_receive(); //receive incoming CRC (16-bit), CRC is ignored here
  SPI_receive();

  SPI_receive(); //extra 8 cycles
  TX_NEWLINE;
  transmitString_F(PSTR(" --------- "));
  TX_NEWLINE;

  for(i=0; i<512; i++) //send the block to UART
  {
    if(buffer[i] == '~') break;
    transmitByte ( buffer[i] );
  }

  TX_NEWLINE;
  transmitString_F(PSTR(" --------- "));
  TX_NEWLINE;
  totalBlocks--;
}

SD_sendCommand(STOP_TRANSMISSION, 0); //command to stop transmission
SD_CS_DEASSERT;
SPI_receive(); //extra 8 clock pulses

return 0;
}

//***************************************************************************/
//Function: to receive data from UART and write to multiple blocks of SD card
//Arguments: none
//return: unsigned char; will be 0 if no error,
// otherwise the response byte will be sent
//****************************************************************************/
unsigned char SD_writeMultipleBlock(unsigned long startBlock, unsigned long totalBlocks)
{
unsigned char response, data;
unsigned int i, retry=0;
unsigned long blockCounter=0, size;

response = SD_sendCommand(WRITE_MULTIPLE_BLOCKS, startBlock); //write a Block command

if(response != 0x00) return response; //check for SD status: 0x00 - OK (No flags set)

SD_CS_ASSERT;

TX_NEWLINE;
transmitString_F(PSTR(" Enter text (End with ~): "));
TX_NEWLINE;

while( blockCounter < totalBlocks )
{//e. Cette librairie est dépendante de la librairie SPI. Voici le code à m
   i=0;
   do
   {
     data = receiveByte();
     if(data == 0x08)	//'Back Space' key pressed
	 {
	   if(i != 0)
	   {
	     transmitByte(data);
	     transmitByte(' ');
	     transmitByte(data);
	     i--;
		 size--;
	   }
	   continue;
	 }
     transmitByte(data);
     buffer[i++] = data;
     if(data == 0x0d)
     {
        transmitByte(0x0a);
        buffer[i++] = 0x0a;
     }
	 if(i == 512) break;
   }while (data != '~');

   TX_NEWLINE;
   transmitString_F(PSTR(" ---- "));
   TX_NEWLINE;

   SPI_transmit(0xfc); //Send start block token 0xfc (0x11111100)

   for(i=0; i<512; i++) //send 512 bytes data
     SPI_transmit( buffer[i] );

   SPI_transmit(0xff); //transmit dummy CRC (16-bit), CRC is ignored here
   SPI_transmit(0xff);

   response = SPI_receive();
   if( (response & 0x1f) != 0x05) //response= 0xXXX0AAA1 ; AAA='010' - data accepted
   {                              //AAA='101'-data rejected due to CRC error
      SD_CS_DEASSERT;             //AAA='110'-data rejected due to write error
      return response;
   }

   while(!SPI_receive()) //wait for SD card to complete writing and get idle
     if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;}

   SPI_receive(); //extra 8 bits
   blockCounter++;
}

SPI_transmit(0xfd); //send 'stop transmission token'

retry = 0;
	   if(data == '~')
	   {
		  fileSize--;	//to remove the last entered '~' character
		  i--;

		  for(;i<512;i++)  //fill the rest of the buffer with 0x00
			buffer[i]= 0x00;

		  error = SD_writeSingleBlock (startBlock);

		  txString(_COM1, "data = ~\n");
		  break;
	   }
while(!SPI_receive()) //wait for SD card to complete writing and get idle
   if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;}

SD_CS_DEASSERT;
SPI_transmit(0xff); //just spend 8 clock cycle delay before reasserting the CS signal
SD_CS_ASSERT; //re assertion of the CS signal is required to verify if card is still busy

while(!SPI_receive()) //wait for SD card to complete writing and get idle
   if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;}
SD_CS_DEASSERT;

return 0;
}
Esempio n. 4
0
File: SD_main.c Progetto: nandra/AVR
int main(void)
{
unsigned char option, error, data, FAT32_active;
unsigned int i;
unsigned char fileName[13];

_delay_ms(100);  //delay for VCC stabilization

init_devices();

PORTD |= 0x04; //switching ON the LED (for testing purpose only)

TX_NEWLINE;
TX_NEWLINE;
transmitString_F (PSTR("***********************************"));
TX_NEWLINE;
transmitString_F (PSTR(" Dharmani's microSD Card Testing.."));
TX_NEWLINE;
transmitString_F (PSTR("***********************************"));
TX_NEWLINE;

SD_init();
SPI_HIGH_SPEED;   //SCK - 4 MHz

_delay_ms(1);

FAT32_active = 1;
error = getBootSectorData (); //read boot sector and keep necessary data in global variables
if(error)  
{
  transmitString_F (PSTR("FAT32 not found!"));  //FAT32 incompatible drive
  FAT32_active = 0;
}

while(1)
{
TX_NEWLINE;
transmitString_F(PSTR("Press any key..."));
TX_NEWLINE;
option = receiveByte();
TX_NEWLINE;
transmitString_F(PSTR("> 0 : Erase Blocks"));
TX_NEWLINE;
transmitString_F(PSTR("> 1 : Write single Block"));
TX_NEWLINE;
transmitString_F(PSTR("> 2 : Read single Block"));

#ifndef FAT_TESTING_ONLY
TX_NEWLINE;
transmitString_F(PSTR("> 3 : Write multiple Blocks"));
TX_NEWLINE;
transmitString_F(PSTR("> 4 : Read multiple Blocks"));
#endif


TX_NEWLINE;
transmitString_F(PSTR("> 5 : Get file list"));
TX_NEWLINE;
transmitString_F(PSTR("> 6 : Read File"));
TX_NEWLINE;
transmitString_F(PSTR("> 7 : Create File"));
TX_NEWLINE;
transmitString_F(PSTR("> 8 : Delete File"));
TX_NEWLINE;
transmitString_F(PSTR("> 9 : Read SD Memory Capacity (Total/Free)"));

TX_NEWLINE;
TX_NEWLINE;
transmitString_F(PSTR("> Select Option (0-9): "));


/*WARNING: If option 0, 1 or 3 is selected, the card may not be detected by PC/Laptop again,
as it disturbs the FAT format, and you may have to format it again with FAT32.
This options are given for learning the raw data transfer to & from the SD Card*/

option = receiveByte();
transmitByte(option);

if(option >= 0x35 && option <= 0x39)  //options 5 to 9 disabled if FAT32 not found
{
  if(!FAT32_active)
  {
    TX_NEWLINE;
    TX_NEWLINE;
      transmitString_F(PSTR("FAT32 options disabled!"));
      continue;
  }
}


if((option >= 0x30) && (option <=0x34)) //get starting block address for options 0 to 4
{
TX_NEWLINE;
TX_NEWLINE;
transmitString_F(PSTR("Enter the Block number (0000-9999):"));
data = receiveByte(); transmitByte(data);
startBlock = (data & 0x0f) * 1000;
data = receiveByte(); transmitByte(data);
startBlock += (data & 0x0f) * 100;
data = receiveByte(); transmitByte(data);
startBlock += (data & 0x0f) * 10;
data = receiveByte(); transmitByte(data);
startBlock += (data & 0x0f);
TX_NEWLINE;
}

totalBlocks = 1;

#ifndef FAT_TESTING_ONLY

if((option == 0x30) || (option == 0x33) || (option == 0x34)) //get total number of blocks for options 0, 3 or 4
{
TX_NEWLINE;
TX_NEWLINE;
transmitString_F(PSTR("How many blocks? (000-999):"));
data = receiveByte(); transmitByte(data);
totalBlocks = (data & 0x0f) * 100;
data = receiveByte(); transmitByte(data);
totalBlocks += (data & 0x0f) * 10;
data = receiveByte(); transmitByte(data);
totalBlocks += (data & 0x0f);
TX_NEWLINE;
}
#endif

switch (option)
{
case '0': //error = SD_erase (block, totalBlocks);
          error = SD_erase (startBlock, totalBlocks);
          TX_NEWLINE;
          if(error)
              transmitString_F(PSTR("Erase failed.."));
          else
              transmitString_F(PSTR("Erased!"));
          break;

case '1': TX_NEWLINE;
          transmitString_F(PSTR(" Enter text (End with ~):"));
          i=0;
            do
            {
                data = receiveByte();
                transmitByte(data);
                buffer[i++] = data;
                if(data == '\r')    //append 'newline' character whenevr 'carriage return' is received
                {
                    transmitByte('\n');
                    buffer[i++] = '\n';
                }
                if(i == 512) break;
            }while (data != '~');

            error = SD_writeSingleBlock (startBlock);
            TX_NEWLINE;
            TX_NEWLINE;
            if(error)
                transmitString_F(PSTR("Write failed.."));
            else
                transmitString_F(PSTR("Write successful!"));
            break;

case '2': error = SD_readSingleBlock (startBlock);
          TX_NEWLINE;
          if(error)
            transmitString_F(PSTR("Read failed.."));
          else
          {
            for(i=0;i<512;i++)
            {
                if(buffer[i] == '~') break;
                transmitByte(buffer[i]);
            }
            TX_NEWLINE;
            TX_NEWLINE;
            transmitString_F(PSTR("Read successful!"));
          }

          break;
//next two options will work only if following macro is cleared from SD_routines.h
#ifndef FAT_TESTING_ONLY

case '3':
          error = SD_writeMultipleBlock (startBlock, totalBlocks);
          TX_NEWLINE;
          if(error)
            transmitString_F(PSTR("Write failed.."));
          else
            transmitString_F(PSTR("Write successful!"));
          break;

case '4': error = SD_readMultipleBlock (startBlock, totalBlocks);
          TX_NEWLINE;
          if(error)
            transmitString_F(PSTR("Read failed.."));
          else
            transmitString_F(PSTR("Read successful!"));
          break;
#endif

case '5': TX_NEWLINE;
              findFiles(GET_LIST,0);
          break;

case '6':
case '7':
case '8': TX_NEWLINE;
              TX_NEWLINE;
          transmitString_F(PSTR("Enter file name: "));
          for(i=0; i<13; i++)
                  fileName[i] = 0x00;   //clearing any previously stored file name
          i=0;
          while(1)
          {
            data = receiveByte();
            if(data == '\r') break;  //'ENTER' key pressed
            if(data == 0x08)  //'Back Space' key pressed
            {
              if(i != 0)
              {
                transmitByte(data);
                transmitByte(' ');
                transmitByte(data);
                i--;
              }
              continue;    
            }
            if(data <0x20 || data > 0x7e) continue;  //check for valid English text character
            transmitByte(data);
            fileName[i++] = data;
            if(i==13){transmitString_F(PSTR(" file name too long..")); break;}
          }
          if(i>12) break;
      
          TX_NEWLINE;
          if(option == '6')
            readFile( READ, fileName);
          if(option == '7')
            createFile(fileName);
          if(option == '8')
            deleteFile(fileName);
          break;

case '9': memoryStatistics();
          break;

default: TX_NEWLINE;
         TX_NEWLINE;
         transmitString_F(PSTR(" Invalid option!"));
         TX_NEWLINE;
}

TX_NEWLINE;
}
return 0;
}