Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

# mmc.c

Go to the documentation of this file.

    00001 /*! \file mmc.c \brief MultiMedia and SD Flash Card Interface. */
    00002 //*****************************************************************************
    00003 //
    00004 // File Name    : 'mmc.c'
    00005 // Title        : MultiMedia and SD Flash Card Interface
    00006 // Author       : Pascal Stang - Copyright (C) 2004
    00007 // Created      : 2004.09.22
    00008 // Revised      : 2006.06.12
    00009 // Version      : 0.1
    00010 // Target MCU   : Atmel AVR Series
    00011 // Editor Tabs  : 4
    00012 //
    00013 // NOTE: This code is currently below version 1.0, and therefore is considered
    00014 // to be lacking in some functionality or documentation, or may not be fully
    00015 // tested.  Nonetheless, you can expect most functions to work.
    00016 //
    00017 // This code is distributed under the GNU Public License
    00018 //      which can be found at http://www.gnu.org/licenses/gpl.txt
    00019 //
    00020 //*****************************************************************************
    00021
    00022 //----- Include Files ---------------------------------------------------------
    00023 #include <avr/io.h>         // include I/O definitions (port names, pin names, etc)
    00024 #include <avr/interrupt.h>  // include interrupt support
    00025
    00026 #include "global.h"     // include our global settings
    00027 #include "spi.h"        // include spi bus support
    00028
    00029 #include "rprintf.h"
    00030
    00031 #include "mmc.h"
    00032
    00033 // include project-specific hardware configuration
    00034 #include "mmcconf.h"
    00035
    00036 // Global variables
    00037
    00038 // Functions
    00039
    00040 void mmcInit(void)
    00041 {
    00042     // initialize SPI interface
    00043     spiInit();
    00044     // release chip select
    00045     sbi(MMC_CS_DDR, MMC_CS_PIN);
    00046     sbi(MMC_CS_PORT,MMC_CS_PIN);
    00047 }
    00048
    00049 u08 mmcReset(void)
    00050 {
    00051     u08 i;
    00052     u08 retry;
    00053     u08 r1=0;
    00054
    00055     retry = 0;
    00056     do
    00057     {
    00058         // send dummy bytes with CS high before accessing
    00059         for(i=0;i<10;i++) spiTransferByte(0xFF);
    00060         // resetting card, go to SPI mode
    00061         r1 = mmcSendCommand(MMC_GO_IDLE_STATE, 0);
    00062         #ifdef MMC_DEBUG
    00063         rprintf("MMC_GO_IDLE_STATE: R1=0x%x\r\n", r1);
    00064         #endif
    00065         // do retry counter
    00066         retry++;
    00067         if(retry>10) return -1;
    00068     } while(r1 != 0x01);
    00069
    00070     // TODO: check card parameters for voltage compliance
    00071     // before issuing initialize command
    00072
    00073     retry = 0;
    00074     do
    00075     {
    00076         // initializing card for operation
    00077         r1 = mmcSendCommand(MMC_SEND_OP_COND, 0);
    00078         #ifdef MMC_DEBUG
    00079         rprintf("MMC_SEND_OP_COND: R1=0x%x\r\n", r1);
    00080         #endif
    00081         // do retry counter
    00082         retry++;
    00083         if(retry>100) return -1;
    00084     } while(r1);
    00085
    00086     // turn off CRC checking to simplify communication
    00087     r1 = mmcSendCommand(MMC_CRC_ON_OFF, 0);
    00088     #ifdef MMC_DEBUG
    00089     rprintf("MMC_CRC_ON_OFF: R1=0x%x\r\n", r1);
    00090     #endif
    00091
    00092     // set block length to 512 bytes
    00093     r1 = mmcSendCommand(MMC_SET_BLOCKLEN, 512);
    00094     #ifdef MMC_DEBUG
    00095     rprintf("MMC_SET_BLOCKLEN: R1=0x%x\r\n", r1);
    00096     #endif
    00097
    00098     // return success
    00099     return 0;
    00100 }
    00101
    00102 u08 mmcSendCommand(u08 cmd, u32 arg)
    00103 {
    00104     u08 r1;
    00105
    00106     // assert chip select
    00107     cbi(MMC_CS_PORT,MMC_CS_PIN);
    00108     // issue the command
    00109     r1 = mmcCommand(cmd, arg);
    00110     // release chip select
    00111     sbi(MMC_CS_PORT,MMC_CS_PIN);
    00112
    00113     return r1;
    00114 }
    00115
    00116 u08 mmcRead(u32 sector, u08* buffer)
    00117 {
    00118     u08 r1;
    00119     u16 i;
    00120
    00121     // assert chip select
    00122     cbi(MMC_CS_PORT,MMC_CS_PIN);
    00123     // issue command
    00124     r1 = mmcCommand(MMC_READ_SINGLE_BLOCK, sector<<9);
    00125     #ifdef MMC_DEBUG
    00126     rprintf("MMC Read Block R1=0x%x\r\n", r1);
    00127     #endif
    00128     // check for valid response
    00129     if(r1 != 0x00)
    00130         return r1;
    00131     // wait for block start
    00132     while(spiTransferByte(0xFF) != MMC_STARTBLOCK_READ);
    00133     // read in data
    00134     for(i=0; i<0x200; i++)
    00135     {
    00136         *buffer++ = spiTransferByte(0xFF);
    00137     }
    00138     // read 16-bit CRC
    00139     spiTransferByte(0xFF);
    00140     spiTransferByte(0xFF);
    00141     // release chip select
    00142     sbi(MMC_CS_PORT,MMC_CS_PIN);
    00143     // return success
    00144     return 0;
    00145 }
    00146
    00147 u08 mmcWrite(u32 sector, u08* buffer)
    00148 {
    00149     u08 r1;
    00150     u16 i;
    00151
    00152     // assert chip select
    00153     cbi(MMC_CS_PORT,MMC_CS_PIN);
    00154     // issue command
    00155     r1 = mmcCommand(MMC_WRITE_BLOCK, sector<<9);
    00156     #ifdef MMC_DEBUG
    00157     rprintf("MMC Write Block R1=0x%x\r\n", r1);
    00158     #endif
    00159     // check for valid response
    00160     if(r1 != 0x00)
    00161         return r1;
    00162     // send dummy
    00163     spiTransferByte(0xFF);
    00164     // send data start token
    00165     spiTransferByte(MMC_STARTBLOCK_WRITE);
    00166     // write data
    00167     for(i=0; i<0x200; i++)
    00168     {
    00169         spiTransferByte(*buffer++);
    00170     }
    00171     // write 16-bit CRC (dummy values)
    00172     spiTransferByte(0xFF);
    00173     spiTransferByte(0xFF);
    00174     // read data response token
    00175     r1 = spiTransferByte(0xFF);
    00176     if( (r1&MMC_DR_MASK) != MMC_DR_ACCEPT)
    00177         return r1;
    00178     #ifdef MMC_DEBUG
    00179     rprintf("Data Response Token=0x%x\r\n", r1);
    00180     #endif
    00181     // wait until card not busy
    00182     while(!spiTransferByte(0xFF));
    00183     // release chip select
    00184     sbi(MMC_CS_PORT,MMC_CS_PIN);
    00185     // return success
    00186     return 0;
    00187 }
    00188
    00189 u08 mmcCommand(u08 cmd, u32 arg)
    00190 {
    00191     u08 r1;
    00192     u08 retry=0;
    00193     // send command
    00194     spiTransferByte(cmd | 0x40);
    00195     spiTransferByte(arg>>24);
    00196     spiTransferByte(arg>>16);
    00197     spiTransferByte(arg>>8);
    00198     spiTransferByte(arg);
    00199     spiTransferByte(0x95);  // crc valid only for MMC_GO_IDLE_STATE
    00200     // end command
    00201     // wait for response
    00202     // if more than 8 retries, card has timed-out
    00203     // return the received 0xFF
    00204     while((r1 = spiTransferByte(0xFF)) == 0xFF)
    00205         if(retry++ > 8) break;
    00206     // return response
    00207     return r1;
    00208 }