Forum: Mikrocontroller und Digitale Elektronik SD Karte mit Ulrich Radigs Software zeigt keine Dateien


von C. H. (hedie)


Lesenswert?

Hallo

Ich versuche nun schon seit einigen Tagen eine SD Karte (1GB) an mein 
Mikrocontroller Board anzuschliessen (STM32F103RB Controller)

Ich verwende die Sourcen von Ulrich Radig (www.ulrichradig.de)

Es hat ein weilchen gedauert bis die Kommunikation einwandfrei lief 
(hardware SPI) doch dies ist nun kein problem mehr...

Ich kann problemlos Blöche a 512 bytes lesen sowie die adresse für den 
Volumen Master Boot Record holen und auch diesen problemlos auslesen.

Nur zeigt mir das beispiel keine Dateien an welche auf der Karte sind :(

Ich hab mir mal über den UART einfach die ersten 1000 Blöcke auslesen 
lassen und auf inhalt der bytes geprüft also ob das byte etwas 
beinhaltet und nur diese dan ausgegeben... Ich hab über den UART alle 
Dateien empfangen

Es muss also irgendwo am code vom ulrich liegen das es nicht klappt 
denke ich mal...

Ich habe etwas am code geändert

ursprünglich hiess die funktion für das Speichern der daten So:
1
void Cluster_Data_Store (void)

da ich dann jedoch probleme mit dem buffer hatte, weshalb weiss ich bis 
jetzt nicht. Hab ich mich entschieden den buffer aus der Main mittels 
pointer zu übergeben.

1
void Cluster_Data_Store (unsigned char *Buffer)

Ich sehe mit dem Debugger, das es die
1
struct BootSec *bootp; //Zeiger auf Bootsektor Struktur

Bootsektor Struktur korrekt befüllt.

Doch leider bekomme ich keine Daten aus dem Root Directory
1
  //Ausgabe des Root Directory <-------------------------------------------------------------
2
  printf("\nDirectory\n\n\r");
3
        unsigned int a;
4
  for (a = 0;a < 240;a++)
5
  {
6
    cluster = Read_Dir_Ent(0,a,&Size,&Dir_Attrib,buffer);
7
      if (cluster == 0xffff)
8
      {
9
        break;
10
      }
11
    tmp = (Size & 0x0000FFFF);
12
    printf("Cluster = %4x DirA = %2x Size= %8d FileName = ",cluster,Dir_Attrib,tmp);
13
    printf(buffer);
14
    printf("\n\r");
15
  }
16
  printf("\nDirectory Ende\n\n\r");
17
  
18
  cluster= 0x0;

Hat vielleicht jemand einen Tipp für mich?

Danke schonmal

von Pete K. (pete77)


Lesenswert?

Für Dateien brauchst Du ein Dateisystem (z.B. FAT oder FAT32).

von C. H. (hedie)


Lesenswert?

Jip das weiss ich :)

Ulrich Radig hat ja da seine Fat.c mit im paket...

Doch leider scheint da bei mir etwas nicht ganz zu klappen....

von zerrome (Gast)


Lesenswert?

Hallo,
wenn du Debuggen kannst, schau dir doch mal an ob der richtige Sektor 
des Root-Dirs geladen wird. Ist die Karte vielleicht Partitioniert oder 
so?

Meist ist es wenig hilfreich auf andere Libs zu verweisen, aber du 
könntest zum Vergleich auch mal diese Lib probieren : 
http://www.mikrocontroller.net/articles/AVR_FAT32

Grüße

von C. H. (hedie)


Lesenswert?

Hallo Zerrome

Ich habe die Library angepasst und getestet...

Doch leider klappt es nicht :(

Initialisieren geht problemlos doch er belibt an dieser Stelle hängen:
1
//Wartet auf Start Byte von der MMC/SD-Karte (0xFE/Start Byte)
2
   while (mmc_read_byte() != 0xFE){};


mmc_read_byte und mmc_write_byte sieht so bei mir aus:
1
// **********************************************************************************************************************************
2
//Routine zum Empfangen eines Bytes von der MMC-Karte 
3
// **********************************************************************************************************************************
4
unsigned char mmc_read_byte (void){
5
6
        unsigned char Byte = 0xFF;
7
  // mmc/sd in hardware spi
8
  #if (MMC_SOFT_SPI==FALSE)
9
    mmc_write_byte(0xFF);
10
          Byte = SPI_I2S_ReceiveData(SPI1);
11
          while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET);
12
    return (Byte);
13
  #endif
14
}
15
16
17
// **********************************************************************************************************************************
18
//Routine zum Senden eines Bytes zur MMC-Karte
19
// **********************************************************************************************************************************
20
void mmc_write_byte (unsigned char Byte){
21
22
23
  // mmc/sd in hardware spi
24
  #if (MMC_SOFT_SPI==FALSE)
25
    SPI_I2S_SendData(SPI1,Byte);
26
                while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET);
27
  #endif
28
}

Vielleicht entdeckt ja jemand mein problem :(

Danke schonmal

von zerrome (Gast)


Lesenswert?

Hallo,
ich bin mir da noch nicht so sicher, dass die Initialisierung korrekt 
ist. Probier mal die Initialisierung ohne eine Karte im Slot zu haben, 
wenn das auch geht, ist da schon ein Fehler.

SPI_I2S_XXX diese Funktionen kenne ich nicht. Wenn aber sicher ist das 
sie das machen was sie sollen sieht das auf den ersten blick schon Ok 
aus.
Das define RESET ist das richtige?

Versuche mal die SPI Geschwindigkeit nach der Initialisierung nicht auf 
Maximalen Speed zu setzen.

Grüße

von C. H. (hedie)


Lesenswert?

Hallo Zerrome

Danke für deine antwort...

Also ohne karte im Slot klappts nicht... es kommt auch wirklich 0x01 
nach CMD0 zurück... somit sollten die Funktionen SPI_I2S_XXX auch 
klappen...

Diese sind übrigens aus der Library von ST (also ST Microelectronics) 
diese sind für die STM32 Cortex M3 controller....

Ich erhöhe den speed nacht dem initialisieren auch nicht...

Habe inzwischen mit einer 8GB SDHC Karte getestet.... Genau das 
gleiche... Initialisieren klappt der rest jedoch nicht mehr :(

von zerrome (Gast)


Lesenswert?

Hm, nach cmd0 ist die Karte ja noch nicht fertig initialisiert.
Da fehlt noch cmd1 bei Standard mmc/sd Karten, aber soweit wohl in 
Ordnung.

Wenn das Initialisieren Klappt, muss eigentlich auch der Rest gehen, 
weil ja die Kommunikation soweit schon klappt.

Was bekommst du denn auf ein cmd17 nach der Initialisierung zurück?
Quasi nach so einem Kommando:
1
unsigned char cmd[] = {0x40+17,0x00,0x00,0x00,0x00,0xFF};

Da sollte dann auch irgendwann der Sektor 0 zurück kommen...

von C. H. (hedie)


Lesenswert?

Also ich hab nun über mmc_write_command deine komandos gesendet also 
CMD17

doch leider belibt er hier hängen:
1
  // warten auf gueltige antwort nach senden des kommandos
2
  Timeout=0;
3
  tmp=0xFF;
4
  do{
5
    tmp = mmc_read_byte();
6
    if (Timeout++ > 1000){
7
      break; // in timeout gelaufen, da die karte nicht korrekt antwortet
8
    }
9
  }while (tmp == 0xFF);
10
  return(tmp);

Es kommt also immer 0xFF zurück...

############### EDIT #########################

Hab nun beim Write Command folgendes am beginn hinzugefügt
1
//set MMC_Chip_Select to low (MMC/SD-Karte Deaktiviert)
2
GPIO_WriteBit(GPIOA,GPIO_Pin_4,Bit_SET);
3
4
  //sendet 8 Clock Impulse
5
  mmc_write_byte(0xFF);
6
7
  //set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
8
  GPIO_WriteBit(GPIOA,GPIO_Pin_4,Bit_RESET);

Nun kommt auf CMD17 0 zurück
und auf CMD0 auch nach dem init 1 zurück

von C. H. (hedie)


Lesenswert?

Wenn ich nun den beispiel code teste
kann ich die FAT nicht initialisieren
1
fat_loadFatData()

liefert nun false zurück

von zerrome (Gast)


Lesenswert?

Ok, das Problem ist,
wenn fat_loadFatData false zurück liefert, funktioniert mmc_read_sector 
nicht richtig. Sonst würde die Fat Initialisierung durchlaufen.

Was du da in der write command geändert hast ist letztens erst 
rausgeflogen, muss aber wohl doch bei einigen Karten sein.

Hab aber auch nicht so recht eine Idee warum read sector nicht 
funktionieren sollte...

Grüße

von C. H. (hedie)


Lesenswert?

Hmmm was würdest du an meiner stelle tun?

Andere lib verwenden?

Alles neu schreiben?

Debuggen? wenn ja wo?

Ich blick da langsam echt nicht mehr durch... hab jetzt schon sooo viel 
energie in diese dooofe SD karte investiert :(

Hoffe jemand hat nen geistesblitz :P

von zerrome (Gast)


Lesenswert?

Wenn du die Möglichkeit hast, versuch mal ein paar unterschiedliche 
Karten, vielleicht ne kleine SD oder MMC Karten oder so. Ich mach mir 
mal Gedanken was man da machen kann.

Also immer Stück für Stück probieren bis man an die Stelle kommt wo es 
hakt.
Wenn die Initialisierung wirklich richtig geklappt hat, sollte der Rest 
kein Problem sein.

Grüße

von C. H. (hedie)


Lesenswert?

Ok vielen dank für deine Hilfe :)

Ich hoffe gemeinsam kriegen wir raus was da schiefläuft :)

Meld dich sobald dir was durch den kopf gegangen ist :)

Also bei anderen karten ists genau das selbe...
Ich werd nochmal versuchen mit dem Debugger was rauszukriegen

Danke schonmal

von C. H. (hedie)


Lesenswert?

Morgen Zerrome...

Ich hab kleinere neuigkeiten...

So wies aussieht liegt das problem beim Schreiben eines blockes...

Wen ich nach dem senden der Daten die nächsten bytes empfange, kommt nie 
das Response byte zurück... also hier:
1
//Fehler beim schreiben? (Data Response XXX00101 = OK)
2
  if((mmc_read_byte()&0x1F) != 0x05) 
3
        {
4
        return 2;
5
        }

Es kommt eeewig 0xFF

siehe beitrag hier

Beitrag "SD Karte Lesen und Schreiben klappt NICHT nacheinander"

von zerrome (Gast)


Angehängte Dateien:

Lesenswert?

Moin :)
Schön das es Fortschritte gibt.
So wie ich das grad sehe, ist das wohl eine Lücke in der Spezifikation 
?!?
Ich habe mal ein Bild angehangen und die Stelle über die wir reden Rot 
markiert. Da ist Tatsache eine Lücke wo die Spezifikation nix zu sagt. 
Werde damit mal ein wenig rumprobieren. Seltsamerweise habe ich hier 
eine Toshiba SDHC die nicht meckert und mehrere SD/MMC Karten die das 
alles so schlucken. Seltsame Sache.
Werde heute abend genaueres sagen können.

Grüße

von C. H. (hedie)


Lesenswert?

Hab das problem lösen können

>So hab das problem nun selbst gefunden und gelöst...

>In der AVR Library hier aus dem Forum hat es Fehler drinn...

>Es sollte nicht heissen

>//CRC-Byte schreiben
>  mmc_write_byte(0xFF); //Schreibt Dummy CRC
>  mmc_write_byte(0xFF); //CRC Code wird nicht benutzt

>  //Fehler beim schreiben? (Data Response XXX00101 = OK)
>  if((mmc_read_byte()&0x1F) != 0x05) return FALSE;


>Sondern man muss Abwarten bis der Respond kommt! Nicht jede karte hat
>gleich lange...

>Obige zeilen sind also komplett durch diese hier zu ersetzen...
>Da mmc_read_byte() auch dummy clocks sendet entfällt das separate sender
>dieser für die CRC abfrage...

>while((mmc_read_byte()&0x1F) != 0x05);

Ich kann nun also problemlos Sektoren lesen und schreiben...

Doch nun habe ich ein anderes Problem


Wen ich nun load_Fat_Data ausführe, dan belibt er bei dieser Zeile 
hängen:
1
mmc_read_sector(secOfFirstPartition,fat.sector);  // lesen von fat sector und bestimmen der wichtigen berreiche

Genauer gesagt im code beim mmc_read_sector nach dem senden der Adresse 
welche ich folgendermassen verpacke:
1
addr = addr << 9; //addr = addr * 512
2
3
   cmd[1] = ((addr & 0xFF000000) >>24 );
4
   cmd[2] = ((addr & 0x00FF0000) >>16 );
5
   cmd[3] = ((addr & 0x0000FF00) >>8 );
6
   cmd[4] = (addr &  0x000000FF);

Er bekommt nach dem mmc_send_command ein 0x00 zurück
jedoch sendet danach die Karte kein startbyte (0xFE).

Hier der Code abschnitt:
1
if( 0 != mmc_write_command(cmd) )  return 0;
2
3
   //Wartet auf Start Byte von der MMC/SD-Karte (0xFE/Start Byte)
4
   while (a != 0xFE){
5
   a = mmc_read_byte();
6
   };

Wenn ich beim ursprünglichen code
1
mmc_read_sector(secOfFirstPartition,fat.sector);  // lesen von fat sector und bestimmen der wichtigen berreiche

secOfFirstPartition durch 0 ersetze, dann kommt er durch... (der rest 
klappt dann jedoch dennoch nicht!)

Somit hat es denke ich mit der übergebenen Adresse zu tun

secOfFirstPartition ist beim übergeben 0x6964654d

Bei meiner Karte Steht übrigens im Sektor 0 der MBR also wo auch MSDOS 
FAT16 etc.. steht...

von Daniel R. (zerrome)


Lesenswert?

Also, so sieht der betreffende Abschnitt im Original aus:
1
void *vsector=&fat.sector[454];
2
3
secOfFirstPartition=*(unsigned long int*)vsector;
4
5
    
6
    if(secOfFirstPartition==0x6964654d){            secOfFirstPartition=0;
7
  }
8
    else{                    mmc_read_sector(secOfFirstPartition,fat.sector);
9
  }

Vor diesem Ausschnitt wird der Sektor 0 geladen. dann werden 4 Bytes ab 
Stelle 454 des Sektors rausgepikt und geprüft ob sie 0x6964654d 
entsprechen. Wenn ja, ist bereits der MBR geladen. Wenn nicht steht auf 
secOfFirstPartition die Sektor Nummer mit der die 1. Partition beginnt.

Wenn du jetzt aber versuchst Sektor Nummer 0x6964654d = 1768187213 zu 
laden wirst du warscheinlich Pech haben weil es den Sektor nicht gibt...

Diese Funktion ist so richtig. Wenn es da Probleme gibt, vermute ich 
immer noch Probleme bei deinen MMC/SD Routinen zum lesen.

Grüße

von Daniel R. (zerrome)


Lesenswert?

Ah was mir grad einfällt, für welche Plattform portierst du das? Ist das 
ein Big Endian System? Wenn nicht gibt das dann Probleme wegen den 
ganzen void Pointern und der Art und Weise wie die benutzt werden...

von C. H. (hedie)


Lesenswert?

Sooo eeendlich :)

Also wegen Big Endian...

Ich verwende einen STM32F103RB Cortex M3 Controller...
Der ist laut ST standardmässig im little endian format kann jedoch beim 
Resetten auf big endian gestellt werden...

Was genau ist eigentlich big und little endian?

Es hat endlich geklappt :)

Ich kann nun Dateien lesen und schreiben :)

Vielen Dank an alle!!!

Ich werde ein ZIP schnüren und es in der section zur verfügung 
stellen...
Das war jetzt echt ein riesen energie aufwand.. hat viel nerven 
gekostet...

Dies war nun das letzte problem
1
secOfFirstPartition=*(unsigned long int*)vsector;
2
3
    
4
    if(secOfFirstPartition==0x6964654d){            secOfFirstPartition=0;
5
  }
6
    else{                    mmc_read_sector(secOfFirstPartition,fat.sector);
7
  }

Vielen Dank an alle die mir hier so tatkräftig geholfen haben :)
Ihr seit echt Suuuuuper spitze :)

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.