Forum: Mikrocontroller und Digitale Elektronik Problem FatFS + SPI


von Markus M. (mmax)


Angehängte Dateien:

Lesenswert?

Hi,

Ich sitz heute schon den ganzen Tag davor via SPI und Chan's FatFS eine 
SD Karte anzusprechen. Basierend auf den Code von Martin Thomas [1] 
versuche ich die Lowlevel Routinen zu implementieren, doch leider komm 
ich über die  Initialisierung (Funktion sdc_disk_initialize()) schon 
nicht drüber.

Auf den CMD8 bekomm ich 0x7F zurück, also offensichtlich keine SDv2 
Karte - OK. Auf ACMD41 bekomm ich 0x3F zurück, also auch keine SDv1, 
sondern eine MMC Karte - Das macht mich schon stutzig. Doch da beim 
setzten der Blocksize (CMD16) auch 0x7F und nicht 0x0 zurückkommt, wird 
der Kartentyp auf 0 gesetzt und die Initialisierung schlägt fehl.

Anbei mein Code und ein Screenshot vom Logicanalyzer.

Jemand eine Idee?

[1] 
http://siwawi.bauing.uni-kl.de/avr_projects/arm_projects/arm_memcards/index.html#chanfat_stm32

von eric (Gast)


Lesenswert?

Was mir jetzt spontan auffällt, aber keine Ahnung ob es das Problem ist:
-CS sollte für die 10 dummy Byte zum Anfang der Initialisierung high 
sein (Karte nicht ausgewählt)
-Max. 400KHz SPI Takt beim Initialisieren (viele Karten sind da aber 
nicht pingelig)
-Nach jedem Cmd CS auf high und noch ein Byte 0xFF senden (außer nach 
CMD55 in der Mitte von ACMDxx, da scheint dein code CS auch kurz 
hochzuziehen)

Damit bekomme ich zumindest meine 8GB MicroSD Karten problemlos 
initialisiert und werden auch korrekt als SDv2 erkannt. Was für eine 
Karte verwendest du? 'Echte' MMC Karten sind heutzutage ziemlich 
exotisch.

von eric (Gast)


Lesenswert?

Korrektur: CMD55 behandel ich wie alle anderen Befehle auch.

von Falk B. (falk)


Lesenswert?

@ Markus M. (mmax)

>Ich sitz heute schon den ganzen Tag davor via SPI und Chan's FatFS eine
>SD Karte anzusprechen. Basierend auf den Code von Martin Thomas [1]
>versuche ich die Lowlevel Routinen zu implementieren,

Ist das nicht ein kleiner Widerspruch in sich? FatFs ist als solches 
komplett, da muss man nix mit Low Level Funktion rummurksen. Man muss 
lediglich die allerunterste Hardwareschicht an den jeweiligenh 
Controller anpassen, spricht, den SPI-Zugriff.

>Jemand eine Idee?

Wie sieht deine Hardware aus? Schaltplan? Bild vom realen Aufbau?

von Markus M. (mmax)


Lesenswert?

Falk B. schrieb:
> @ Markus M. (mmax)

> Ist das nicht ein kleiner Widerspruch in sich? FatFs ist als solches
> komplett, da muss man nix mit Low Level Funktion rummurksen. Man muss
> lediglich die allerunterste Hardwareschicht an den jeweiligenh
> Controller anpassen, spricht, den SPI-Zugriff.

Ja genau, FatFs kümmert sich um das Filesystem und der LowLevel Zugriff 
muss, abhängig vom Interface selbst implementiert werden - in meinem 
Fall ist das SPI. Das funktioniert prinzipiell ja auch da die SD Karte 
auf Kommandos meldet.

Aber ich denke, wenn jemand mit dem Thema zu tun hatte, weiß er wovon 
ich spreche.

>>Jemand eine Idee?
>
> Wie sieht deine Hardware aus? Schaltplan? Bild vom realen Aufbau?

Aktuell noch eine fertiges STM32F103 Board aus China (BluePill) und ein 
Breakout-Board mit dem SD Kartenhalter.

von Falk B. (falk)


Lesenswert?

@ Markus M. (mmax)

>Ja genau, FatFs kümmert sich um das Filesystem und der LowLevel Zugriff
>muss, abhängig vom Interface selbst implementiert werden - in meinem
>Fall ist das SPI. Das funktioniert prinzipiell ja auch da die SD Karte
>auf Kommandos meldet.

>Aber ich denke, wenn jemand mit dem Thema zu tun hatte, weiß er wovon
>ich spreche.

Ich hatte damit schon mehrfach zu tun und hab mich dabei nicht eine 
Sekunde um die Low Level Geschichten gekümmert. OK, stimmt nicht ganz, 
da war mal was 8-0

Beitrag "Re: Problem mit Micro-SD-Karte"

Möglicherweise hast du ein ähnliches Problem.

von Markus M. (mmax)


Lesenswert?

Falk B. schrieb:
> Ich hatte damit schon mehrfach zu tun und hab mich dabei nicht eine
> Sekunde um die Low Level Geschichten gekümmert. OK, stimmt nicht ganz,
> da war mal was 8-0

Mit Low-Level meine ich die Implementation jener Funktionen die auf 
Chans Webseite [1] als "Media Access Interface" bezeichnet werden. Und 
da ich schon mit der Initialisierung kämpfe, konkret um die Funktion 
disk_initialize().

[1] http://elm-chan.org/fsw/ff/00index_e.html
>
> Beitrag "Re: Problem mit Micro-SD-Karte"
>
> Möglicherweise hast du ein ähnliches Problem.

Das hab ich schon durchgelesen, werds mir aber nochmal anschauen.

von Markus M. (mmax)


Angehängte Dateien:

Lesenswert?

Vielleicht könnte ja mal jemand meine Aufzeichnungen des Logic Analyzers 
ansehen oder mit den eigenen vergleichen.

Die erste Aufzeichnung entsteht durch die Antwort auf CMD0. Da kommt 
auch eine 0x01 zurück und die Karte dürfte im Idle-Mode sein - das 
scheint zu passen.
1
spi_res = sdc_spi_send_cmd(CMD0, 0);
2
if (spi_res == 1) { /* Put the card SPI/Idle state */

Bei der Zweiten kommt auf den CMD8 ein 0x7F (127d) zurück, was mir schon 
komisch vorkommt. Ist das eine plausible Antwort, wenn es sich um keine 
SDv2 (SDHC) Karte handelt? Kann das jemand bestätigen?
1
/* Check SD version */
2
 spi_res = 0;
3
 spi_res = sdc_spi_send_cmd(CMD8, 0x1AA);
4
 if (spi_res == 1) {
5
    /* SDv2 card */

Also springt mein Code in die nächste Abfrage - SDv1 oder MMC. Ich bin 
mir ziemlich sicher dass es sich nicht um eine MMC handelt, und doch 
kommt auf das ACMD41 eine Wert größer 1 zurück. Dritte Aufzeichnung - 
uns spätestens hier passt was nicht. Hier wird ja davor ein CMD55 
verschickt und der ACMD41 mit 0x7F oder verknüpft.

Da kommt dann 0x3F (63d) zurück, also größer 1 und offensichtlich eine 
MMC, was ich nicht glauben kann. Ich habs auch mit einer Sandisk SDHC 
probiert und komm zu dem selben Ergebnis.
1
spi_res = sdc_spi_send_cmd(ACMD41, 0);
2
if (spi_res <= 1) {
3
  /* SDv1 (ACMD41(0)) */
4
  type = CT_SD1;
5
  cmd = ACMD41;
6
                
7
} else {
8
  /* MMCv3 (CMD1(0)) */
9
  type = CT_MMC;
10
  cmd = CMD1; 
11
}

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Markus M. schrieb:
> Bei der Zweiten kommt auf den CMD8 ein 0x7F (127d) zurück, was mir schon
> komisch vorkommt. Ist das eine plausible Antwort, wenn es sich um keine
> SDv2 (SDHC) Karte handelt? Kann das jemand bestätigen?

 Wenn es eine normale SD-Karte ist, kriege ich meistens 0x05 zurück.
 Allerdings musst du nach CMD8 zuerst 5 (fünf) Bytes einlesen und erst
 dann die Antwort prüfen.
 Byt(0) = result (muss 0x01 sein für SDHC) alles andere deutet auf
          normale Karten, also SD.

> Also springt mein Code in die nächste Abfrage - SDv1 oder MMC. Ich bin
> mir ziemlich sicher dass es sich nicht um eine MMC handelt, und doch
> kommt auf das ACMD41 eine Wert größer 1 zurück.

 Falsch.
 a) SD Karte:
 Falls nach CMD8 etwas anderes als 0x01 zurückkommt, sendet man solange
 CMD1, bis result 0x00 wird.
 Ich stelle loopcounter auf 2500 aber so nach 250-300 Versuchen kriege
 ich 0x00 zurück und breche den loop ab.

 b) SDHC Karte:
    Byt(3) Voltage       (muss 0x01 sein)
    Byt(4) Check Pattern (muss 0xAA sein)
  Danach CMD58 um zu sehen, ob 3V3 unterstützt wird.
  Danach ACMD41 für Initialisation.
  Danach wieder CMD58, um zu sehen ob es sich um SDHC oder um SDSC
  handelt, weil CCS bit erst nach erfolgreicher Initialisation gültig
  ist.
  Danach CID und CSD einlesen und das war es für SDHC und SDSC.


  Danach bei beiden SPI Clock auf Max und gut ist es.

von Markus M. (adrock)


Lesenswert?

Hi,

sagmal bist Du sicher das
1
SPI2->DR = data;

das ein BYTE Zugriff ist? Das Register ist m.W. als 16 Bit definiert, 
folglich wird der SPI 16 Bits schicken.

Ich musste das zumindest beim STM32F030 entsprechend auf ein 
Byte-Zugriff "casten".

von Markus M. (mmax)


Lesenswert?

Markus M. schrieb:
> Hi,
>
> sagmal bist Du sicher das
>
>
1
> SPI2->DR = data;
2
>
>
> das ein BYTE Zugriff ist? Das Register ist m.W. als 16 Bit definiert,
> folglich wird der SPI 16 Bits schicken.
>
> Ich musste das zumindest beim STM32F030 entsprechend auf ein
> Byte-Zugriff "casten".

Ist bei mir auf 8-Bit konfiguriert ... und das sieht man ja auch im 
Logic Analyzer Output
1
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;

von Markus M. (mmax)


Lesenswert?

Marc V. schrieb:
>  Wenn es eine normale SD-Karte ist, kriege ich meistens 0x05 zurück.
>  Allerdings musst du nach CMD8 zuerst 5 (fünf) Bytes einlesen und erst
>  dann die Antwort prüfen.
>  Byt(0) = result (muss 0x01 sein für SDHC) alles andere deutet auf
>           normale Karten, also SD.
>

Hmmm ... ich dachte dass man die Implementation von Martin Thomas 
diesbezüglich so übernehmen kann. Also die Abfolgen was man wann sendet 
und welche Antworten wie zu verarbeiten sind. Nagut, die letzte Version 
ist jetzt fast sieben Jahre alt - vielleicht hat sich da was bei den SD 
Karten getan.

Kennt vielleicht jemand eine aktuellere Version die man verwenden kann?

>
>  Falsch.
>  a) SD Karte:
>  Falls nach CMD8 etwas anderes als 0x01 zurückkommt, sendet man solange
>  CMD1, bis result 0x00 wird.
>  Ich stelle loopcounter auf 2500 aber so nach 250-300 Versuchen kriege
>  ich 0x00 zurück und breche den loop ab.


Pronzipiell wir nach jedem CMD sowieso so lange (bzw. max 10 mal) 0xFF 
geschickt (also weitergetaktet) solange im Ergebnis das höchstwertige 
Bit gesetzt ist

1
n = 10; /* Wait for response (10 bytes max) */
2
    do {
3
        res = sdc_spi_transfer(0xFF);
4
    } while ((res & 0x80) && --n);


>  b) SDHC Karte:
>     Byt(3) Voltage       (muss 0x01 sein)
>     Byt(4) Check Pattern (muss 0xAA sein)
>   Danach CMD58 um zu sehen, ob 3V3 unterstützt wird.
>   Danach ACMD41 für Initialisation.
>   Danach wieder CMD58, um zu sehen ob es sich um SDHC oder um SDSC
>   handelt, weil CCS bit erst nach erfolgreicher Initialisation gültig
>   ist.
>   Danach CID und CSD einlesen und das war es für SDHC und SDSC.

Soweit war ich noch nie ;-)
Wie gesagt, wenn die Abläufe in der Referenzimplementation so nicht 
passen, muss ich mir was Anderes suchen.

Da bin ich für jedes Codebeispiel dankbar!

von Olaf (Gast)


Lesenswert?

Hier mal ein kleiner Tip.

Das allererste was man macht wenn man mit SD-Karten rumspielt, man 
schaltet nach der MMC-Initialisierung gleich die CRC wieder ein. Dann 
waerst du dir naemlich jetzt sicher das die uebertragenen Kommandos und 
Daten korrekt sind und muesstest nicht darueber nachsinnen ob irgendwo 
ein Bit komisch ist. Solltest du dagegen irgendeinen groben Fehler 
gemacht haben, wie z.B einen falschen SPI-Mode so wurde das gleich sehr 
deutlich auffallen.

Und spaeter im Betrieb sorgt es dafuer das du bei Fehlern nicht gleich 
mal eine Karte oder Datei verlierst.

Olaf

von Markus M. (mmax)


Lesenswert?

Olaf schrieb:
> Hier mal ein kleiner Tip.
>
> Das allererste was man macht wenn man mit SD-Karten rumspielt, man
> schaltet nach der MMC-Initialisierung gleich die CRC wieder ein.

Naja, aber über genau diese Initialisierung komm ich ja noch nicht 
drüber ;-)

Aber prinzipiell hast du natürlich recht!

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Markus M. schrieb:
> Pronzipiell wir nach jedem CMD sowieso so lange (bzw. max 10 mal) 0xFF
> geschickt (also weitergetaktet) solange im Ergebnis das höchstwertige
> Bit gesetzt ist

 Nein, das sagt dir genau nichts.
 Laut SD-Spezifikation muss beim Antwort Bit7 immer 0 sein.

 Warum probierst du es nicht mit CMD1 nach CMD8 ?

 Und nach CMD8 immer 5 Bytes einlesen, egal wie R1 aussieht !

von Markus M. (mmax)


Angehängte Dateien:

Lesenswert?

Marc V. schrieb:
>  Nein, das sagt dir genau nichts.
>  Laut SD-Spezifikation muss beim Antwort Bit7 immer 0 sein.
>
>  Warum probierst du es nicht mit CMD1 nach CMD8 ?
>
>  Und nach CMD8 immer 5 Bytes einlesen, egal wie R1 aussieht !

Ich hab was gefunden. Verschicke ich nach einem "erfolglosen" CMD8 ein 
CMD1 solange CMD1 einen Wert ungleich null zurück liefert, sehe ich zwar 
via LA dass nach dem zweiten Durchlauf die 0x00 zurück kommt (siehe 
Screenshot) aber spi_res scheint den Wert 0x01 zu erhalten (sehe ich 
beim Debuggen)
1
        spi_res = sdc_spi_send_cmd(CMD8, 0x1AA);
2
        
3
        if (spi_res != 0x01) {
4
            do {
5
                spi_res = sdc_spi_send_cmd(CMD1,0);
6
            } while( spi_res != 0x00 );
7
        }

Also passt da was nicht. Bei alle anderen Ergebnisse, die ich so 
kontrolliert habe, stimmt der Output vom Debugger und vom LA überein ... 
sehr eigenartig.

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Markus M. schrieb:
> Ich hab was gefunden. Verschicke ich nach einem "erfolglosen" CMD8 ein
> CMD1 solange CMD1 einen Wert ungleich null zurück liefert, sehe ich zwar
> via LA dass nach dem zweiten Durchlauf die 0x00 zurück kommt (siehe
> Screenshot) aber spi_res scheint den Wert 0x01 zu erhalten (sehe ich
> beim Debuggen)

 Hmmm.
 Wahrscheinlich kriegst du 0xFF zurück aber beim prüfen wird dieser
 Wert AND mit 0x01 und deswegen denkst du, dass da eine 0x01
 zurückkommt.


Markus M. schrieb:
> Also passt da was nicht. Bei alle anderen Ergebnisse, die ich so
> kontrolliert habe, stimmt der Output vom Debugger und vom LA überein ...
> sehr eigenartig.

 Eigentlich nicht.
 Ich habe mir gerade deinen Code angesehen.
 In sdc_spi_send_cmd(..) die zwei Zeilen (if Abfrage) auskommentieren.
1
    /* Receive command resp */
2
 //***     if (cmd == CMD12) {
3
        sdc_spi_transfer(0xFF); /* Diacard following one byte when CMD12 */
4
 //***   }
 D. h. immer ein Dummy Byte hinterher schicken und erst dann lesen.

 Auch folgendes würde nicht schaden:
1
    /* Send command packet */
2
   sdc_spi_enable();
3
4
   sdc_spi_transfer(0xFF); /* Zuerst ein Dummy Byte - kann manchmal Wunder wirken !! */
5
6
   sdc_spi_transfer(0x40 | cmd); /* Start + command index */
7
    ...

 Probieren (und melden, ob es geholfen hat).

: Bearbeitet durch User
von Markus M. (mmax)


Lesenswert?

Marc V. schrieb:
>  Eigentlich nicht.
>  Ich habe mir gerade deinen Code angesehen.
>  In sdc_spi_send_cmd(..) die zwei Zeilen (if Abfrage) auskommentieren.
>
1
>     /* Receive command resp */
2
>  //***     if (cmd == CMD12) {
3
>         sdc_spi_transfer(0xFF); /* Diacard following one byte when CMD12 
4
> */
5
>  //***   }
6
>
>  D. h. immer ein Dummy Byte hinterher schicken und erst dann lesen.

Naja, das mit der if-Abfrage ist sowieso sinnfrei da in der 
darauffolgenden while-Schleife auch die 0xFF verschickt werden.
1
        n = 10;                 /* Wait for response (10 bytes max) */
2
        do {
3
            res = sdc_spi_transfer(0xFF);
4
        } while ((res & 0x80) && --n);

>  Auch folgendes würde nicht schaden:
>
1
>     /* Send command packet */
2
>    sdc_spi_enable();
3
> 
4
>    sdc_spi_transfer(0xFF); /* Zuerst ein Dummy Byte - kann manchmal 
5
> Wunder wirken !! */
6
> 
7
>    sdc_spi_transfer(0x40 | cmd); /* Start + command index */
8
>     ...
9
>
>
>  Probieren (und melden, ob es geholfen hat).

Ja, das hats gebracht ... vor dem command ein 0xFF wirkt in meinem Fall 
wirklich Wunder. Danke für den Tip! Jetzt komm ich schon mal weiter.

von Markus M. (mmax)


Angehängte Dateien:

Lesenswert?

Marc V. schrieb:
> Markus M. schrieb:
>> Ich hab was gefunden. Verschicke ich nach einem "erfolglosen" CMD8 ein
>> CMD1 solange CMD1 einen Wert ungleich null zurück liefert, sehe ich zwar
>> via LA dass nach dem zweiten Durchlauf die 0x00 zurück kommt (siehe
>> Screenshot) aber spi_res scheint den Wert 0x01 zu erhalten (sehe ich
>> beim Debuggen)
>
>  Hmmm.
>  Wahrscheinlich kriegst du 0xFF zurück aber beim prüfen wird dieser
>  Wert AND mit 0x01 und deswegen denkst du, dass da eine 0x01
>  zurückkommt.

Bei der Abfrage von R7 scheint das selbe Problem zu sein. LA zeigt die 
korrekte Antwort (1.Bild) aber im Debug-Output (2.Bild) bin ich wieder 
um das eine Bit falsch.
1
            /* SDv2 card */
2
            sdc_spi_enable();
3
            
4
            for (n = 0; n < 4; n++) {
5
                /* Get 32 bit return value of R7 response */
6
                ocr[n] = sdc_spi_transfer(0xFF);
7
            }
8
            
9
            sdc_spi_disable();
10
            
11
            /* Check if SD supports voltage between 2.7 and 3.6 V */
12
            if (ocr[2] == 0x01 && ocr[3] == 0xAA) {

Was meinst du mit "beim prüfen wird dieser Wert AND mit 0x01" ... das 
muss ich wegbekommen.

von Marc V. (Firma: Vescomp) (logarithmus)


Angehängte Dateien:

Lesenswert?

Markus M. schrieb:
> Ja, das hats gebracht ... vor dem command ein 0xFF wirkt in meinem Fall
> wirklich Wunder. Danke für den Tip! Jetzt komm ich schon mal weiter.

 Ja, und mich hats so um die 2 Liter Kaffee und eine ganze Nacht
 gekostet.

Markus M. schrieb:
> Bei der Abfrage von R7 scheint das selbe Problem zu sein. LA zeigt die
> korrekte Antwort (1.Bild) aber im Debug-Output (2.Bild) bin ich wieder
> um das eine Bit falsch.

 Kann ich leider nicht nachvollziehen (BTW, auch nicht verstehen).

 Anbei 2 Screenshots, 512MB sendet 0x05, wird danach mit CMD1 ohne
 Probleme initialisiert, 1GB-Kingston akzeptiert CMD8, nur ist es bei
 mir Version 0 (?).

Markus M. schrieb:
> Was meinst du mit "beim prüfen wird dieser Wert AND mit 0x01" ... das
> muss ich wegbekommen.

 Vielleicht, dass du irgendwo so etwas machst:
1
    if ((res & 0x01) == 0x01) {

 Mein Vorschlag ist:
 CMD8 senden, danach 20..30Bytes in ein Array einlesen (ohne die Werte
 überhaupt zu prüfen) und danach Array ausdrucken.
 Und nicht dauernd SPI_Enable und SPI_Disable, sondern nur vor und
 nach entspr. CMD.

 P.S.
 Bei R7 darf bei OCR(0) bit7 niemals Log.1 sein

 Kann es sein, dass bei dir der Empfang um 1 Nibble versetzt ist ?

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

Das klingt alles nicht sonderlich sinnvoll. Fakt ist, FATfs von ELm Chan 
läuft stabil, das ist tausendfach bewiesen worden. Wenn was klemmt, dann 
sind es die Low Level Zugriffe, welche durch ihr Fehlverhalten zu 
Fehlern in höheren Protokollfunktionen führen.

Mein Tip. Mach erstmal die Funktion xchg_spi() fit, die kann man auch 
testweise direkt aufrufen und prüfen, ob sie exakt ein Byte per SPI 
transferiert. Dann nutzt man diese als Funtkionsaufruf in den Funktionen 
rcvr_spi_multi() und xmit_spi_multi(), um die Blockübertragungen zu 
machen. Ist zwar deutlich langsamer, aber egal. Das MUSS dann erstmal 
funktionieren! Danach kann man die Funktionen noch ohne den 
Funktionsaufruf mit direktem Registerzugriff optimieren.

(Hätte ich das damals bei meinem Fehler auch so gemacht, hätte ich mir 
eine tagelange Fehlersuche mit Logicanalyzer und Debugger erspart . . .)

Ich hoffe mal, daß du auch einen 10ms Timeraufruf für die Funktion 
mmc_disk_timerproc() hast.

von Markus M. (mmax)


Angehängte Dateien:

Lesenswert?

So, hatte leider wenig Zeit in den letzten beiden Tagen ... also gings 
heute erst wieder weiter. Leider ohne weitere Erkenntnis

Marc V. schrieb:
>  Vielleicht, dass du irgendwo so etwas machst:
>
1
>     if ((res & 0x01) == 0x01) {
2
>

Nein, hab alles kontrolliert. Hier nochmal der relevante Code:
1
        spi_res = sdc_spi_send_cmd(CMD8, 0x1AA);
2
        
3
        if (spi_res == 1) {
4
            /* --- DAS PASST NOCH --- */
5
            sdc_spi_enable();
6
            
7
            for (n = 0; n < 4; n++) {
8
                /* Get 32 bit return value of R7 response */
9
                ocr[n] = sdc_spi_transfer(0xFF);
10
            }
11
            
12
            sdc_spi_disable();
13
            
14
            /* Check if SD supports voltage between 2.7 and 3.6 V */
15
            if (ocr[2] == 0x01 && ocr[3] == 0xAA) {
16
               /* --- HIER NICHT MEHR --- */

Und bei der Routine sdc_spi_transfer() wird nur versendet, gewartet und 
wieder eingelesen ... mehr nicht.

>  Mein Vorschlag ist:
>  CMD8 senden, danach 20..30Bytes in ein Array einlesen (ohne die Werte
>  überhaupt zu prüfen) und danach Array ausdrucken.
>  Und nicht dauernd SPI_Enable und SPI_Disable, sondern nur vor und
>  nach entspr. CMD.

Das schaut dann so aus (1.Zahl ist TX, dann kommt RX):
1
CMD8 ...
2
0xff 0xff
3
0x48 0xff
4
0x 0 0xff
5
0x 0 0xff
6
0x 1 0xff
7
0xaa 0xff
8
0x87 0xff
9
0xff 0xff
10
0xff 0x 1
11
... 0x01
12
 
13
0xff 0x 1
14
0xff 0x 0
15
0xff 0x 0
16
0xff 0xab
17
0xff 0xfe
18
0xff 0xff
19
0xff 0xff
20
0xff 0xff
21
0xff 0xff
22
0xff 0xff
23
0xff 0xff
24
0xff 0xff
25
0xff 0xff
26
0xff 0xff
27
0xff 0xff
28
0xff 0xff
29
0xff 0xff
30
0xff 0xff
31
0xff 0xff
32
...

CMD8 wird korrekt mit 0x01 quittiert. Die vier Byte nach dem CMD8 passen 
aber nicht ganz:
1
IST:
2
0000 0001 | 0000 0000 | 0000 0000 | 1010 1011
3
----------------------------------------------------------
4
SOLL:
5
0000 0000 | 0000 0000 | 0000 0001 | 1010 1010
6
----------------------------------------------------------
7
ERROR:
8
        X |           |         X |         X

>
>  P.S.
>  Bei R7 darf bei OCR(0) bit7 niemals Log.1 sein
>
>  Kann es sein, dass bei dir der Empfang um 1 Nibble versetzt ist ?

Ich hab keine Ahnung - Es sind beim ersten, dritten und vierten Byte das 
LSB invertiert. Dahinter steckt für mich keine Logik. Außerdem sollten 
die Byte laut LA ja passen, nur der STM32 liest sie falsch ein - scheint 
zumindest so.

Also die Frage lautet - wieso liest der STM32 die vier Byte (CR7) falsch 
ein! Ich denke ich muss mir mal das Signal mit dem Oszi genauer 
anschauen.

von Markus M. (mmax)


Angehängte Dateien:

Lesenswert?

Hier nochmal ein Bild vom Oszi. Das einzige was mir auffällt ist die 
schlechte Flanke vom Clock (in rot).

Kann sein dass die Versorgung für die SD Karte nicht ausreichend ist - 
für den LA evtl. kein Problem aber für den STM32 schon?

Ich versorge die SD über das Board. Ist so ein China Teil [1] mit einem 
AMS1117 Spannungsregler ... wobei der bis zu 1A liefern sollte.

[1] http://blog.lincomatic.com/?p=1761

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Markus M. schrieb:
> Kann sein dass die Versorgung für die SD Karte nicht ausreichend ist -
> für den LA evtl. kein Problem aber für den STM32 schon?

 Irgendetwas stimmt da nicht - jetzt sieht dein LA die vier Bytes als
 0x00-0x00-0x01-0xAA, vorher waren es aber 0x80-0x00-0x01-0xAA ?

> Ich versorge die SD über das Board. Ist so ein China Teil [1] mit einem
> AMS1117 Spannungsregler ... wobei der bis zu 1A liefern sollte.

 Für mich ist das eindeutig ein Hardware Fehler, aber dass es an der
 unzureichenden Stromversorgung liegt, wage ich zu bezweifeln - 1A ist
 mehr als genug, allerdings wirkt ein Elko zwischen STM32 und SD-Modul
 manchmal auch Wunder ;)

 Manchmal auch ein 100E Widerstand in der Clockleitung...

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ Markus M. (mmax)

>Hier nochmal ein Bild vom Oszi. Das einzige was mir auffällt ist die
>schlechte Flanke vom Clock (in rot).

Sieht komisch aus. Da stimmt was nicht. Entweder mit deiner Messung oder 
it der HArdware? Hast du für den Kanal einen 10:1 Tastkopf benutzt? Den 
ein 1:1 Tastkopf ist DEUTLICH langsamer (größere Anstiegszeit).

>Kann sein dass die Versorgung für die SD Karte nicht ausreichend ist -
>für den LA evtl. kein Problem aber für den STM32 schon?

Wir sehen deine Versorgung nicht.

>Ich versorge die SD über das Board. Ist so ein China Teil [1] mit einem
>AMS1117 Spannungsregler ... wobei der bis zu 1A liefern sollte.

Sollte reichen, erst recht für einen einfachen Lesezugriff.

Ich wiederhole mich.

Beitrag "Re: Problem FatFS + SPI"

von Markus M. (mmax)


Lesenswert?

So, ich habs gefunden!

Ich hatte im laufe meiner Tests mal probiert die STM32 internen 
Push-Pull-Widerstände via GPIO Konfig zu deaktivieren und die IOs auf 
Open-Drain gestellt, da ich dachte dass am Breakout-Board des SD-readers 
ja schon Pullups vorhanden sind.

1
    // GPIO pins for MOSI (PB15), MISO (PB14), and SCL (PB13)
2
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_14 | GPIO_Pin_13;
3
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD; // PP;
4
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
5
    GPIO_Init(GPIOB, &GPIO_InitStruct);
6
7
    // GPIO pin for CS (PB12)
8
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
9
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; //PP;
10
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
11
    GPIO_Init(GPIOB, &GPIO_InitStruct);

Das war offensichtlich das Problem und im laufe meiner Änderungen hab 
ich leider vergessen das wieder zurückzustellen. Jetzt schaut das 
Clock-Signal auch wieder sauber aus.

Jetzt komm ich über die Abfrage der OCR Bits nach dem CMD8 drüber und 
das testen geht weiter.

Danke auf jeden Fall für all eure Hilfe! Ich bin ja wirklich für jede 
Anregung/Idee dankbar und mir wurde hier schon oft geholfen. Oft 
übersieht man Offensichtliches ja ganz einfach.

von grundschüler (Gast)


Lesenswert?

Wenn die Hardware ok ist, funktioniert der chan code auch. Habe gerade 
fat auf f103 implementiert.

Ob die hardware ok ist, kann man mit dem foolproof -idiotensicher- 
code/bitbang/avr gut überprüfen. Mit leichten Anpassungen läuft das auf 
jeder mcu.

von Markus M. (mmax)


Lesenswert?

Falk B. schrieb:
>
> Ich wiederhole mich.
>
> Beitrag "Re: Problem FatFS + SPI"

Danke Hr.Falk ... aber ich bin ja noch gar nicht so weit dass es zu 
einer Lese- oder Schreiboperation kommt und scheiterte an der 
Initialisierung selbst.

Jetzt bin ich weiter und werde mich aufs Lesen stürzen!

von grundschüler (Gast)


Lesenswert?

habe bei meinem f103 versucht, fat von spi1 auf spi2 umzustellen. Geht 
bei mir auch nicht obwohl die hardware in ordnung ist.

von grundschüler (Gast)


Angehängte Dateien:

Lesenswert?

grundschüler schrieb:
> habe bei meinem f103 versucht, fat von spi1 auf spi2 umzustellen.

klappt jetzt mit bitbang auf den spi2-pins. hardware-spi2 geht immer 
noch nicht.

von Markus M. (mmax)


Angehängte Dateien:

Lesenswert?

Anbei nochmal mein code, verwende auch SPI2 ... vielleicht findest ja 
was.

Bei mir haut mittlerweile alles, ohne schreiben, hin. Hatte heute nicht 
mehr Zeit da weiter zu machen, wird aber jetzt auch kein Problem mehr 
sein - Hoffe ich halt.

von grundschüler (Gast)


Lesenswert?

Fehler gefunden. Und zwar hier:
Beitrag "Re: Stm32f103 Problem mit Spi2"
1
//  while (SPIx_SR & _BV(7)) ;
2
  while (!(SPIx_SR & 1<<0));//0_rxne 1_txe 7_bsy// ok

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.