Forum: Mikrocontroller und Digitale Elektronik AVR+SD-Card: inititialisierung klappt nur bei einer von 3 karten


von Martin S. (msperl)


Lesenswert?

Hallo!

Ich versuche jetzt gerade eine andere als meine bisher verwendetet SD 
Karte anzusprechen und stoße auf das Problem das meine bisherige 
Initialisierungs-Routine sich an dieser (und auch einer Weiteren) 
verschluckt.

Und ich verstehe nicht ganz wieso...

Hier die init routine:
1
        uint8_t i,r;
2
        SET(MMC_CS);
3
        for(i=0;i<32;i++) { uspi_getc(); }
4
        _delay_us(1);
5
        RESET(MMC_CS);
6
7
        /* now go idle via CMD0 - GO IDLE_STATE */
8
        uint8_t c=0;
9
        while(mmc_cmd(CMD0,0,0,0,0)!=1) { 
10
                /* after 16 tries fall asleep and wait for reboot */
11
                if ((c++)>16) { mmc_error(); }
12
        }
13
14
        /* check SD card version via CMD8 */
15
        while(1) {
16
                /* try CMD8 - SEND_IF_COND */
17
                if (
18
                        mmc_cmd_crc7(CMD8,0x40,0,0x01,0xaa,0x15) 
19
                        == (4 | 1)
20
                        ) {
21
                        /* if it is BAD, then we are of type 1 */
22
                        mmc_type=1;
23
                        break;
24
                }
25
                /* otherwise read 4 byte */
26
                r=uspi_getc();
27
                uspi_getc();
28
                uspi_getc();
29
                if (uspi_getc() == 0xaa) {
30
                        mmc_type=2;
31
                        break;
32
                }
33
                if (r|0x40) { mmc_type|=IS_SDHC; }
34
        }
35
36
        /* send out SD Card type so far on "normal" SPI */
37
        /* and depending on the type send ACMD with different args */
38
        if ((mmc_type&0x0f)==2) {
39
                do {
40
                        /* for type 2 cards use ACMD41*/
41
                        r=mmc_acmd(ACMD41,0x40,0x00,0x00,0x00);
42
                } while (r);
43
        } else {
44
                do {
45
                        /* for type 1 cards use CMD1 */
46
                        r=mmc_cmd(CMD1,0x00,0x00,0x00,0x00);
47
                } while (r);
48
        }
49
        /* check for SDHC card */
50
        if ((mmc_type&0x0f)==2) {
51
                /* read OCR */
52
                if (mmc_cmd_crc7(CMD58,0,0,0,0,0x87)==0) {
53
                        /* of SDHC type */
54
                        if ((uspi_getc()&0xc0)!=0xc0) {
55
                                mmc_type|=IS_SDHC;
56
                        }
57
                        uspi_getc();
58
                        uspi_getc();
59
                        uspi_getc();
60
                }
61
        }
62
63
        /* pull CS high, as we have finished */
64
        SET(MMC_CS);

Das Problem ist die schleife:
1
                do {
2
                        /* for type 2 cards use ACMD41*/
3
                        r=mmc_acmd(ACMD41,0x40,0x00,0x00,0x00);
4
                } while (r);

bei der einen 2G-Karte die funktioniert, braucht es ca 0.25 sekunden bis 
endlich 0 zurück kommt. Die anderen beiden Karten (4G und 2G, aber schon 
recht alt) verbleiben für mehr als meine 8 Sekunden Watchdog timeout in 
der Schleife...

Am SPI bus kommt bei den beiden nicht-funktionierenden Karten folgendes 
in einer quasi-Endlos-Schleife:
1
0x77 -> 0xff
2
0x00 -> 0xff
3
0x00 -> 0xff
4
0x00 -> 0xff
5
0x00 -> 0xff
6
0x95 -> 0xff
7
0xff -> 0xff
8
0xff -> 0x01
9
;---------------------
10
0x69 -> 0xff
11
0x40 -> 0xff
12
0x00 -> 0xff
13
0x00 -> 0xff
14
0x00 -> 0xff
15
0x95 -> 0xff
16
0xff -> 0xff
17
0xff -> 0x01

Bei der funktionierenden kommt wie schon gesagt irgendwann statt 0x01 
dann 0x00 und es geht weiter mit CMD58...

Hat jemand eine Idee, was da falsch sein könnte?

Danke,
      Martin

P.s: vieleicht das noch:
* Funktionierend:
** Transcend micro - 2GB
* nicht funktionierend:
** Kingston micro - 2GB - 3-4 Jahre alt
** No-Name microHC 4GB

von Chris L. (kingkernel)


Lesenswert?

Um dir helfen zu können brauchen wir den ganzen code + schaltplan!
hast du mal an die üblichen stolpersteine gedacht?
- im Init nicht mehr als 400kHz SPI-Frequenz
- Pullup an der MISO-Leitung

von Jim M. (turboj)


Lesenswert?

1
mmc_cmd_crc7(CMD8,0x40,0,0x01,0xaa,0x15)

Das stimmt so nicht, das 0x40 setzt ein als "reserved" markiertes Bit, 
siehe Spezifikation auf sdcard.org. Da muss 0x00 rein, die Checksumme 
ist dann 0x87.

Dashalb funktionieren die neuren Karten alle nicht, die kennen das CMD8 
aber mögen das falsch gesetzte Bit nicht.

von Martin S. (msperl)


Lesenswert?

Danke für die Hinweise!

Irgendwie lag die Versorgungsspannung Spannung auf der SD Karte unter 
den erwarteten 3.3V und das scheinen nicht alle Karten genau so gut zu 
verkraften...

Jetzt (bei 3.27V) funktionieren die 3 Karten korrekt...

Danke für die Tipps!

Allerdings habe ich jetzt mit einer 4ten Karte (frisch gekaufte SANDisk 
Ultra - 4GB, die hoffentlich schneller beim schreiben ist) jetzt das 
Problem, daß mir diese beim ACMD41 statt mit 0x01 oder 0x00 mit 0x05 
antwortet - Illegal Command bei einer 4GB Karte? (Um den Verdacht zu 
überprüfen, dass die Karte "gefälscht" ist, habe ich sie mit Dateien mit 
schon bekannter md5-prüfsumme auf das maximale Volumen gefüllt und 
nachher die Prüfsummen von den dateien auf der Karte ermitteln lassen - 
100% Übereinstimmung bei allen Dateien...)

Vielleicht finde ich da ja auch noch irgendwie eine Lösung - nur nicht 
mehr heute...

Martin

von Martin S. (msperl)


Lesenswert?

P.s: im code ist CMD8 ist zurückgesetzt auf 
mmc_cmd_crc7(CMD8,0x00,0x00,0x01,0xaa,0x87) - habe ich irgendwann 
gesetzt, nachdem ich in einer doku dieses Bit als "host-SDHC" fähig 
gelesen habe. War ursprünglich auch mit 0x00...

von Martin S. (msperl)


Lesenswert?

OK - was es bedurfte um die Karte aus dem 0x05 zu bekommen war zwischen 
CMD55 und CMD41 ein paar 0xff - in meinem Fall habe ich 4 gewählt - zu 
schicken...

Jetzt hapert es aber beim schreiben - Ultra sind anders...

von Martin S. (msperl)


Angehängte Dateien:

Lesenswert?

OK, was mich jetzt viel mehr wundert ist das diese ULTRA Karte mir die 
"akzeptiert" Antwort (0x05) auf meinen "Block write schon zu schicken 
scheint, wenn ich das erste Byte der "fake" CRC7 schicke (ob ich jetzt 
0x55,0xaa oder 0xff,0xff schicke ist egal)...

Das kommt mir erst bei dieser Karte vor - die anderen 3 Karten schicken 
0x05 es erst nach dem Ende der 2 CRC7 byte.

Hat das schon jemand gesehen?

Danke, Martin

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.