Probleme beim Lesen von Daten von einer microSD-Karte

Ich versuche, einen Datenblock von einer Micro-SD-Karte mit Standardkapazität zu lesen, aber die empfangenen Daten ergeben keinen Sinn. Hier ist, was ich mache:

  • Initialisieren der Karte
  • Lesen von Daten
    • CS niedrig einstellen
    • Senden von CMD16 zum Einstellen der Blocklänge
    • Senden von CMD17 mit Startadresse
    • Warten auf Startbyte (0xfe)
    • Bytes empfangen und auf dem seriellen Terminal ausgeben
    • CRC empfangen
    • CS hoch einstellen
    • Senden von 8 zusätzlichen Takten (?)

Die Daten, die ich zu lesen versuche, sind der FAT16-Bootsektor, wie unten gezeigt: KarteninhaltUnd die Daten, die ich herausbekomme, sind diese:Geben Sie hier die Bildbeschreibung ein

An diesem Punkt kann ich nicht einmal ansatzweise daran denken, was falsch läuft. Ich denke nicht, dass es ein Übertragungsfehler ist, da die Daten immer gleich sind. Ich kann auch jedes Mal die Bootsektor-Signatur 0x55 0xAA lesen, selbst wenn ich die Startadresse auf 510 setze und zwei Bytes lese, kommen sie perfekt zurück. Das Problem ist, dass ich andere Bytes nicht lesen kann.

Ich habe auch versucht, Karten zu tauschen, aber das hat auch nicht geholfen.

Was vermisse ich?

EDIT: Die fragliche Funktion ist unten.

bit sd_read_block(unsigned long size, unsigned long start_addr)
{
    unsigned long i;
    unsigned char r;

    SD_CS = 0;

    r = sd_card_cmd(16, size, 0);

    sprintf(usb_uart_tx_buffer, "CMD16 R Token: %02x.\r\n", r);
    usb_uart_tx(usb_uart_tx_buffer);

    r = sd_card_cmd(17, start_addr, 0);

    sprintf(usb_uart_tx_buffer, "CMD17 R Token: %02x.\r\n", r);
    usb_uart_tx(usb_uart_tx_buffer);

    // wait for start token
    r = 0;
    while (spi_rx_byte() != 0xfe) {
        if (r++ > 25) {
            SD_CS = 1;
            return r;
        }
    }

    for (i = 0; i < size; i++) {
        if (i % 20 == 0) {
            UART1_TX(0x0d);
            UART1_TX(0x0a);
        }
        sprintf(usb_uart_tx_buffer, "%02x ", spi_rx_byte());
        usb_uart_tx(usb_uart_tx_buffer);
    }

    // CRC
    spi_rx_byte();
    spi_rx_byte();

    // extra clocks
    r = spi_rx_byte();

    SD_CS = 1;

    return 0;
}
Ich kann nicht wirklich sagen, was los ist - aber es scheint, dass die Byte-Größe falsch ist - da Fat16 eine andere Größe als Fat32 / NTFS verwendet. Alle 00 am Anfang machen keinen Sinn. und dann scheinen einige Bytes zu fehlen/komprimiert? Irgendetwas stimmt nicht mit der Art und Weise, wie die Bytes empfangen/interpretiert werden.

Antworten (1)

Es stellt sich heraus, dass ich den MBR gelesen habe, der sich unter der Adresse 0auf der SD-Karte befindet. Um den Ort des Bootsektors zu finden, muss man den entsprechenden Eintrag im MBR lesen. Die Einträge beginnen bei der Adresse 0x01beund sind jeweils 16 Byte groß. Die interessante Stelle im Eintrag liegt am Offset 0x08, ist 4 Byte lang und wird als LBA bezeichnet. [Wikipedia] Um die Adresse des Bootsektors zu erhalten, würde man die LBA mit der Größe eines Sektors (512 Bytes) multiplizieren. [Microchip-Forum]

Zum Beispiel:

In der obigen Ausgabe sehen die vier Einträge so aus:

00 02 10 00 06 2f ef af 8d 00 00 00 73 0f 3a 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Wie Sie sehen können, wird nur ein Eintrag verwendet. Die LBA ist 8d 00 00 00und ist in diesem Fall im Little-Endian-Format, also wäre sie in Big-Endian 0x8doder 141 dezimal. Multiplizieren Sie dies mit 512 und Sie erhalten 72192 ( 0x11a00). Dies ist die Adresse des Sektors, in dem die FAT beginnt.