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 }

Generated on Sun Oct 29 03:41:07 2006 for Procyon AVRlib by  doxygen 1.4.2