mmc.c


1
/*#######################################################################################
2
Connect AVR to MMC/SD 
3
4
Copyright (C) 2004 Ulrich Radig
5
6
Bei Fragen und Verbesserungen wendet euch per EMail an
7
8
mail@ulrichradig.de
9
10
oder im Forum meiner Web Page : www.ulrichradig.de
11
12
Dieses Programm ist freie Software. Sie können es unter den Bedingungen der 
13
GNU General Public License, wie von der Free Software Foundation veröffentlicht, 
14
weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder 
15
(nach Ihrer Option) jeder späteren Version. 
16
17
Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, 
18
daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, 
19
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT 
20
FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License. 
21
22
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem 
23
Programm erhalten haben. 
24
Falls nicht, schreiben Sie an die Free Software Foundation, 
25
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 
26
#######################################################################################*/
27
28
#include "mmc.h"
29
30
//############################################################################
31
//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE)
32
unsigned char mmc_init ()
33
//############################################################################
34
{
35
  unsigned int Timeout = 0;
36
  
37
  //Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde
38
  MMC_Direction_REG &=~(1<<SPI_DI);      //Setzen von Pin MMC_DI auf Input
39
  MMC_Direction_REG |= (1<<SPI_Clock);    //Setzen von Pin MMC_Clock auf Output
40
  MMC_Direction_REG |= (1<<SPI_DO);      //Setzen von Pin MMC_DO auf Output
41
  MMC_Direction_REG |= (1<<MMC_Chip_Select);  //Setzen von Pin MMC_Chip_Select auf Output
42
    MMC_Direction_REG |= (1<<SPI_SSSD);  
43
  MMC_Write |= (1<<MMC_Chip_Select);      //Setzt den Pin MMC_Chip_Select auf High Pegel
44
45
  for(unsigned char a=0;a<200;a++){
46
  nop();
47
  };    //Wartet eine kurze Zeit
48
49
  #if SPI_Mode
50
    //Aktiviren des SPI - Bus, Clock = Idel LOW
51
    //SPI Clock teilen durch 128
52
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); //Enable SPI, SPI in Master Mode  
53
    SPSR = (0<<SPI2X);
54
  #endif
55
  
56
  //Initialisiere MMC/SD-Karte in den SPI-Mode
57
  for (unsigned char b = 0;b<0x0f;b++) //Sendet min 74+ Clocks an die MMC/SD-Karte
58
    {
59
    mmc_write_byte(0xff);
60
    }
61
  
62
  //Sendet Commando CMD0 an MMC/SD-Karte
63
  unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
64
  while(mmc_write_command (CMD) !=1)
65
  {
66
    if (Timeout++ > 200)
67
      {
68
      MMC_Disable();
69
      return(1); //Abbruch bei Commando1 (Return Code1)
70
      }
71
  }
72
  //Sendet Commando CMD1 an MMC/SD-Karte
73
  Timeout = 0;
74
  CMD[0] = 0x41;//Commando 1
75
  CMD[5] = 0xFF;
76
  while( mmc_write_command (CMD) !=0)
77
  {
78
    if (Timeout++ > 400)
79
      {
80
      MMC_Disable();
81
      return(2); //Abbruch bei Commando2 (Return Code2)
82
      }
83
  }
84
  #if SPI_Mode
85
    //SPI Bus auf max Geschwindigkeit
86
    SPCR &= ~((1<<SPR0) | (1<<SPR1));
87
    SPSR = SPSR|(1<<SPI2X);
88
  #endif
89
  
90
  //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
91
  MMC_Disable();
92
  return(0);
93
}
94
95
//############################################################################
96
//Sendet ein Commando an die MMC/SD-Karte
97
unsigned char mmc_write_command (unsigned char *cmd)
98
//############################################################################
99
{
100
  unsigned char tmp = 0xff;
101
  unsigned int Timeout = 0;
102
103
  //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv) 
104
  MMC_Disable();
105
106
  //sendet 8 Clock Impulse
107
  mmc_write_byte(0xFF);
108
109
  //set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
110
  MMC_Enable();
111
112
  //sendet 6 Byte Commando
113
  for (unsigned char a = 0;a<0x06;a++) //sendet 6 Byte Commando zur MMC/SD-Karte
114
    {
115
    mmc_write_byte(*cmd++);
116
    }
117
118
  //Wartet auf ein gültige Antwort von der MMC/SD-Karte
119
  while (tmp == 0xff)  
120
    {
121
    tmp = mmc_read_byte();
122
    if (Timeout++ > 500)
123
      {
124
      break; //Abbruch da die MMC/SD-Karte nicht Antwortet
125
      }
126
    }
127
  return(tmp);
128
}
129
130
//############################################################################
131
//Routine zum Empfangen eines Bytes von der MMC-Karte 
132
unsigned char mmc_read_byte (void)
133
//############################################################################
134
{
135
  unsigned char Byte = 0;
136
#if SPI_Mode  //Routine für Hardware SPI
137
  SPDR = 0xff;
138
  while(!(SPSR & (1<<SPIF))){};
139
  Byte = SPDR;
140
141
#else      //Routine für Software SPI
142
  for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Empangen MSB First
143
    {
144
    MMC_Write &=~(1<<SPI_Clock); //erzeugt ein Clock Impuls (Low) 
145
    
146
    if (bit_is_set(MMC_Read,SPI_DI) > 0) //Lesen des Pegels von MMC_DI
147
        {
148
        Byte |= (1<<(a-1));
149
        }
150
      else
151
        {
152
        Byte &=~(1<<(a-1));
153
        }
154
    MMC_Write |=(1<<SPI_Clock); //setzt Clock Impuls wieder auf (High)    
155
    }
156
#endif
157
  return (Byte);
158
}
159
160
161
//############################################################################
162
//Routine zum Senden eines Bytes zur MMC-Karte
163
void mmc_write_byte (unsigned char Byte)
164
//############################################################################
165
{
166
#if SPI_Mode    //Routine für Hardware SPI
167
  SPDR = Byte;   //Sendet ein Byte
168
  while(!(SPSR & (1<<SPIF))) //Wartet bis Byte gesendet wurde
169
  {
170
  }
171
#else      //Routine für Software SPI
172
  for (unsigned char a=8; a>0; a--) //das Byte wird Bitweise nacheinander Gesendet MSB First
173
  {
174
    if (bit_is_set(Byte,(a-1))>0)  //Ist Bit a in Byte gesetzt
175
        {
176
        MMC_Write |= (1<<SPI_DO); //Set Output High
177
        }
178
      else
179
        {
180
        MMC_Write &= ~(1<<SPI_DO); //Set Output Low
181
        }  
182
    MMC_Write &= ~(1<<SPI_Clock);  //erzeugt ein Clock Impuls (LOW)
183
    
184
    MMC_Write |= (1<<SPI_Clock); //setzt Clock Impuls wieder auf (High)
185
  }
186
  MMC_Write |= (1<<SPI_DO);  //setzt Output wieder auf High  
187
#endif
188
}
189
190
//############################################################################
191
//Routine zum schreiben eines Blocks(512Byte) auf die MMC/SD-Karte
192
unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer)
193
//############################################################################
194
{
195
  unsigned char tmp;
196
  //Commando 24 zum schreiben eines Blocks auf die MMC/SD - Karte
197
  unsigned char cmd[] = {0x58,0x00,0x00,0x00,0x00,0xFF}; 
198
  
199
  /*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
200
    addr wird von Blocks zu Bytes umgerechnet danach werden 
201
    diese in das Commando eingefügt*/
202
    
203
  addr = addr << 9; //addr = addr * 512
204
  
205
  cmd[1] = ((addr & 0xFF000000) >>24 );
206
  cmd[2] = ((addr & 0x00FF0000) >>16 );
207
  cmd[3] = ((addr & 0x0000FF00) >>8 );
208
209
  //Sendet Commando cmd24 an MMC/SD-Karte (Write 1 Block/512 Bytes)
210
  tmp = mmc_write_command (cmd);
211
  if (tmp != 0)
212
    {
213
    return(tmp);
214
    }
215
      
216
  //Wartet einen Moment und sendet einen Clock an die MMC/SD-Karte
217
  for (unsigned char a=0;a<100;a++)
218
    {
219
    mmc_read_byte();
220
    }
221
  
222
  //Sendet Start Byte an MMC/SD-Karte
223
  mmc_write_byte(0xFE);  
224
  
225
  //Schreiben des Bolcks (512Bytes) auf MMC/SD-Karte
226
  for (unsigned int a=0;a<512;a++)
227
    {
228
    mmc_write_byte(*Buffer++);
229
    }
230
  
231
  //CRC-Byte schreiben
232
  mmc_write_byte(0xFF); //Schreibt Dummy CRC
233
  mmc_write_byte(0xFF); //CRC Code wird nicht benutzt
234
  
235
  //Fehler beim schreiben? (Data Response XXX00101 = OK)
236
  if((mmc_read_byte()&0x1F) != 0x05) return(1);
237
238
  //Wartet auf MMC/SD-Karte Bussy
239
  while (mmc_read_byte() != 0xff){};
240
  
241
  //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
242
  MMC_Disable();
243
  
244
return(0);
245
}
246
247
//############################################################################
248
//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
249
void mmc_read_block(unsigned char *cmd,unsigned char *Buffer,unsigned int Bytes)
250
//############################################################################
251
{  
252
  //Sendet Commando cmd an MMC/SD-Karte
253
  if (mmc_write_command (cmd) != 0)
254
      {
255
       return;
256
      }
257
258
  //Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte)
259
  
260
  while (mmc_read_byte() != 0xfe){};
261
262
  //Lesen des Bolcks (normal 512Bytes) von MMC/SD-Karte
263
  for (unsigned int a=0;a<Bytes;a++)
264
    {
265
    *Buffer++ = mmc_read_byte();
266
    }
267
  //CRC-Byte auslesen
268
  mmc_read_byte();//CRC - Byte wird nicht ausgewertet
269
  mmc_read_byte();//CRC - Byte wird nicht ausgewertet
270
  
271
  //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
272
  MMC_Disable();
273
  
274
  return;
275
}
276
277
//############################################################################
278
//Routine zum lesen eines Blocks(512Byte) von der MMC/SD-Karte
279
unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer)
280
//############################################################################
281
{  
282
  //Commando 16 zum lesen eines Blocks von der MMC/SD - Karte
283
  unsigned char cmd[] = {0x51,0x00,0x00,0x00,0x00,0xFF}; 
284
  
285
  /*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
286
    addr wird von Blocks zu Bytes umgerechnet danach werden 
287
    diese in das Commando eingefügt*/
288
    
289
  addr = addr << 9; //addr = addr * 512
290
291
  cmd[1] = ((addr & 0xFF000000) >>24 );
292
  cmd[2] = ((addr & 0x00FF0000) >>16 );
293
  cmd[3] = ((addr & 0x0000FF00) >>8 );
294
295
    mmc_read_block(cmd,Buffer,512);
296
297
  return(0);
298
}
299
300
//############################################################################
301
//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
302
unsigned char mmc_read_cid (unsigned char *Buffer)
303
//############################################################################
304
{
305
  //Commando zum lesen des CID Registers
306
  unsigned char cmd[] = {0x4A,0x00,0x00,0x00,0x00,0xFF}; 
307
  
308
  mmc_read_block(cmd,Buffer,16);
309
310
  return(0);
311
}
312
313
//############################################################################
314
//Routine zum lesen des CSD Registers von der MMC/SD-Karte (16Bytes)
315
unsigned char mmc_read_csd (unsigned char *Buffer)
316
//############################################################################
317
{  
318
  //Commando zum lesen des CSD Registers
319
  unsigned char cmd[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
320
  
321
  mmc_read_block(cmd,Buffer,16);
322
323
  return(0);
324
}