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      : 2004.09.22
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/signal.h>     // include "signal" names (interrupt names)
00025 #include <avr/interrupt.h>  // include interrupt support
00026 
00027 #include "global.h"     // include our global settings
00028 #include "spi.h"        // include spi bus support
00029 
00030 #include "rprintf.h"
00031 
00032 #include "mmc.h"
00033 
00034 // include project-specific hardware configuration
00035 #include "mmcconf.h"
00036 
00037 // Global variables
00038 
00039 // Functions
00040 
00041 void mmcInit(void)
00042 {
00043     // initialize SPI interface
00044     spiInit();
00045     // release chip select
00046     sbi(MMC_CS_DDR, MMC_CS_PIN);
00047     sbi(MMC_CS_PORT,MMC_CS_PIN);
00048 }
00049 
00050 u08 mmcReset(void)
00051 {
00052     u08 retry;
00053     u08 r1=0;
00054 
00055     retry = 0;
00056     do
00057     {
00058         // send dummy bytes with CS high before accessing
00059         spiTransferByte(0xFF);
00060         spiTransferByte(0xFF);
00061         spiTransferByte(0xFF);
00062         spiTransferByte(0xFF);
00063         // resetting card, go to SPI mode
00064         r1 = mmcSendCommand(MMC_GO_IDLE_STATE, 0);
00065         #ifdef MMC_DEBUG
00066         rprintf("MMC_GO_IDLE_STATE: R1=0x%x\r\n", r1);
00067         #endif
00068         // do retry counter
00069         retry++;
00070         if(retry>10) return -1;
00071     } while(r1 != 0x01);
00072 
00073     // TODO: check card parameters for voltage compliance
00074     // before issuing initialize command
00075 
00076     retry = 0;
00077     do
00078     {
00079         // initializing card for operation
00080         r1 = mmcSendCommand(MMC_SEND_OP_COND, 0);
00081         #ifdef MMC_DEBUG
00082         rprintf("MMC_SEND_OP_COND: R1=0x%x\r\n", r1);
00083         #endif
00084         // do retry counter
00085         retry++;
00086         if(retry>100) return -1;
00087     } while(r1);
00088         
00089     // turn off CRC checking to simplify communication
00090     r1 = mmcSendCommand(MMC_CRC_ON_OFF, 0);
00091     #ifdef MMC_DEBUG
00092     rprintf("MMC_CRC_ON_OFF: R1=0x%x\r\n", r1);
00093     #endif
00094 
00095     // set block length to 512 bytes
00096     r1 = mmcSendCommand(MMC_SET_BLOCKLEN, 512);
00097     #ifdef MMC_DEBUG
00098     rprintf("MMC_SET_BLOCKLEN: R1=0x%x\r\n", r1);
00099     #endif
00100 
00101     // return success
00102     return 0;
00103 }
00104 
00105 u08 mmcSendCommand(u08 cmd, u32 arg)
00106 {
00107     u08 r1;
00108 
00109     // assert chip select
00110     cbi(MMC_CS_PORT,MMC_CS_PIN);
00111     // issue the command
00112     r1 = mmcCommand(cmd, arg);
00113     // release chip select
00114     sbi(MMC_CS_PORT,MMC_CS_PIN);
00115 
00116     return r1;
00117 }
00118 
00119 u08 mmcRead(u32 sector, u08* buffer)
00120 {
00121     u08 r1;
00122     u16 i;
00123 
00124     // assert chip select
00125     cbi(MMC_CS_PORT,MMC_CS_PIN);
00126     // issue command
00127     r1 = mmcCommand(MMC_READ_SINGLE_BLOCK, sector<<9);
00128     #ifdef MMC_DEBUG
00129     rprintf("MMC Read Block R1=0x%x\r\n", r1);
00130     #endif
00131     // check for valid response
00132     if(r1 != 0x00)
00133         return r1;
00134     // wait for block start
00135     while(spiTransferByte(0xFF) != MMC_STARTBLOCK_READ);
00136     // read in data
00137     for(i=0; i<0x200; i++)
00138     {
00139         *buffer++ = spiTransferByte(0xFF);
00140     }
00141     // read 16-bit CRC
00142     spiTransferByte(0xFF);
00143     spiTransferByte(0xFF);
00144     // release chip select
00145     sbi(MMC_CS_PORT,MMC_CS_PIN);
00146     // return success
00147     return 0;
00148 }
00149 
00150 u08 mmcWrite(u32 sector, u08* buffer)
00151 {
00152     u08 r1;
00153     u16 i;
00154 
00155     // assert chip select
00156     cbi(MMC_CS_PORT,MMC_CS_PIN);
00157     // issue command
00158     r1 = mmcCommand(MMC_WRITE_BLOCK, sector<<9);
00159     #ifdef MMC_DEBUG
00160     rprintf("MMC Write Block R1=0x%x\r\n", r1);
00161     #endif
00162     // check for valid response
00163     if(r1 != 0x00)
00164         return r1;
00165     // send dummy
00166     spiTransferByte(0xFF);
00167     // send data start token
00168     spiTransferByte(MMC_STARTBLOCK_WRITE);
00169     // write data
00170     for(i=0; i<0x200; i++)
00171     {
00172         spiTransferByte(*buffer++);
00173     }
00174     // write 16-bit CRC (dummy values)
00175     spiTransferByte(0xFF);
00176     spiTransferByte(0xFF);
00177     // read data response token
00178     r1 = spiTransferByte(0xFF);
00179     if( (r1&MMC_DR_MASK) != MMC_DR_ACCEPT)
00180         return r1;
00181     #ifdef MMC_DEBUG
00182     rprintf("Data Response Token=0x%x\r\n", r1);
00183     #endif
00184     // wait until card not busy
00185     while(!spiTransferByte(0xFF));
00186     // release chip select
00187     sbi(MMC_CS_PORT,MMC_CS_PIN);
00188     // return success
00189     return 0;
00190 }
00191 
00192 u08 mmcCommand(u08 cmd, u32 arg)
00193 {
00194     u08 r1;
00195     u08 retry=0;
00196     // send command
00197     spiTransferByte(cmd | 0x40);
00198     spiTransferByte(arg>>24);
00199     spiTransferByte(arg>>16);
00200     spiTransferByte(arg>>8);
00201     spiTransferByte(arg);
00202     spiTransferByte(0x95);  // crc valid only for MMC_GO_IDLE_STATE
00203     // end command
00204     // wait for response
00205     // if more than 8 retries, card has timed-out
00206     // return the received 0xFF
00207     while((r1 = spiTransferByte(0xFF)) == 0xFF)
00208         if(retry++ > 8) break;
00209     // return response
00210     return r1;
00211 }

Generated on Tue Sep 20 03:11:42 2005 for Procyon AVRlib by  doxygen 1.4.2