FatFs: Warum kann ich Sektor 0 nicht richtig lesen?

Hintergrund: Ich verwende ein nRF52832 Development Kit mit dieser microSD-Karte in diesem Breakout-Board . Die Karte wird mit 3 V versorgt (ich habe getestet, ob der Dev-Kit-Regler und eine externe Stromversorgung ausgeführt werden). Ich verwende 22-Ohm-Serienwiderstände auf den SCLK-, SDO-, SDI-, CS-Leitungen und einen 10-kOhm-Pullup-Widerstand auf SDO.

Ich verwende FatFs, um die SD-Karte zu mounten und in eine Datei zu schreiben. Ich kann die Karte initialisieren, aber mein Aufruf von f_opengibt den Fehlercode 13 ( FR_NO_FILESYSTEM) zurück.

Nach einigem Graben konnte ich feststellen, dass FR_NO_FILESYSTEMvon einem Aufruf an zurückgegeben wird find_volume, der versucht, eine FAT-Partition auf dem Laufwerk zu finden. Ich verstehe, dass dies bedeutet, Sektor 0 der Karte und die Bytes 510 und 511 zu lesen. Für ein gültiges FAT-Volume sollten diese Bytes 0x55 0xAA sein. Wenn ich mir jedoch die SPI-Transaktionen ansehe, scheint meine Karte 0x00 0x00 zurückzugeben.

Ich habe versucht, meine SD-Karte mit dem offiziellen SD-Kartenformatierer , dem Windows-Formatierungstool, dem Festplattendienstprogramm von OS X, Ubuntu gparted und dd als FAT32 zu formatieren , aber um sicherzugehen, habe ich Hex Workshop verwendet, um den Bootsektor der SD zu lesen Karte auf meinem Laptop und habe an der entsprechenden Stelle 0x55 0xAA gesehen:

Bildschirmaufnahme von Hex Workshop

Ich verwende ein Saleae Logic Pro, um die SPI-Sequenz zu erfassen. Ich bin mir nicht sicher, wie ich die gesamte Erfassung am besten teilen kann, aber hier ist eine Tabelle mit allen decodierten Werten: http://pastebin.com/gQh07QfE

Sie können sehen, dass die Initialisierung gut funktioniert (sie reagiert auf CMD0, CMD8 usw.) und gegen Ende 0xFE zurückgibt (was meines Wissens nach ein gültiges Datentoken anzeigt?), Aber dann 0x00 0x00 anstelle von 0x55 0xAA.

Meine ffconf.h ist hier: http://pastebin.com/1XRa7c94 -- Meine sdmm.c ist leicht modifiziert, um die Nordic SPI API ( nrf_drv_spi_transfer) und die Verzögerungsfunktion ( nrf_delay_us) zu verwenden. Ich verwende einen separaten GPIO-Pin als CS ( nrf_gpio_pin_setund nrf_gpio_pin_clear).

Hat jemand eine Idee, warum dieses Lesen nicht funktioniert?

Ähm .. Ich erinnere mich vage an einige Probleme mit Windows-Tools, die "Sektor 0" an einer anderen Stelle als dem eigentlichen Sektor 0 platziert haben, wahrscheinlich um den Bootsektor zu "schützen" ... wie durch Lesen mit "dd" unter Linux festgestellt. Das war vor einigen Jahren auf einer CF-Karte, nicht auf SD, kann also nicht mehr zutreffen. (Aber ich würde vorsichtshalber mit dd abgleichen)
SD-Karten benötigen Pull-Ups an allen Pins (mit Ausnahme eines Pins mit internem Pull-Up). Dies ist nicht optional und wird von der Spezifikation vorgeschrieben. Dies wird Ihr Problem wahrscheinlich nicht beheben, aber Sie sollten es trotzdem in Betracht ziehen.
Können Sie Daten, die nicht 0 sind, von einer anderen Adresse auf der SD abrufen?
@crasic, nicht dass ich sagen kann! Der gesamte Sektor 0 wird als 0x00 angezeigt, ebenso jeder andere Sektor, den ich ausprobiert habe (obwohl die Karte ansonsten leer ist).

Antworten (1)

Es stellte sich heraus, dass die Antwort mit der Art und Weise zu tun hatte, wie ich die SPI-Transaktionen mit dem Nordic SDK implementiert habe.

Meine rcvr_mmc-Funktion sah so aus:

static
void rcvr_mmc (
    BYTE *buff, /* Pointer to read buffer */
    UINT bc     /* Number of bytes to receive */
)
{
    nrf_drv_spi_transfer(&spi, NULL, 0, buff, bc);
}

Ich nahm an, dass mein rcvr_mmc funktionierte, da ich Befehlsantworten korrekt analysierte. Das Lesen von Sektoren funktionierte jedoch überhaupt nicht. Ich habe nicht einmal volle 512 * 8 Taktzyklen gesehen.

Als mir klar wurde, dass dies passiert war, schaute ich mir den Nordic SDK SPI-Treiber genauer an und entdeckte Folgendes:

https://devzone.nordicsemi.com/question/66434/nrf_drv_spi_transfer-larger-transfer-size/

Da Sektorlesevorgänge bc=512 passieren, führte dies dazu, dass nichts wirklich gelesen wurde. Mein derzeit sehr ineffizienter Hack, um diese Arbeit zu bekommen, ist:

int i;
uint8_t small_buf[1];
for (i = 0; i < bc; i++) {
    nrf_drv_spi_transfer(&spi, NULL, 0, small_buf, 1);
    buff[i] = small_buf[0];
}