Forum: Mikrocontroller und Digitale Elektronik Auslesen einer SD-Karte mit AVR


von Daniel K. (daniel_k80)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich schreibe mir gerade eine Bibliothek um mit einem AVR SD-Karten zu 
Schreiben und zu Lesen. Dazu habe ich zwei Fragen...

1)
Die Initialisierung der SD-Karte funktioniert auch soweit bei meinen 
beiden 4 GB Karten. Bei meiner alten 512 MB Karte klappt die 
Initialisierung nicht. Da würde ich gerne wissen warum (auch wenn es 
nicht wirklich wichtig ist...). Und zwar bekomme ich bei der Funktion 
"SD_SoftwareReset" immer ein "NO_RESPONSE" zurück, sprich die Karte 
reagiert nicht auf das Commando 0.

2)
Nachdem die Karte (jetzt meine 4 GB Karte) initialisiert worden ist, 
möchte ich gerne Sektor 0 auslesen. Dazu habe ich mir mit HxD den Sektor 
mal angeschaut (siehe Bild SD.png). Wenn ich die Karte nun mit dem AVR 
lese steht in meinem Buffer überall 0 drin und das obwohl die Karte 
problemlos durchläuft (ich erhalte nach dem Lesebefehl erst ein 0x00 und 
dann ein 0xFE).

Mein Code sieht so aus:

SD.c
1
SD_Error_t Status = SD_InitInterface(Config);
2
SD_ReadSingleBlock(0x00);  
3
  
4
return Status;

SD_Interface.c
1
static SD_CardType_t CardType = SD_VER_UNKNOWN;
2
3
SD_Error_t SD_InitInterface(SPI_Config_t* Config)
4
{  
5
  SD_Error_t ErrorCode = SD_SUCCESSFULL;
6
  
7
  // Set SD card CS as output in high state
8
  GPIO_SetDirection(SD_SS_PORT, SD_SS_PIN, GPIO_DIRECTION_OUT);
9
  GPIO_Set(SD_SS_PORT, SD_SS_PIN);
10
  
11
  if(Config != NULL)
12
  {
13
    SD_SPI_INIT(Config);
14
  }
15
16
  // Reset the SD card
17
  ErrorCode = SD_SoftwareReset();
18
  if(ErrorCode != SD_SUCCESSFULL)
19
  {
20
    return ErrorCode;
21
  }
22
  
23
  // Initialize the SD card
24
  ErrorCode = SD_InitializeCard();
25
  if(ErrorCode != SD_SUCCESSFULL)
26
  {
27
    return ErrorCode;
28
  }
29
  
30
  // Set the block length to 512 (only necessary if the card is not a SDXC or SDHX card) 
31
  if((CardType != SD_VER_2_HI) & (CardType != SD_VER_2_STD))
32
  {
33
    ErrorCode = SD_SetBlockLength(SD_BLOCK_SIZE);
34
    if(ErrorCode != SD_SUCCESSFULL)
35
    {
36
      return ErrorCode;
37
    }
38
  }
39
    
40
  return ErrorCode;
41
}
42
43
uint8_t SD_Command(uint8_t Command, uint32_t Arg, uint8_t Checksum, uint32_t Count, uint8_t* Buffer)
44
{
45
  // Create 8 clock pulse before activating the card
46
  SD_SPI_TRANSMIT(0xFF);
47
  SD_SPI_CHIP_SELECT(SD_SS_PORT, SD_SS_PIN);
48
  SD_SPI_TRANSMIT(Command);
49
  SD_SPI_TRANSMIT(Arg >> 0x18);
50
  SD_SPI_TRANSMIT(Arg >> 0x10);
51
  SD_SPI_TRANSMIT(Arg >> 0x08);
52
  SD_SPI_TRANSMIT(Arg);
53
  SD_SPI_TRANSMIT(Checksum);
54
  
55
  /*  
56
  Wait for the response (0 - 8 bytes for SD cards and 1 - 8 bytes for MMC)
57
  The spec also say that you have to wait 8 clock cycles after the last bus
58
  transaction.
59
  */      
60
  for(uint8_t i = 0; i < 0x08; i++)
61
  {
62
    uint8_t DataIn = SD_SPI_TRANSMIT(0xFF);
63
    if(DataIn != 0xFF)
64
    {
65
      // Read all additional data
66
      if(Count > 0)
67
      {
68
        for(uint32_t j = 0x01; j < Count; j++)
69
        {
70
          *Buffer++ = SD_SPI_TRANSMIT(0xFF);
71
        }
72
      }
73
      
74
      // Send a dummy byte and deselect the card after it
75
      SD_SPI_TRANSMIT(0xFF);
76
      SD_SPI_CHIP_DESELECT(SD_SS_PORT, SD_SS_PIN);
77
78
      return DataIn;
79
    }
80
  }
81
  
82
  SD_SPI_CHIP_DESELECT(SD_SS_PORT, SD_SS_PIN);
83
  
84
  return SD_NO_RESPONSE;
85
}
86
87
SD_Error_t SD_SoftwareReset(void)
88
{
89
  uint8_t Repeat = 0x00;
90
  
91
  SD_SPI_CHIP_SELECT(SD_SS_PORT, SD_SS_PIN);
92
  
93
  for(uint8_t i = 0x00; i < 0x0A; i++)
94
  {
95
    SD_SPI_TRANSMIT(0xFF);
96
  }
97
  
98
  SD_SPI_CHIP_DESELECT(SD_SS_PORT, SD_SS_PIN);
99
  
100
  while(SD_Command(SD_ID_TO_CMD(0), 0x00000000, 0x95, 0, 0) != SD_STATE_IDLE)
101
  {
102
    // Initialization failed
103
    if(Repeat++ == 10)
104
    {
105
      return SD_NO_RESPONSE;
106
    }
107
  }
108
  
109
  return SD_SUCCESSFULL;
110
}
111
112
SD_Error_t SD_InitializeCard(void)
113
{
114
  uint16_t Wait = 0x00;
115
  uint32_t R3 = 0x00;
116
  uint8_t R1 = 0xFF;
117
  uint8_t Buffer[4];
118
  
119
  R1 = SD_Command(SD_ID_TO_CMD(8), 0x000001AA, 0x87, 4, Buffer);
120
  if(R1 == SD_STATE_IDLE)
121
  {
122
    /*
123
      Version 2 SD card
124
    */
125
126
    R3 = ((uint32_t)Buffer[3]) << 0x18;
127
    R3 |= ((uint32_t)Buffer[2]) << 0x10;
128
    R3 |= ((uint32_t)Buffer[1]) << 0x08;
129
    R3 |= ((uint32_t)Buffer[0]);
130
    /*
131
    if(R3 != 0x000001AA)
132
    {
133
      return SD_UNSUPPORTED_CARD;
134
    }*/
135
    
136
    // Send ACMD41 and check for ready
137
    R1 = 0xFF;
138
    while((++Wait < 0x2710) & (R1 != SD_STATE_SUCCESSFULL))
139
    {
140
      SD_Command(SD_ID_TO_CMD(55), 0x00000000, 0x00, 0, 0);
141
      R1 = SD_Command(SD_ID_TO_CMD(41), 0x40000000, 0x00, 0, 0);
142
    }
143
    
144
    if((Wait >= 0x2710) | (R1 != SD_STATE_SUCCESSFULL))
145
    {
146
      return SD_TIMEOUT;
147
    }
148
    
149
    // Send CMD58 to read OCR
150
    R1 = SD_Command(SD_ID_TO_CMD(58), 0x00000000, 0x00, 4, Buffer);
151
    if(R1 == SD_STATE_SUCCESSFULL)
152
    {
153
      R3 = ((uint32_t)Buffer[3]) << 0x18;
154
      R3 |= ((uint32_t)Buffer[2]) << 0x10;
155
      R3 |= ((uint32_t)Buffer[1]) << 0x08;
156
      R3 |= ((uint32_t)Buffer[0]);
157
    }
158
    else
159
    {
160
      CardType = SD_VER_UNKNOWN;
161
    }
162
    
163
    // Check if the CCS bit is set
164
    if(R3 & 0x40000000)
165
    {
166
      CardType = SD_VER_2_HI;
167
    }
168
    else
169
    {
170
      CardType = SD_VER_2_STD;
171
    }
172
  }
173
  else
174
  {
175
    /*
176
      Version 1 SD card or MMC
177
    */
178
    
179
    // Check for version 1 SD card
180
    Wait = 0x00;
181
    while(++Wait < 0xFF) 
182
    {
183
      SD_Command(SD_ID_TO_CMD(55), 0x00000000, 0, 0, 0);
184
      R1 = SD_Command(SD_ID_TO_CMD(41), 0x00000000, 0, 0, 0);
185
      if(R1 == SD_STATE_SUCCESSFULL)
186
      {
187
        CardType = SD_VER_1_STD;
188
        break;
189
      }
190
    }
191
    
192
    // Check for multimedia card
193
    Wait = 0x00;
194
    if(R1 & SD_STATE_ILLEGAL_COMMAND)
195
    {
196
      while(++Wait < 0xFF)
197
      {
198
        R1 = SD_Command(SD_ID_TO_CMD(1), 0x00000000, 0, 0, 0);
199
        if(R1 == SD_STATE_SUCCESSFULL) 
200
        {
201
          CardType = SD_MMC;
202
          break;
203
        }
204
      }
205
    }
206
  }
207
  
208
  return SD_SUCCESSFULL;
209
}
210
211
uint8_t SD_SetBlockLength(uint32_t BlockLength)
212
{
213
  return SD_Command(SD_ID_TO_CMD(16), 0x00000200, 0xFF, 0, 0);
214
}
215
216
uint8_t SD_ReadSingleBlock(uint32_t Address)
217
{
218
  uint8_t R1 = 0x00;
219
  uint16_t Wait = 0x00;
220
  uint32_t Offset = 0x00;
221
  uint32_t Len = 10;
222
  uint8_t Buffer[512];
223
  uint8_t Sector = 0x00;
224
225
  SD_SPI_TRANSMIT(0xFF);
226
  SD_SPI_CHIP_SELECT(SD_SS_PORT, SD_SS_PIN);
227
  SD_SPI_TRANSMIT(SD_ID_TO_CMD(17));
228
  SD_SPI_TRANSMIT(Sector >> 15);
229
  SD_SPI_TRANSMIT(Sector >> 7);
230
  SD_SPI_TRANSMIT(Sector << 1);
231
  SD_SPI_TRANSMIT(0x00);
232
  SD_SPI_TRANSMIT(0xFF);
233
    
234
  // Wait for 0x00
235
  R1 = 0xFF;
236
  while((++Wait < 0x2710) & (R1 != SD_STATE_SUCCESSFULL))
237
  {
238
    R1 = SD_SPI_TRANSMIT(0xFF);
239
  }
240
  
241
  if((Wait >= 0x2710) | (R1 != SD_STATE_SUCCESSFULL))
242
  {
243
    return SD_TIMEOUT;
244
  }
245
246
  // Wait for 0xFE
247
  Wait = 0x00;
248
  R1 = 0xFF;
249
  while((++Wait < 0x2710) & (R1 != SD_STATE_BEGIN_TRANSMISSION))
250
  {
251
    R1 = SD_SPI_TRANSMIT(0xFF);
252
  }
253
  
254
  if((Wait >= 0x2710) | (R1 != SD_STATE_BEGIN_TRANSMISSION))
255
  {
256
    return SD_TIMEOUT;
257
  }
258
259
    for(uint32_t i = 0x00; i < Offset; i++)
260
  {
261
    SD_SPI_TRANSMIT(0xFF);
262
  }
263
        
264
  for(uint32_t i = 0x00; i < Len; i++)
265
  {
266
    Buffer[i] = SD_SPI_TRANSMIT(0xFF);
267
  }
268
269
     for(uint32_t i = 0x00; i < 512 - Offset; i++)
270
  {
271
    SD_SPI_TRANSMIT(0xFF);
272
  }
273
        
274
    SD_SPI_TRANSMIT(0xFF);
275
    SD_SPI_TRANSMIT(0xFF);    
276
277
    SD_SPI_CHIP_DESELECT(SD_SS_PORT, SD_SS_PIN);;
278
  
279
  uint8_t T = 0x00;
280
  
281
  return T;
282
}

Vielen Dank :)

: Bearbeitet durch Moderator
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Daniel K. schrieb:
> Mein Code sieht so aus:
Zwei Tipps dazu aus der Anleitung, die über jeder Texteingabebox steht:
1.
1
Antwort schreiben
2
Wichtige Regeln - erst lesen, dann posten!
3
    Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
2.
1
Formatierung (mehr Informationen...)
2
    [c]C-Code[/c]
Den zweiten habe ich jetzt mal umgesetzt...

: Bearbeitet durch Moderator
von S. Landolt (Gast)


Lesenswert?

zu 1): 512 MB ist SDC, 4 GB ist SDHC; die Initialisierung ist 
unterschiedlich, ebenso die Adressierung

zu 2): kann/will ich nichts sagen, ist mir zuviel Programm; sollte ich 
eine Vermutung äußern, würde ich auf falsche Adressierung tippen

von Dr. Sommer (Gast)


Lesenswert?

Sehe ich da mkdosfs? SD-Karten darf man nur mit dem Tool von sdcard.org 
formatieren, da dies die spezifischen Anforderungen von SD-Karten beim 
Layout beachtet

Daniel K. schrieb:
> Die Initialisierung der SD-Karte funktioniert auch soweit bei meinen
> beiden 4 GB Karten. Bei meiner alten 512 MB Karte klappt die
> Initialisierung nicht.

Dass diese beiden Karten eine komplett andere Initialisierung sowie 
Adressierung benutzen ist dir klar (SDSC vs. SDHC)?

von Daniel K. (daniel_k80)


Angehängte Dateien:

Lesenswert?

Lothar M. schrieb:
> Daniel K. schrieb:
>> Mein Code sieht so aus:
> Zwei Tipps dazu aus der Anleitung, die über jeder Texteingabebox steht:
> 1.
>
1
> Antwort schreiben
2
> Wichtige Regeln - erst lesen, dann posten!
3
>     Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
4
>
> 2.
>
1
> Formatierung (mehr Informationen...)
2
>     [c]C-Code[/c]
3
>
> Den zweiten habe ich jetzt mal umgesetzt...

Mmh ich wollte gerade den Beitrag ändern, aber es gab ein Fehler. 
Vermutlich ist die Zeit zum ändern abgelaufen. Ich hänge die Dateien mal 
hier an die Antwort. Vielleicht kann ein Moderator die verschieben?

Dr. Sommer schrieb:
> Sehe ich da mkdosfs? SD-Karten darf man nur mit dem Tool von sdcard.org
> formatieren, da dies die spezifischen Anforderungen von SD-Karten beim
> Layout beachtet
>
> Daniel K. schrieb:
>> Die Initialisierung der SD-Karte funktioniert auch soweit bei meinen
>> beiden 4 GB Karten. Bei meiner alten 512 MB Karte klappt die
>> Initialisierung nicht.
>
> Dass diese beiden Karten eine komplett andere Initialisierung sowie
> Adressierung benutzen ist dir klar (SDSC vs. SDHC)?

Die SD-Karte stammt aus einem anderen Projekt. Ich glaube da ist noch 
ein u-boot Bootloader drauf. Ich habe die vor den Versuchen nicht 
formatiert, da ich die nur lesen wollte und es mir gerade recht kam, 
wenn da noch was drauf ist.

Das die Initialisierung bei beiden Karten anders ist, ist mir durchaus 
klar. Aber betrifft dies auch den Reset, den man ganz am Anfang macht, 
sprich 80 Taktzyklen erzeugen und dann das Commando 0 senden? Ich bin 
bisher davon ausgegangen, dass das bei allen Kartentypen gleich ist 
(siehe hier 
https://electronics.stackexchange.com/questions/77417/what-is-the-correct-command-sequence-for-microsd-card-initialization-in-spi)

Die 512 MB Karte antwortet schon gar nicht auf diesen Block
1
ErrorCode = SD_SoftwareReset();
2
if(ErrorCode != SD_SUCCESSFULL)
3
{
4
  return ErrorCode;
5
}

Soweit ich verstanden habe adressiere ich bei SDHC-Karten ganze Blöcke. 
Dafür verwende ich den Befehl 17 und adressiere den Sektor 0. Oder habe 
ich da was falsch verstanden?

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

'SD_SoftwareReset': Bei diesen Dummy-FFs zu Beginn muss die SDC doch 
deselektiert sein, oder habe ich das falsch in Erinnerung?

'SD_ReadSingleBlock': Sector als uint8_t?

von Daniel K. (daniel_k80)


Lesenswert?

S. Landolt schrieb:
> 'SD_SoftwareReset': Bei diesen Dummy-FFs zu Beginn muss die SDC doch
> deselektiert sein, oder habe ich das falsch in Erinnerung?
>
> 'SD_ReadSingleBlock': Sector als uint8_t?

Stimmt. Du hast recht. Hab beides korrigiert, aber das Problem ist nach 
wie vor vorhanden.

von S. Landolt (Gast)


Lesenswert?

Nicht mal am 512 MB-Kartenproblem hat sich etwas geändert? Schlecht.

Nochmal zu 'SD_ReadSingleBlock', auch wenn es mit dem Sektor-0-Problem 
nicht direkt etwas zu tun hat: mir ist, als Assemblerprogrammierer, die 
ganze Konstruktion unklar, da wird 'Adresse' übergeben, aber nicht 
weiterverwendet, 'Sector' ist 0 und wird dann in einer Weise 
rechts/links verschoben, die ich auch nicht verstehe, sieht irgendwie so 
aus, als wäre es für eine SDC, nicht für eine SDHC gedacht.

von Daniel K. (daniel_k80)


Lesenswert?

S. Landolt schrieb:
> Nicht mal am 512 MB-Kartenproblem hat sich etwas geändert? Schlecht.
>
> Nochmal zu 'SD_ReadSingleBlock', auch wenn es mit dem Sektor-0-Problem
> nicht direkt etwas zu tun hat: mir ist, als Assemblerprogrammierer, die
> ganze Konstruktion unklar, da wird 'Adresse' übergeben, aber nicht
> weiterverwendet, 'Sector' ist 0 und wird dann in einer Weise
> rechts/links verschoben, die ich auch nicht verstehe, sieht irgendwie so
> aus, als wäre es für eine SDC, nicht für eine SDHC gedacht.

Hallo,

mit der 512 MB Karte habe ich es nicht getestet. Das mache ich im Laufe 
des Tages mal. Ggf. hat sich das Problem dann gelöst...
Die Sektoren habe ich erst einmal fest kodiert, da ich das Lesen erst 
einmal ausprobieren wollte. Daher habe ich die Werte erst nur in der 
Funktion definiert. Die Übergabeparameter sollen später anders aussehen. 
Aber ich schaue mir gleich noch mal das Schieben an. Ggf. habe ich mich 
da vertan...

von S. Landolt (Gast)


Lesenswert?

Jetzt bin ich irritiert: wenn ich das c-Programm richtig verstehe, lesen 
Sie im Sektor 0 ab Adresse 0x1BF in den Buffer 10 Bytes ein - woher 
sollen wir wissen, was dort  steht, das eingangs gezeigte SD.png reicht 
nicht so weit.

von Daniel K. (daniel_k80)


Lesenswert?

S. Landolt schrieb:
> Jetzt bin ich irritiert: wenn ich das c-Programm richtig verstehe, lesen
> Sie im Sektor 0 ab Adresse 0x1BF in den Buffer 10 Bytes ein - woher
> sollen wir wissen, was dort  steht, das eingangs gezeigte SD.png reicht
> nicht so weit.

Hallo,

den Code hatte ich nach dem ersten Beitrag noch modifiziert und vor dem 
Upload auf die ursprüngliche Version zurück geändert. Dieser Wert ist 
mir leider durchgegangen. Selbstverständlich muss der Wert 0x00 sein, 
damit es zum gezeigten Screenshot passt (tatsächlich ist auf der 
SD-Karte an der Stelle 0x1BF 0x00...).

von S. Landolt (Gast)


Lesenswert?

Und wie sieht nun unsere derzeitige gemeinsame Basis, sprich das 
aktuelle Programm, aus?

von S. Landolt (Gast)


Lesenswert?

PS:
Wie und wo nehmen Sie Einblick in diesen Buffer?

Beitrag #5627138 wurde vom Autor gelöscht.
von Daniel K. (daniel_k80)


Angehängte Dateien:

Lesenswert?

S. Landolt schrieb:
> Und wie sieht nun unsere derzeitige gemeinsame Basis, sprich das
> aktuelle Programm, aus?

Hallo,

ich habe den aktuellen Code mit einem neuen Bild angehängt.
Stand ist der, dass mit dem aktuellen Code und der gezeigten SD-Karte
nichts in der lokalen Variable "Buffer" der "SD_ReadSingleBlock"
Funktion steht.
Die SD-Karte hat zwei Partitionen - eine FAT (siehe Screenshot) und eine
Ext3, wobei die FAT-Partition den Bootbefehl enthält, daher dürfte diese
Partition ja den Anfang des Speichers der Karte darstellen.

Ausgelesen habe ich den Buffer mittels JTAG (siehe Bild "JTAG.png"). Die
Funktion "SD_InitInterface()" gibt ein Successfull zurück und auch das
0x00 und 0xFE nach dem Kommando 17 wird empfangen.

Edit: Alten Beitrag gelöscht, da ich dort eine Datei mehrfach 
hochgeladen hatte und das falsch war.

: Bearbeitet durch User
von Kartenkurt (Gast)


Lesenswert?

Wie sieht der komplette Sektor 0 aus?

von Daniel K. (daniel_k80)


Angehängte Dateien:

Lesenswert?

Kartenkurt schrieb:
> Wie sieht der komplette Sektor 0 aus?

Siehe Bild.

von Jim M. (turboj)


Lesenswert?

Daniel K. schrieb:
> Siehe Bild.

Meep, falsch.
Das ist der Sektor 0 der ersten Partition ("Laufwerksbuchstabe G:") in 
Windoof. Sieht man an dem ganzen FAT16 gelumpe.

Der echte Sektor 0 hat in der Tat eine Menge Nullen am Anfang, und 
erst ziemlich weit hinten die eigentliche Partitionstabelle drin. Schau 
Dir mal die letzten 100 Byte an.

Den Sektor kann man unter Windows aber nur mit Admin-Rechten von der 
"physichen Disk" lesen. HXD muss dafür "als Administrator" ausgeführt 
werden IIRC.

von S. Landolt (Gast)


Lesenswert?

Sollte man nicht, um hier klare Verhältnisse zu schaffen, eine Karte 
'raw', also z.B. mit Win32DiskImager eine reine Textdatei, beschreiben? 
Die Karte lässt sich ja später wieder problemlos formatieren zur 
normalen Verwendung.

von Daniel K. (daniel_k80)


Lesenswert?

Jim M. schrieb:
> Daniel K. schrieb:
>> Siehe Bild.
>
> Meep, falsch.
> Das ist der Sektor 0 der ersten Partition ("Laufwerksbuchstabe G:") in
> Windoof. Sieht man an dem ganzen FAT16 gelumpe.
>
> Der echte Sektor 0 hat in der Tat eine Menge Nullen am Anfang, und
> erst ziemlich weit hinten die eigentliche Partitionstabelle drin. Schau
> Dir mal die letzten 100 Byte an.
>
> Den Sektor kann man unter Windows aber nur mit Admin-Rechten von der
> "physichen Disk" lesen. HXD muss dafür "als Administrator" ausgeführt
> werden IIRC.

Ahhhhhhh okay. Dann habe ich da wohl was ganz gewaltig missverstanden. 
Ich probier das nachher mal an einem anderen PC aus, weil ich an diesem 
PC selbst mit Adminrechte nicht genug Rechte habe um mir das in HxD 
anzuschauen (Windows halt ^^).

von Dr. Sommer (Gast)


Lesenswert?

Daniel K. schrieb:
> weil ich an diesem
> PC selbst mit Adminrechte nicht genug Rechte habe um mir das in HxD
> anzuschauen (Windows halt ^^).

Starte HxD als Admin. Bei mir hat das selbst unter Win10 immer 
funktioniert.

von Daniel K. (daniel_k80)


Lesenswert?

Dr. Sommer schrieb:
> Daniel K. schrieb:
>> weil ich an diesem
>> PC selbst mit Adminrechte nicht genug Rechte habe um mir das in HxD
>> anzuschauen (Windows halt ^^).
>
> Starte HxD als Admin. Bei mir hat das selbst unter Win10 immer
> funktioniert.

Hier geht das leider nicht (FH-PC) :(
Muss ich gleich Zuhause machen...

von Daniel K. (daniel_k80)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

so ich habe mir mal den physischen Datenträger angeschaut und einen 
Ausschnitt davon hochgeladen.
Zudem habe ich den Offset auf 0x1B8 geändert. Allerdings lese ich 
immernoch nur 0x00 aus -.-

Und zudem funktioniert die 512 MB Karte mit dem gezeigten Code noch 
nicht, aber das Problem ist erst einmal sekundär. Die Anmerkung war nur 
als Update zur vorherigen Antwort.

von holger (Gast)


Lesenswert?

>Allerdings lese ich
>immernoch nur 0x00 aus -.-

Ich sehe mehr als nur Nullen. Ab 1B8 könnte eine Partitionstabelle sein 
und das 55AA am Ende sieht auch gut aus für Sektor 0.

von holger (Gast)


Lesenswert?

>Allerdings lese ich
>immernoch nur 0x00 aus -.-

Ach verdammt, du meinst mit dem AVR;)

>Zudem habe ich den Offset auf 0x1B8 geändert.

Lass das, nimm Null.

von Daniel K. (daniel_k80)


Lesenswert?

Hab den Offset nun mal raus geworfen und den Code für die Funktion 
geändert
1
  uint8_t R1 = 0x00;
2
  uint16_t Wait = 0x00;
3
  uint16_t Len = 512;
4
  uint8_t Buffer[512];
5
6
  SD_SPI_TRANSMIT(0xFF);
7
  SD_SPI_CHIP_SELECT(SD_SS_PORT, SD_SS_PIN);
8
  SD_SPI_TRANSMIT(SD_ID_TO_CMD(17));
9
  SD_SPI_TRANSMIT(0);
10
  SD_SPI_TRANSMIT(0);
11
  SD_SPI_TRANSMIT(0);
12
  SD_SPI_TRANSMIT(0x00);
13
  SD_SPI_TRANSMIT(0xFF);
14
    
15
  // Wait for 0x00
16
  R1 = 0xFF;
17
  while((++Wait < 0x2710) & (R1 != SD_STATE_SUCCESSFULL))
18
  {
19
    R1 = SD_SPI_TRANSMIT(0xFF);
20
  }
21
  
22
  if((Wait >= 0x2710) | (R1 != SD_STATE_SUCCESSFULL))
23
  {
24
    return SD_TIMEOUT;
25
  }
26
27
  // Wait for 0xFE
28
  Wait = 0x00;
29
  R1 = 0xFF;
30
  while((++Wait < 0x2710) & (R1 != SD_STATE_BEGIN_TRANSMISSION))
31
  {
32
    R1 = SD_SPI_TRANSMIT(0xFF);
33
  }
34
  
35
  if((Wait >= 0x2710) | (R1 != SD_STATE_BEGIN_TRANSMISSION))
36
  {
37
    return SD_TIMEOUT;
38
  }
39
        
40
  for(uint16_t i = 0x00; i < Len; i++)
41
  {
42
    Buffer[i] = SD_SPI_TRANSMIT(0xFF);
43
  }
44
        
45
    // skip checksum
46
    SD_SPI_TRANSMIT(0xFF);
47
    SD_SPI_TRANSMIT(0xFF);    
48
49
    SD_SPI_CHIP_UNSELECT(SD_SS_PORT, SD_SS_PIN);
50
  
51
  return;

Das komplette Array ist mit 0 gefüllt. :/
Ich verstehe nicht wo das Problem ist -.-

von S. Landolt (Gast)


Lesenswert?

1
SD_Error_t SD_SoftwareReset(void)
2
{
3
  uint8_t Repeat = 0x00;
4
  
5
  //SD_SPI_CHIP_SELECT(SD_SS_PORT, SD_SS_PIN);
6
  
7
  for(uint8_t i = 0x00; i < 0x0A; i++)
8
  {
9
    SD_SPI_TRANSMIT(0xFF);
10
  }
11
  
12
  SD_SPI_CHIP_UNSELECT(SD_SS_PORT, SD_SS_PIN);
13
  
14
  while(SD_Command(SD_ID_TO_CMD(0), 0x00000000, 0x95, 0, 0) != SD_STATE_IDLE)

Vor dem CMD0 ein 'UNSELECT'? Verstehe ich nicht.

von Daniel K. (daniel_k80)


Lesenswert?

S. Landolt schrieb:
> Vor dem CMD0 ein 'UNSELECT'? Verstehe ich nicht.

Das ist noch übrig geblieben, weil ich vorher das Select davor hatte 
(das Auskommentierte). Das ist im Grunde zu viel, macht aber auch nicht 
mehr als den Pin auf High zu lassen...

von S. Landolt (Gast)


Lesenswert?

Das heißt, das CMD0 geht an der Karte vorbei?

von S. Landolt (Gast)


Angehängte Dateien:

Lesenswert?

Also falls Ihnen eine Vorlage fehlt, mit meiner Assembler-Bibliothek 
können Sie sicher nichts anfangen, aber hier habe ich etwas zu 
Vergleichszwecken, vor langer Zeit irgendwo aufgegabelt, ist wohl auch 
nur für SDC, nicht SDHC, aber vielleicht hilft es etwas.

von Daniel K. (daniel_k80)


Lesenswert?

Nein. Der Pin ist High und wird noch einmal auf High gesetzt, bleibt 
also High, da er vorher nicht mehr auf Low gezogen wird. Die 
Initialisierung der 4 GB Karte funktioniert auch problemlos, es ist nur 
die 512 MB Karte die zickt.
Aber wie gesagt, ich würde gerne erst das Problem mit dem Lesen lösen. 
Die 512 MB Karte schaue ich mir dann mal im Detail an.

von S. Landolt (Gast)


Lesenswert?

> Die Initialisierung der 4 GB Karte funktioniert auch problemlos

Pardon, mittlerweile habe ich da meine Zweifel. Z.B. wird ohne gesetztes 
SS das CMD0 von der Karte doch gar nicht gesehen.

von Daniel K. (daniel_k80)


Lesenswert?

S. Landolt schrieb:
>> Die Initialisierung der 4 GB Karte funktioniert auch problemlos
>
> Pardon, mittlerweile habe ich da meine Zweifel. Z.B. wird ohne gesetztes
> SS das CMD0 von der Karte doch gar nicht gesehen.

Das SS wird in der Funktion "SD_Command(SD_ID_TO_CMD(0), 0x00000000, 
0x95, 0, 0)" gesetzt.
Das was überflüssig war, war das Selektieren und Deselektieren der 
SD-Karte bei den ersten 80 Taktzyklen nach einem Power-On Reset :)
1
uint8_t SD_Command(uint8_t Command, uint32_t Arg, uint8_t Checksum, uint32_t Count, uint8_t* Buffer)
2
{
3
  // Create 8 clock pulse before activating the card
4
  SD_SPI_TRANSMIT(0xFF);
5
  SD_SPI_CHIP_SELECT(SD_SS_PORT, SD_SS_PIN);
6
  SD_SPI_TRANSMIT(Command);
7
  SD_SPI_TRANSMIT(Arg >> 0x18);
8
  SD_SPI_TRANSMIT(Arg >> 0x10);
9
  SD_SPI_TRANSMIT(Arg >> 0x08);
10
  SD_SPI_TRANSMIT(Arg);
11
  SD_SPI_TRANSMIT(Checksum);
12
  
13
  /*  
14
  Wait for the response (0 - 8 bytes for SD cards and 1 - 8 bytes for MMC)
15
  The spec also say that you have to wait 8 clock cycles after the last bus
16
  transaction.
17
  */      
18
  for(uint8_t i = 0; i < 0x08; i++)
19
  {
20
    uint8_t DataIn = SD_SPI_TRANSMIT(0xFF);
21
    if(DataIn != 0xFF)
22
    {
23
      // Read all additional data
24
      if(Count > 0)
25
      {
26
        for(uint32_t j = 0x01; j < Count; j++)
27
        {
28
          *Buffer++ = SD_SPI_TRANSMIT(0xFF);
29
        }
30
      }
31
      
32
      // Send a dummy byte and deselect the card after it
33
      SD_SPI_TRANSMIT(0xFF);
34
      SD_SPI_CHIP_UNSELECT(SD_SS_PORT, SD_SS_PIN);
35
36
      return DataIn;
37
    }
38
  }
39
  
40
  SD_SPI_CHIP_UNSELECT(SD_SS_PORT, SD_SS_PIN);
41
  
42
  return SD_NO_RESPONSE;
43
}

von S. Landolt (Gast)


Lesenswert?

Okay, ich bin am Ende; ein anderer muss weiterhelfen.
Einen schönen Abend noch.

von Daniel K. (daniel_k80)


Lesenswert?

Hallo,

ich glaube ich habe das Problem ausmachen können.
Ich betreibe die SD-Karte an einem XPlained, welches über USB versorgt 
wird. das Board wurde die ganze Zeit von einem Hub in einer Tastatur 
versorgt. Das Auslesen hat wunderbar funktioniert, als ich das Board an 
einen USB-Port am Rechner gesteckt habe.
Wahrscheinlich hat der Hub in der Tastatur einfach zu wenig Leistung 
bereitstellen können (die Tastatur wird ja auch nur über USB 
betrieben...) und daher hat sich die SD-Karte nicht korrekt verhalten.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.