C1541-III mbed edition

Dependencies:   mbed

ata.c

Committer:
gertk
Date:
2011-08-22
Revision:
1:0cbbb66a6100
Parent:
0:28557a4d2215

File content as of revision 1:0cbbb66a6100:

/*------------------------------------------------------------------------------------------*/
/*This is the lowlevel MMC/SD-card driver,                                                         */
/*in order to function with the allready available software, the routines use the name ATA    */
/*                                                                                            */
/*Note that this driver is dirty because it polls the drive for it's flags. The             */
/*routines in this driver should therefore only be called from a low priority task            */
/*------------------------------------------------------------------------------------------*/

/*    History:
    2007-09-28    Minor layout changes
    2006-08-25    Hurray, SanDisk wouldn't be SanDisk if they wouldn't have something different in the specifications that are to be considered as STANDARD !!! Why tell me why (as in the famous song of Anita Meijer)
                The 'manual-rs-mms.pdf' version of 13-5-2004, page 5-12 states: CMD55 (SPI) This optional MMCA command is not supported in the SanDisk MultiMediaCard/RS-MultiMediaCard.
                How are the big-boys able to work with these kind of standards what kind of info do they have that I don't have.
                Well, it's up to me now to handle this exception... <zucht>
    2006-08-24    all card now work EXCEPT the SanDisk RS-MMC, it even claims to be an SD-card... at least in my code, wonder why that is, back to the documentation
    2006-08-23    Hurray, the card that first would not function is now functional !!!
                COMPLETELY NUTS!!! Some MMC/SD-cards DO NOT, I repeat DO NOT function according specification,
                normally after giving the command 'CMD17' the command responds with an error token (should be 0 when all is OK)
                But for some reason some cards do not give this and simply answer 0xFF (instead of 0x00) this code is not even vaild according specs...
                I do not get it, but when I simply ignore the expected response and immediatley start polling for the start-of-data then there is no problem what so ever...
                Have they gone nuts or am I missing something... why is nobody following the protocol... this is RS232 connectors all over again.
                For those who are not familiar whith RS232 connectors, some people still do not know the difference between
                DTE and DCE and just mount a connector that fits to the device that is not meant to be connected in the way it is used. And wire the pins until it works and viola... no longer according specs, but it works in their own setup so it appears nothing is wrong, that is until you connect a device that is according specs...
    2006-08-21    added more debugging info in order to find the problem regarding the problems with some card not being supported...
                added a retry mechanism on the SDCARD_init() routine
                renamed the routines SDCARD to CARD, this because it also handles MMC cards so the old name was incorrect
    2006-02-02    improvements in code layout... i.o.w. making it more readable
    2006-01-29    added first steps for byte addressable read routine (read X bytes)
    2006-01-26    a routine waiting for 0xFE contained a ';' to much, so it did not timeout
    2005-12-23    removal of the CS handling routines... not required for this project...
    2005-12-11    (Dennis) added proper CS handling to enable sharing of SPI bus
    2005-04-19    start of project
*/


/* TO DO:
   ------
    - improve 'AtaRead_X_Bytes'

*/
/*------------------------------------------------------------------------------------------*/

/*--------------------------------------------------------*/
/*                        includes                        */
/*--------------------------------------------------------*/
#include "mbed.h"

//#include <stdio.h>
#include "ata.h"
#include "hardware.h"

/*--------------------------------------------------------*/
/*                        constants                       */   
/*--------------------------------------------------------*/
#define        FALSE        0            /*FALSE*/
#define        TRUE        1            /*TRUE*/
#define        MMCCARD        2
#define        SDCARD        3

/*MMC commandset*/
#define        CMD0        0x40        /*Resets the multimedia card*/
#define        CMD1        0x41        /*Activates the card's initialization process*/
#define        CMD2        0x42        /*--*/
#define        CMD3        0x43        /*--*/
#define        CMD4        0x44        /*--*/
#define        CMD5        0x45        /*reseved*/
#define        CMD6        0x46        /*reserved*/
#define        CMD7        0x47        /*--*/
#define        CMD8        0x48        /*reserved*/
#define        CMD9        0x49        /*CSD : Ask the selected card to send its card specific data*/
#define        CMD10        0x4a        /*CID : Ask the selected card to send its card identification*/
#define        CMD11        0x4b        /*--*/
#define        CMD12        0x4c        /*STOP-command*/
#define        CMD13        0x4d        /*Ask the selected card to send its status register*/
#define        CMD14        0x4e        /*--*/
#define        CMD15        0x4f        /*--*/
#define        CMD16        0x50        /*Select a block length (in bytes) for all following block commands (Read:between 1-512 and Write:only 512)*/
#define        CMD17        0x51        /*Reads a block of the size selected by the SET_BLOCKLEN command, the start address and block length must be set so that the data transferred will not cross a physical block boundry*/
#define        CMD18        0x52        /*--*/
#define        CMD19        0x53        /*reserved*/
#define        CMD20        0x54        /*--*/
#define        CMD21        0x55        /*reserved*/
#define        CMD22        0x56        /*reserved*/
#define        CMD23        0x57        /*reserved*/
#define        CMD24        0x58        /*Writes a block of the size selected by CMD16, the start address must be alligned on a sector boundry, the block length is always 512 bytes*/
#define        CMD25        0x59        /*--*/
#define        CMD26        0x5a        /*--*/
#define        CMD27        0x5b        /*Programming of the programmable bits of the CSD*/
#define        CMD28        0x5c        /*If the card has write protection features, this command sets the write protection bit of the addressed group. The porperties of the write protection are coded in the card specific data (WP_GRP_SIZE)*/
#define        CMD29        0x5d        /*If the card has write protection features, this command clears the write protection bit of the addressed group*/
#define        CMD30        0x5e        /*If the card has write protection features, this command asks the card to send the status of the write protection bits. 32 write protection bits (representing 32 write protect groups starting at the specific address) followed by 16 CRD bits are transferred in a payload format via the data line*/
#define        CMD31        0x5f        /*reserved*/
#define        CMD32        0x60        /*sets the address of the first sector of the erase group*/
#define        CMD33        0x61        /*Sets the address of the last sector in a cont. range within the selected erase group, or the address of a single sector to be selected for erase*/
#define        CMD34        0x62        /*Removes on previously selected sector from the erase selection*/
#define        CMD35        0x63        /*Sets the address of the first erase group within a range to be selected for erase*/
#define        CMD36        0x64        /*Sets the address of the last erase group within a continuos range to be selected for erase*/
#define        CMD37        0x65        /*Removes one previously selected erase group from the erase selection*/
#define        CMD38        0x66        /*Erases all previously selected sectors*/
#define        CMD39        0x67        /*--*/
#define        CMD40        0x68        /*--*/
#define        CMD41        0x69        /*reserved*/
#define        CMD42        0x6a        /*reserved*/
#define        CMD43        0x6b        /*reserved*/
#define        CMD44        0x6c        /*reserved*/
#define        CMD45        0x6d        /*reserved*/
#define        CMD46        0x6e        /*reserved*/
#define        CMD47        0x6f        /*reserved*/
#define        CMD48        0x70        /*reserved*/
#define        CMD49        0x71        /*reserved*/
#define        CMD50        0x72        /*reserved*/
#define        CMD51        0x73        /*reserved*/
#define        CMD52        0x74        /*reserved*/
#define        CMD53        0x75        /*reserved*/
#define        CMD54        0x76        /*reserved*/
#define        CMD55        0x77        /*reserved*/
#define        CMD56        0x78        /*reserved*/
#define        CMD57        0x79        /*reserved*/
#define        CMD58        0x7a        /*reserved*/
#define        CMD59        0x7b        /*Turns the CRC option ON or OFF. A '1' in the CRC option bit will turn the option ON, a '0' will turn it OFF*/
#define        CMD60        0x7c        /*--*/
#define        CMD61        0x7d        /*--*/
#define        CMD62        0x7e        /*--*/
#define        CMD63        0x7f        /*--*/

/*--------------------------------------------------------*/
/*                         globals                        */
/*--------------------------------------------------------*/
unsigned char crc_7;            /*contains CRC value*/
unsigned char response_1;        /*byte that holds the first response byte*/
unsigned char response_2;        /*byte that holds the second response byte*/
unsigned char response_3;        /*byte that holds the third response byte*/
unsigned char response_4;        /*byte that holds the fourth response byte*/
unsigned char response_5;        /*byte that holds the fifth response byte*/

/*--------------------------------------------------------*/
/*                     local functions                    */
/*--------------------------------------------------------*/
void Command_R0(char cmd,unsigned short AdrH,unsigned short AdrL);
void Command_R1(char cmd,unsigned short AdrH,unsigned short AdrL);
void Command_R2(char cmd,unsigned short AdrH,unsigned short AdrL);
void Command_R3(char cmd,unsigned short AdrH,unsigned short AdrL);
void MmcAddCrc7(unsigned char c);
void set_SPI_LowSpeed(void);
void set_SPI_HighSpeed(void);
unsigned char Card_CMD0(void);
unsigned char Card_CMD1(void);
unsigned char Card_BlockSize(void);
unsigned char WaitForSOD(void);
unsigned char Card_CID(void);
unsigned char Card_CSD(void);

/*************************************************************************************/
/*************************************************************************************/
/*External functions*/
/*************************************************************************************/
/*************************************************************************************/
SPI spicard(p11, p12, p13); // mosi, miso, sclk
DigitalOut SDCARD_CS(p14);
extern Timer timeout;
#define mySPI    spicard.write

void set_SPI_LowSpeed(void)
{
    spicard.frequency(100000);  // low speed 100 kHz
}

void set_SPI_HighSpeed(void)
{
    spicard.frequency(1000000); // Set to 1MHz for data transfer
}

/*wait for start of data transfer with timeout*/
unsigned char WaitForSOD(void)
{

    timeout.reset();
    
    while(mySPI(0xFF) != 0xFE)
        if (timeout.read_us() >= 1000)                    
        {
            return(FALSE);
        }
    return(TRUE);
}

/*Enable the SDcard correctly*/
unsigned char CARD_Init(void)
{
    unsigned short     lp;

    set_SPI_LowSpeed();
    SDCARD_CS=1;                                /*SDcard Disabled*/
    for(lp=0;lp<10;lp++)                        /*Set SDcard in SPI-Mode, Reset*/
        mySPI(0xFF);                                /*10 * 8bits = 80 clockpulses*/
    SDCARD_CS=0;                                /*SDcard Enabled*/

    wait_ms(50);
//    for(lp=0;lp<50000;lp++);                    /*delay for a lot of milliseconds (at least 16 bus clock cycles)*/

    if (Card_CMD0() == FALSE)
        return(FALSE);                            /*error, quit routine*/

    Command_R1(CMD55,0,0);                        /*when the response is 0x04 (illegal command), this must be an MMC-card*/
    if (response_1 == 0x05)                        /*determine MMC or SD*/
    {    /*An MMC-card has been detected, handle accordingly*/
        /*-------------------------------------------------*/
        if (Card_CMD1() == FALSE)
            return(FALSE);                        /*error, quit routine*/
    }
    else
    {    /*An SD-card has been detected, handle accordingly*/
        /*-------------------------------------------------*/
        timeout.reset();
        response_1 = 1;
        while(response_1 != 0)
        {
            Command_R1(CMD41,0,0);
            Command_R1(CMD55,0,0);
            if (timeout.read_us() > 10000)                /*timeout mechanism*/
            {
                return(FALSE);                    /*error, quit routine*/
            }
        }
    }

    if (Card_BlockSize() == FALSE)
        return(FALSE);                            /*error, quit routine*/

    set_SPI_HighSpeed();
    return(TRUE);                    
}

/*Enable the SDcard according SanDisk RS-MMC (a.k.a. the idiots not follow the world's standards*/
unsigned char CARD_AlternativeInit(void)
{
    unsigned short     lp;

    set_SPI_LowSpeed();
    SDCARD_CS=1;                                /*SDcard Disabled*/
    for(lp=0; lp < 10; lp++)                    /*Set SDcard in SPI-Mode, Reset*/
        mySPI(0xFF);                                /*10 * 8bits = 80 clockpulses*/
    SDCARD_CS=0;                                /*SDcard Enabled*/

    wait_ms(50);
    // for(lp=0; lp < 50000; lp++);                /*delay for a lot of milliseconds (at least 16 bus clock cycles)*/

    if (Card_CMD0() == FALSE)
        return(FALSE);                            /*error, quit routine*/

    if (Card_CMD1() == FALSE)
        return(FALSE);                            /*error, quit routine*/

    if (Card_BlockSize() == FALSE)
        return(FALSE);                            /*error, quit routine*/

    set_SPI_HighSpeed();
    return(TRUE);                    
}


unsigned char Card_BlockSize(void)
{
    unsigned char    retry_counter;

    retry_counter = 100;                        /*this routine is verrrrrrrry important, and sometimes fails on some cards so a retry mechanism is crucial*/
    while(retry_counter--)
    {
        Command_R1(CMD16,0,512);                /*Set read block length to 512 bytes, by the way 512 is default, but since nobody if following standards...*/
        if (response_1 == 0)
            break;

        if (retry_counter == 0)
            return(FALSE);
    }
    return(TRUE);
}

unsigned char Card_CID(void)
{
    Command_R1(CMD10,0,0);                        /*read CID register (total of 16Bytes)*/
//    if (response_1 !=0)
//    {
//        return(ERROR_CARDINIT_CID);                /*exit if invalid response*/
//    }
    if (WaitForSOD() == FALSE)                    /*wait for start-of-data (function features time-out)*/
        return(FALSE);

    OutputToRS232();                            /*set standard output to RS232*/
    printf("\r\n\r\nCID registers (16bytes)\r\n-----------------------");
    printf("\r\nCID(01) [manuf-ID] = %02X",(mySPI(0xFF)));    /*manuf-ID, 3 bytes*/
    printf("\r\nCID(02) [manuf-ID] = %02X",(mySPI(0xFF)));    /*manuf-ID, 3 bytes*/
    printf("\r\nCID(03) [manuf-ID] = %02X",(mySPI(0xFF)));    /*manuf-ID, 3 bytes*/
    printf("\r\nCID(04) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/                    
    printf("\r\nCID(05) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/                    
    printf("\r\nCID(06) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/                    
    printf("\r\nCID(07) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/                    
    printf("\r\nCID(08) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/                    
    printf("\r\nCID(09) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/                    
    printf("\r\nCID(10) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/
    printf("\r\nCID(11) [0x HW,FW] = %02X",(mySPI(0xFF)));    /*revision, hi-nibble=HW, low-nibble=FW, 1 byte*/
    printf("\r\nCID(12) [serial #] = %02X",(mySPI(0xFF)));    /*serial number, 3 bytes*/
    printf("\r\nCID(13) [serial #] = %02X",(mySPI(0xFF)));    /*serial number, 3 bytes*/
    printf("\r\nCID(14) [serial #] = %02X",(mySPI(0xFF)));    /*serial number, 3 bytes*/
    printf("\r\nCID(15) [0x Mo,Ye] = %02X",(mySPI(0xFF)));    /*revision, hi-nibble=Month, low-nibble=Year, 1 byte*/
    printf("\r\nCID(16) [7-1 =CRC] = %02X",(mySPI(0xFF)));    /*7-1=CRC checksum, 0=not used, 1 byte*/
    OutputToLCD();                                /*set standard output to LCD*/
    return(TRUE);
}

unsigned char Card_CSD(void)
{
    unsigned short     lp;

    Command_R1(CMD9,0,0);                        /*read CSD register*/
//    if (response_1 !=0)
//    {
//        return(ERROR_CARDINIT_CSD);                /*exit if invalid response*/
//    }
    if (WaitForSOD() == FALSE)                    /*wait for start-of-data (function features time-out)*/
        return(FALSE);

    OutputToRS232();                            /*set standard output to RS232*/
    printf("\r\n\r\nCSD registers (16bytes)\r\n-----------------------");
    for(lp=0; lp < 17; lp++)                    
    {
        printf("\r\nCSD(%02d) = %02X",lp,(mySPI(0xFF)));
    }
    OutputToLCD();                                /*set standard output to LCD*/
    return(TRUE);
}


/*request the status register of the card*/
unsigned char CARD_Status(unsigned char *ResponseData)
{
    Command_R2(CMD13,0,0);
    ResponseData[1] = response_1;                /*return the first response byte (---) in reg[1]*/
    ResponseData[0] = response_2;                /*return the second  response byte (LSB) in reg[0]*/
    return(TRUE);
}


/*Request the OCR register (SD-card in SPI-mode that is to be done with CMD58), this will give us the operation condition sof the card*/    
unsigned char CARD_OperatingConditions(unsigned char *ResponseData)
{
    timeout.reset();
    response_1 = 1;
    while(response_1 != 0)
    {
        Command_R3(CMD58,0,0);
        if (timeout.read_us()>255)                        /*timeout mechanism*/
        {
            return(FALSE);
        }
    }

    ResponseData[3] = response_2;                /*return the second response byte (MSB) in reg[3]*/
    ResponseData[2] = response_3;                /*return the third  response byte (---) in reg[2]*/
    ResponseData[1] = response_4;                /*return the fourth response byte (---) in reg[1]*/
    ResponseData[0] = response_5;                /*return the fifth  response byte (LSB) in reg[0]*/
    return(TRUE);
}


/*Read XXX bytes from the card*/
/*In some suitations it is not relevant to read the entire sector,*/
/*Sometimes only one byte is required, then this routine comes in handy...*/
unsigned char AtaRead_X_Bytes(unsigned long lba, unsigned int offset, unsigned char *ReadData, unsigned int NmbrOfBytes)
{
    unsigned long lp;
    unsigned short upper_lba, lower_lba;
    unsigned char *p,c;
    
    lba = lba * 512;                                /*calculate byte address*/
    upper_lba = (lba/65536);
    lower_lba = (lba%65536);

    Command_R1(CMD17, upper_lba, lower_lba);        /*read block start at ...,...*/
//    if (response_1 !=0)                                /*usually you would check the response, BUT not all do this, don't ask me why, but all cards eventually come with the 0xFE (start of data)*/
//        return(FALSE);                                /*exit if invalid response*/
    
    if (WaitForSOD() == FALSE)                        /*wait for start-of-data (function features time-out)*/
        return(FALSE);

//    /*read data and exit OK*/
//    p=ReadData;
//    do
//    {
//        SSPBUF = 0xff;
//        while (!BF);        
//        *(p++)= SSPBUF;    
//    }
//    while(--NmbrOfBytes);
//
//    Command_R1(CMD12, 0xff, 0xff);        /*send the stop command*/
//    return(TRUE);

    p=ReadData;
    for(lp=0; lp < 512; lp++)                    
    {
        c=mySPI(0xff);
        if(offset == 0)                /*skip the inrelevant bytes*/
            *(p++)=c;    
        else
        {
            *(p)=c;                
            offset--;
        }
    }

    mySPI(0xff);
    mySPI(0xff);
    return(TRUE);
}


/*Read single block (with block-size set by CMD16 to 512 by default)*/
unsigned char AtaReadSector(unsigned long lba, unsigned char *ReadData)
{
    unsigned short     upper_lba, lower_lba;
    unsigned char     i;        
    unsigned char     *p;
    

    lba = lba * 512;                                            /*calculate byte address*/
    upper_lba = (lba/65536);
    lower_lba = (lba%65536);
    /*printf("\r\nlba=%ld, upper lba=%d, lower lba=%d",lba, upper_lba,lower_lba);*/

    Command_R1(CMD17, upper_lba, lower_lba);                    /*read block start at ...,...*/
//    if (response_1 !=0)
//    {
//        return(ERROR_ATAREAD_CMD17);                            /*exit if invalid response*/
//    }
    
    if (WaitForSOD() == FALSE)                                    /*wait for start-of-data (function features time-out)*/
        return(ERROR_ATAREAD_TIMEOUT);

    /*read data and exit OK*/
    p=ReadData;
    i=0;
    do
    {
        *(p++)=mySPI(0xff);
    }
    while(--i);

    do
    {
        *(p++)=mySPI(0xff);            
    }
    while(--i);
    //for(lp=0; lp < 512; lp++)                    
    //    ReadData[lp] = mySPI(0xFF);

    mySPI(0xff);
    mySPI(0xff);
    return(TRUE);
}
    


/*Write: 512 Byte-Mode, this will only work (read MMC and SD-card specs) with a sector/block size of 512*/
unsigned char AtaWriteSector(unsigned long lba, unsigned char *WriteData)
{
    unsigned short upper_lba, lower_lba, lp;    /*Variable 0...65535*/
    unsigned char i;

    lba = lba * 512;                            /*since the MMC and SD cards are byte addressable and the FAT relies on a sector address (where a sector is 512bytes big), we must multiply by 512 in order to get the byte address*/
    upper_lba = (lba/65536);
    lower_lba = (lba%65536);

    Command_R1(CMD24, upper_lba, lower_lba);
    if (response_1 != 0)
    {
        return(FALSE);
    }
    else
    {
        SDCARD_CS=0;            /*SDcard Enabled*/
        mySPI(0xFF);
        mySPI(0xFF);
        mySPI(0xFE);

        for(lp=0; lp < 512; lp++)
            {
                mySPI(WriteData[lp]);
            }
        mySPI(255);                        // Send 2 Byte's without a meaning... although required by protocol
        mySPI(255);

        i = mySPI(0xFF);
//        i &=0b.0001.1111;
//        if (i != 0b.0000.0101) 
//            printf("Write error\n\r");
//        else
//            printf("Write succeeded?");
        while(mySPI(0xFF) !=0xFF);        /*wait until the card has finished writing the data*/
        return(TRUE);
    }
}
 

/*************************************************************************************/
/*Internal functions*/
/*************************************************************************************/

unsigned char Card_CMD0(void)
{
    unsigned char    retry_counter;

    retry_counter = 100;                        /*this routine is verrrrrrrry important, and sometimes fails on some cards so a retry mechanism is crucial*/
    while(retry_counter--)
    {
        Command_R1(CMD0,0,0);                    /*CMD0: Reset all cards to IDLE state*/
        if (response_1 == 1)
            break;

        if (retry_counter == 0)
            return(FALSE);                        /*error, quit routine*/
    }
    return(TRUE);
}

unsigned char Card_CMD1(void)
{
    timeout.reset();
    response_1 = 1;
    while(response_1 != 0)
    {
        Command_R1(CMD1,0,0);                /*activate the cards init process*/    
        if (timeout.read_us() > 10000)                /*timeout mechanism*/
        {
            return(FALSE);
        }
    }
    return(TRUE);
}


/*Send a command to the SDcard*/
void Command_R0(char cmd,unsigned short AdrH,unsigned short AdrL)
{
    crc_7=0;
    mySPI(0xFF);                /*flush SPI-bus*/

    mySPI(cmd);
    MmcAddCrc7(cmd);        /*update CRC*/
    mySPI(AdrH/256);            /*use upper 8 bits (everything behind the comma is discarded)*/
    MmcAddCrc7(AdrH/256);    /*update CRC*/
    mySPI(AdrH%256);            /*use lower 8 bits (shows the remaining part of the devision)*/
    MmcAddCrc7(AdrH%256);    /*update CRC*/
    mySPI(AdrL/256);            /*use upper 8 bits (everything behind the comma is discarded)*/
    MmcAddCrc7(AdrL/256);    /*update CRC*/
    mySPI(AdrL%256);            /*use lower 8 bits (shows the remaining part of the devision)*/
    MmcAddCrc7(AdrL%256);    /*update CRC*/

    crc_7<<=1;                /*shift all bits 1 position to the left, to free position 0*/
    crc_7++;                /*set LSB to '1'*/

    mySPI(crc_7);                /*transmit CRC*/
    mySPI(0xFF);                /*flush SPI-bus, or int other words process command*/
}


/*Send a command to the SDcard, a one byte response is expected*/
void Command_R1(char cmd,unsigned short AdrH,unsigned short AdrL)
{
    Command_R0(cmd, AdrH, AdrL);    /*send command*/
    response_1 = mySPI(0xFF);            /*return the reponse in the correct register*/
}


/*Send a command to the SDcard, a two byte response is expected*/
void Command_R2(char cmd,unsigned short AdrH,unsigned short AdrL)
{
    Command_R0(cmd, AdrH, AdrL);    /*send command*/
    response_1 = mySPI(0xFF);            /*return the reponse in the correct register*/
    response_2 = mySPI(0xFF);            
}


/*Send a command to the SDcard, a five byte response is expected*/
void Command_R3(char cmd,unsigned short AdrH,unsigned short AdrL)
{
    Command_R0(cmd, AdrH, AdrL);    /*send command*/
    response_1 = mySPI(0xFF);            /*return the reponse in the correct register*/
    response_2 = mySPI(0xFF);            
    response_3 = mySPI(0xFF);            
    response_4 = mySPI(0xFF);            
    response_5 = mySPI(0xFF);            
}


/*calculate CRC7 checksum*/
void MmcAddCrc7(unsigned char c)
{
    unsigned char i;
    
    i=8;
    do
    {
        crc_7<<=1;
        if(c&0x80)
            crc_7^=0x09;
        if(crc_7&0x80)
            crc_7^=0x09;
        c<<=1;
    }
    while(--i);
}