//*************************************************************************** //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 <<9); //read a Block command //block address converted to starting address of 512 byte Block if(response != 0x00) { //check for SD status: 0x00 - OK (No flags set) return response; } 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 initialize the SD 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 i, response, retry=0 ; SD_CS_ASSERT; do { for(i=0;i<10;i++) SPI_transmit(0xff); response = SD_sendCommand(GO_IDLE_STATE, 0);//send 'reset & go idle' command retry++; if(retry>0xfe) {transmitString_F(PSTR("SD init fail..")); return 1; }//time out } while(response != 0x01); SD_CS_DEASSERT; SPI_transmit (0xff); SPI_transmit (0xff); retry = 0; do { response = SD_sendCommand(SEND_OP_COND, 0); //activate card's initialization process response = SD_sendCommand(SEND_OP_COND, 0); //resend command (for compatibility with some cards) retry++; if(retry>0xfe) return 1; //time out }while(response); 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 return 0; //normal return }
//*************************************************************************** //Function : to read multiple blocks from SD card & send every block to UART //Arguments : none //return : uint8_t; will be 0 if no error, // otherwise the response byte will be sent //**************************************************************************** uint8_t SD_readMultipleBlock (uint32_t startBlock, uint32_t totalBlocks) { uint8_t response; uint16_t i, 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_Receive8(SD_SPI_PORT) != 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_Receive8(SD_SPI_PORT); SPI_Receive8(SD_SPI_PORT); //receive incoming CRC (16-bit), CRC is ignored here SPI_Receive8(SD_SPI_PORT); SPI_Receive8(SD_SPI_PORT); //extra 8 cycles // printf_P(PSTR("\n --------- \n")); for(i=0; i<512; i++) //send the block to UART { if(buffer[i] == '~') break; // printf("%c", buffer[i] ); } // printf_P(PSTR("\n --------- \n")); totalBlocks--; } SD_sendCommand(STOP_TRANSMISSION, 0); //command to stop transmission SD_CS_DEASSERT; SPI_Receive8(SD_SPI_PORT); //extra 8 clock pulses return(0); }
//****************************************************************** //Function : to write to a single block of SD card //Arguments : none //return : uint8_t; will be 0 if no error, // otherwise the response byte will be sent //****************************************************************** uint8_t SD_writeSingleBlock(uint32_t startBlock) //, uint8_t atomic) { uint8_t response; uint16_t i, retry=0; if(Atomic) { LIS_SD_ATOMIZE; // disable INT0 to make it quasi atomic } response = SD_sendCommand(WRITE_SINGLE_BLOCK, startBlock); //write a Block command if(response != 0x00) return(response); //check for SD status: 0x00 - OK (No flags set) SD_CS_ASSERT; SPI_Send8(0xfe,SD_SPI_PORT); //Send start block token 0xfe (0x11111110) for(i=0; i<512; i++) //send 512 bytes data SPI_Send8(buffer[i],SD_SPI_PORT); SPI_Send8(0xff,SD_SPI_PORT); //transmit dummy CRC (16-bit), CRC is ignored here SPI_Send8(0xff,SD_SPI_PORT); response = SPI_Receive8(SD_SPI_PORT); 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_Receive8(SD_SPI_PORT)) //wait for SD card to complete writing and get idle if(retry++ > 0xfffe) { SD_CS_DEASSERT; return(1); } SD_CS_DEASSERT; SPI_Send8(0xff,SD_SPI_PORT); //just spend 8 clock cycle delay before reasserting the CS line SD_CS_ASSERT; //re-asserting the CS line to verify if card is still busy while(!SPI_Receive8(SD_SPI_PORT)) //wait for SD card to complete writing and get idle if(retry++ > 0xfffe) { SD_CS_DEASSERT; return(1); } SD_CS_DEASSERT; if(Atomic) { LIS_SD_DEATOMIZE; // disable INT0 to make it quasi atomic } return(0); }
//****************************************************************** //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<<9); //read a Block command //block address converted to starting address of 512 byte Block if(response != 0x00) { //check for SD status: 0x00 - OK (No flags set) return response; } SD_CS_ASSERT; 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 clock pulses SD_CS_DEASSERT; return 0; }
//****************************************************************** //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, char buffer[BLOCK]) { 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 for SD status: 0x00 - OK (No flags set) SD_CS_ASSERT; retry = 0; while(SpiReceive() != 0xfe) //wait for start block token 0xfe (0x11111110) if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;} //return if time-out for(i=0; i<BLOCK; i++) //read 512 bytes buffer[i] = SpiReceive(); SpiReceive(); //receive incoming CRC (16-bit), CRC is ignored here SpiReceive(); SpiReceive(); //extra 8 clock pulses SD_CS_DEASSERT; return 0; }
uint8_t SD_Idle(uint8_t power) { uint8_t response, retry = 0; SPI_LOW_SPEED; SD_CS_ASSERT; do { response = SD_sendCommand(GO_IDLE_STATE, 0); //send 'reset & go idle' command retry++; if(retry>0x20) return(0xff); //time out, card not detected } while(response != 0x01); SD_CS_DEASSERT; SPI_Send8(0xff,SD_SPI_PORT); SPI_Send8(0xff,SD_SPI_PORT); if(power) { SD_Status |= SDSTAT_IDLE; return(1); } SD_POWER_OFF; // switch off power for SD card SPI_Init(SPI_SD_OFF); // disable SPI and tristate the port // SD_Status |= SDSTAT_NOTINIT; // only if first time powered on - checking the type of card after init!!! SD_Status &= ~(SDSTAT_INIT | SDSTAT_POWER); return(0); }
//****************************************************************** //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; //transmitString_F(PSTR("\nSD_readsingleBlock send command READ_SINGLE_BLOCK")); response = SD_sendCommand(READ_SINGLE_BLOCK, startBlock); //read a Block command if(response != 0x00) return response; //check for SD status: 0x00 - OK (No flags set) SD_CS_ASSERT; //transmitString_F(PSTR("\nSD_readsingleBlock SD status ")); retry = 0; while(receiveByte_SPI() != 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] = receiveByte_SPI(); //transmitString_F(PSTR("\nSD_readsingleBlock After filling buffer")); receiveByte_SPI(); //receive incoming CRC (16-bit), CRC is ignored here receiveByte_SPI(); receiveByte_SPI(); //extra 8 clock pulses SD_CS_DEASSERT; //transmitString_F(PSTR("\nSD_readsingleBlock ending")); return 0; }
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 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(char *inputbuffer,uint32_t startBlock) { unsigned char response; uint16_t i, retry=0; response = SD_sendCommand(READ_SINGLE_BLOCK, startBlock); //read a Block command if(response != 0x00) { return response; //check for SD status: 0x00 - OK (No flags set) } SPI_EnableChipSelect(); retry = 0; while(SPI_Read() != 0xfe) //wait for start block token 0xfe (0x11111110) { if(retry++ > 0xfffe) { SPI_DisableChipSelect(); return 1; //return if time-out } } for(i=0; i<512; i++) //read 512 bytes inputbuffer[i] = SPI_Read(); SPI_Read(); //receive incoming CRC (16-bit), CRC is ignored here SPI_Read(); SPI_Read(); //extra 8 clock pulses SPI_DisableChipSelect(); return 0; }
void init_SD(void) { unsigned char i, response, retry=0 ; ENABLE_SD; do { for(i=0;i<10;i++) SPI_sendchar(0xff); response = SD_sendCommand(GO_IDLE_STATE, 0); //send 'reset & go idle' command retry++; if(retry>0xfe) { printString("SD init fail..Code: "); printByte(response); printString("Retry: "); printByte(retry); printString("\r\n"); return ; } //time out } while(response != 0x01); DISABLE_SD; SPI_sendchar (0xff); SPI_sendchar (0xff); retry = 0; do { response = SD_sendCommand(SEND_OP_COND, 0); //activate card's initialization process response = SD_sendCommand(SEND_OP_COND, 0); //same command sent again for compatibility with some cards retry++; if(retry>0xfe) { printString("SD Failed: SEND_OP_COND\r\n"); return ; //time out } }while(response); SD_sendCommand(CRC_ON_OFF, 0); //disable CRC; deafault - CRC disabled in SPI mode SD_sendCommand(SET_BLOCK_LEN, 512); //set block size to 512 printString("SD initialized\r\n"); return; }
//****************************************************************** //Function: to write to a single block of SD card //Arguments: none //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<<9); //write a Block command if(response != 0x00) { //check for SD status: 0x00 - OK (No flags set) return response; } SD_CS_ASSERT; SPI_transmit(0xfe); //Send start block token 0xfe (0x11111110) 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; } } SD_CS_DEASSERT; SPI_transmit(0xff); //just spend 8 clock cycle delay before reasserting the CS line SD_CS_ASSERT; //re-asserting the CS line 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; }
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 erase specified no. of blocks of SD card //Arguments : none //return : uint8_t; will be 0 if no error, // otherwise the response byte will be sent //***************************************************************** uint8_t SD_erase (uint32_t startBlock, uint32_t totalBlocks) { uint8_t response; response = SD_sendCommand(ERASE_BLOCK_START_ADDR, startBlock); //send starting block address if(response != 0x00) //check for SD status: 0x00 - OK (No flags set) return(response); response = SD_sendCommand(ERASE_BLOCK_END_ADDR,(startBlock + totalBlocks - 1)); //send end block address if(response != 0x00) return(response); response = SD_sendCommand(ERASE_SELECTED_BLOCKS, 0); //erase all selected blocks if(response != 0x00) return(response); return(0); //normal return }
//***************************************************************** //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 starting block address if(response != 0x00) //check for SD status: 0x00 - OK (No flags set) return response; response = SD_sendCommand(ERASE_BLOCK_END_ADDR,(startBlock + totalBlocks - 1)); //send end block address if(response != 0x00) return response; response = SD_sendCommand(ERASE_SELECTED_BLOCKS, 0); //erase all selected blocks if(response != 0x00) return response; return 0; //normal return }
unsigned char SD_readSingleBlock(unsigned long startBlock) { /*int i; uint16_t ix; char r1 = Command(0x51,0,512,0xFF); for (ix = 0; ix < 50000; ix++) { if (r1 == (char)0x00) break; r1 = SPI_sendchar(0xFF); } if (r1 != (char)0x00) { return 1; } //read from the card will start after the framework while(SPI_sendchar(0xFF) != (char)0xFE); for(i=0; i < 512; i++) { while(!(SPSR & (1<<SPIF))); buffer[i] = SPDR; SPDR = SPI_sendchar(0xFF); } SPI_sendchar(0xFF); SPI_sendchar(0xFF); return 0;*/ unsigned char response; unsigned int i, retry=0; response = SD_sendCommand(READ_SINGLE_BLOCK, startBlock<<9); //read a Block command //block address converted to starting address of 512 byte Block if(response != 0x00) //check for SD status: 0x00 - OK (No flags set) return response; ENABLE_SD; retry = 0; while(SPI_sendchar(0xFF) != 0xfe) //wait for start block token 0xfe (0x11111110) { if(retry++ > 0xfffe) { printString("Error reading\r\n"); DISABLE_SD; return 1; } //return if time-out } for(i=0; i<512; i++) //read 512 bytes buffer[i] = SPI_sendchar(0xFF); SPI_sendchar(0xFF); //receive incoming CRC (16-bit), CRC is ignored here SPI_sendchar(0xFF); SPI_sendchar(0xFF); //extra 8 clock pulses DISABLE_SD; //printString("Reading succesful\r\n"); return 0; }
//****************************************************************** //Function : to write to a single block of SD card //Arguments : none //return : unsigned char; will be 0 if no error, // otherwise the response byte will be sent //****************************************************************** unsigned char SD_writeSingleBlock(char *inputbuffer,uint32_t startBlock) { unsigned char response; uint16_t i, retry=0; response = SD_sendCommand(WRITE_SINGLE_BLOCK, startBlock); //write a Block command if(response != 0x00) return response; //check for SD status: 0x00 - OK (No flags set) SPI_EnableChipSelect(); SPI_Write(0xfe); //Send start block token 0xfe (0x11111110) for(i=0; i<512; i++) //send 512 bytes data SPI_Write(inputbuffer[i]); SPI_Write(0xff); //transmit dummy CRC (16-bit), CRC is ignored here SPI_Write(0xff); response = SPI_Read(); if( (response & 0x1f) != 0x05) //response= 0xXXX0AAA1 ; AAA='010' - data accepted { //AAA='101'-data rejected due to CRC error SPI_DisableChipSelect(); //AAA='110'-data rejected due to write error return response; } while(!SPI_Read()) //wait for SD card to complete writing and get idle { if(retry++ > 0xfffe) { SPI_DisableChipSelect(); return 1; } } SPI_DisableChipSelect(); SPI_Write(0xff); //just spend 8 clock cycle delay before reasserting the CS line SPI_EnableChipSelect(); //re-asserting the CS line to verify if card is still busy while(!SPI_Read()) //wait for SD card to complete writing and get idle { if(retry++ > 0xfffe) { SPI_DisableChipSelect(); return 1; } } SPI_DisableChipSelect(); return 0; }
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; }
//****************************************************************** //Function : to read a single block from SD card //Arguments : none //return : uint8_t; will be 0 if no error, // otherwise the response byte will be sent //****************************************************************** uint8_t SD_readSingleBlock(uint32_t startBlock) //, uint8_t atomic) { uint8_t response; uint16_t i, retry=0; if(Atomic) { LIS_SD_ATOMIZE; // disable INT0 to make it quasi atomic } response = SD_sendCommand(READ_SINGLE_BLOCK, startBlock); //read a Block command if(response != 0x00) return(response); //check for SD status: 0x00 - OK (No flags set) SD_CS_ASSERT; retry = 0; while(SPI_Receive8(SD_SPI_PORT) != 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_Receive8(SD_SPI_PORT); SPI_Receive8(SD_SPI_PORT); //receive incoming CRC (16-bit), CRC is ignored here SPI_Receive8(SD_SPI_PORT); SPI_Receive8(SD_SPI_PORT); //extra 8 clock pulses SD_CS_DEASSERT; if(Atomic) { LIS_SD_DEATOMIZE; // disable INT0 to make it quasi atomic } return(0); }
unsigned char SD_writeSingleBlock(unsigned long startBlock) { uint8_t wbr; unsigned char response; unsigned int i; DISABLE_SD; response = SD_sendCommand(24, startBlock<<9); //write a Block command if(response != 0x00) //check for SD status: 0x00 - OK (No flags set) return response; ENABLE_SD; SPI_sendchar(0xfe); //Send start block token 0xfe (0x11111110) for(i=0; i<512; i++) //send 512 bytes data { SPI_sendchar(buffer[i]); //SPI_sendchar(0x12); } SPI_sendchar(0xff); //transmit dummy CRC (16-bit), CRC is ignored here SPI_sendchar(0xff); wbr = SPI_sendchar(0xff); //write block response and testing error wbr &= 0x1F; //zeroing top three indeterminate bits 0b.0001.1111 if (wbr != 0x05) { printString("ERooR\r\n"); printByte(wbr); return 1; } while(SPI_sendchar(0xFF) != (char)0xFF); //printString("File writed\r\n"); //wait for the completion of a write operation to the card DISABLE_SD; return 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; }
//****************************************************************** //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 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(unsigned char *cardType){ unsigned char i, response, SD_version; unsigned int retry=0 ; for(i=0;i<10;i++) SpiTransmit(0xff); //80 clock pulses spent before sending the first command SD_CS_ASSERT; do { response = SD_sendCommand(GO_IDLE_STATE, 0); //send 'reset & go idle' command retry++; if(retry>0x20) return 1; //time out, card not detected } while(response != 0x01); SD_CS_DEASSERT; SpiTransmit (0xff); SpiTransmit (0xff); retry = 0; 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, mandatory 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) { 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 return 0; //successful return }
uint8_t init_SdCard(uint8_t *cardType) { uint8_t i, response, sd_version; uint16_t retry=0 ; for(i=0;i<10;i++) SPI_Write(0xff); //80 clock pulses spent before sending the first command SPI_EnableChipSelect(); do { response = SD_sendCommand(GO_IDLE_STATE, 0); //send 'reset & go idle' command retry++; if(retry>0x20) return SDCARD_NOT_DETECTED; //time out, card not detected } while(response != 0x01); SPI_DisableChipSelect(); SPI_Write (0xff); SPI_Write (0xff); retry = 0; 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, mendatory for SDHC card retry++; if(retry>0xfe) { sd_version = 1; *cardType = SDCARD_TYPE_STANDARD; 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) { return SDCARD_INIT_FAILED; //time out, card initialization failed } }while(response != 0x00); retry = 0; V_SdHighcapacityFlag_u8 = 0; if (sd_version == 2) { do { response = SD_sendCommand(READ_OCR,0); retry++; if(retry>0xfe) { *cardType = SDCARD_TYPE_UNKNOWN; break; } //time out }while(response != 0x00); if(V_SdHighcapacityFlag_u8 == 1) { *cardType = SDCARD_TYPE_HIGH_CAPACITY; } else { *cardType = SDCARD_TYPE_STANDARD; } } return response; }
//*************************************************************************** //Function: to receive data from UART and write to multiple blocks of SD card //Arguments: none //return: uint8_t; will be 0 if no error, // otherwise the response byte will be sent //**************************************************************************** uint8_t SD_writeMultipleBlock(uint32_t startBlock, uint32_t totalBlocks) { uint8_t response, data = 0; uint16_t i, retry=0; uint32_t blockCounter=0; 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; // printf_P(PSTR("\n Enter text (End with ~): \n")); while( blockCounter < totalBlocks ) { 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 != '~'); // printf_P(PSTR("\n ---- \n")); SPI_Send8(0xfc,SD_SPI_PORT); //Send start block token 0xfc (0x11111100) for(i=0; i<512; i++) //send 512 bytes data SPI_Send8( buffer[i],SD_SPI_PORT); SPI_Send8(0xff,SD_SPI_PORT); //transmit dummy CRC (16-bit), CRC is ignored here SPI_Send8(0xff,SD_SPI_PORT); response = SPI_Receive8(SD_SPI_PORT); 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_Receive8(SD_SPI_PORT)) //wait for SD card to complete writing and get idle if(retry++ > 0xfffe) { SD_CS_DEASSERT; return(1); } SPI_Receive8(SD_SPI_PORT); //extra 8 bits blockCounter++; } SPI_Send8(0xfd,SD_SPI_PORT); //send 'stop transmission token' retry = 0; while(!SPI_Receive8(SD_SPI_PORT)) //wait for SD card to complete writing and get idle if(retry++ > 0xfffe) { SD_CS_DEASSERT; return(1); } SD_CS_DEASSERT; SPI_Send8(0xff,SD_SPI_PORT); //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_Receive8(SD_SPI_PORT)) //wait for SD card to complete writing and get idle if(retry++ > 0xfffe) { SD_CS_DEASSERT; return(1); } SD_CS_DEASSERT; return(0); }
//****************************************************************** //Function : to initialize the SD/SDHC card in SPI mode //Arguments : uint8_t power 1 - already on, 2 - init //return : uint8_t; will be 0 if no error, // otherwise the response byte will be sent //****************************************************************** uint8_t SD_Init(void) { uint8_t i, response, SD_version; uint16_t retry=0 ; SPI_Init(SPI_SD); // enable SPI and reinitialize SPI SPI_LOW_SPEED; // after each power up if(!(SD_Status & SDSTAT_POWER)) { SD_CS_DEASSERT; // pull high CS before starting the interface SD_POWER_ON; _delay_ms(10); SD_Status |= SDSTAT_POWER; for(i=0;i<10;i++) SPI_Send8(0xff,SD_SPI_PORT); //80 clock pulses spent before sending the first command SD_CS_ASSERT; do { response = SD_sendCommand(GO_IDLE_STATE, 0); //send 'reset & go idle' command retry++; if(retry>0x20) return(1); //time out, card not detected } while(response != 0x01); SD_CS_DEASSERT; SPI_Send8(0xff,SD_SPI_PORT); SPI_Send8(0xff,SD_SPI_PORT); retry = 0; 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, mandatory for SDHC card retry++; if(retry>0xfe) { SD_version = 1; cardType = 1; break; } //time out }while(response != 0x01); SD_Status |= SDSTAT_IDLE; } // only if activation from idle if(SD_Status & SDSTAT_IDLE) { 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) { return 2; //time out, card initialization failed } }while(response != 0x00); SD_Status &= ~SDSTAT_IDLE; } //only in init if(SD_Status & SDSTAT_NOTINIT) { 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_Status &= ~SDSTAT_NOTINIT; } //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 // test to save power SPI_HIGH_SPEED; SD_Status |= SDSTAT_INIT; return(0); //successful return }