Forum: Mikrocontroller und Digitale Elektronik SD-Karte und Multitasking


von Programmierer (Gast)


Lesenswert?

Hallo,

ich habe auf einem STM32 der mit 72 MHz läuft ein Programm das alle 
500µs eine Funktion für eine Prozesssteuerung ausführt (Eingabe - 
Berechnung - Ausgabe). Das sind dann 36000 verfügbare Takte zur 
Ausführung der Steuerungsfunktion. Sie braucht davon ca. 25000.

Jetzt würde ich gerne pro Ausführung einen Datenblock aus 512 Bytes aus 
Logdaten generieren und diesen auf eine SD-Karte speichern (sequentiell 
an eine Datei anhängen o.ä.). Diese würde per Hardware-SPI (18 MHz max) 
angebunden werden. 2kHz * 512 Bytes ~= 1MByte/Sec sollte möglich sein. 
Zur Übertragung eines 512Bytes Datenblock würden 4096 SPI-Takte = 16384 
CPU-Takte benötigt.
Für die Ansteuerung würde ich die Elm-Chan FatFs Library nehmen.

Leider passt das SD-Karten-Schreiben so nicht hinein, denn 16384+25000 > 
36000. Allerdings wäre es per DMA möglich, den Datenblock automatisch 
zum SPI rauszuschieben. Nur wie integriere ich das in die FatFs Library? 
Die ruft eine "disk_write" Funktion auf zum Schreiben auf die Karte und 
erwartet dass der Vorgang nach dessen Rückkehr fertig ist. Ich müsste 
FatFs dazu bringen...
* Den Schreibvorgang zu starten
* DMA-Transfer zu starten
* die CPU freizumachen für die Prozess-Steuerungs-Funktion (Rückkehr aus 
f_write ohne dass disk_write fertig ist??)
und nach Abschluss des Blocktransfers das Schreiben abzuschließen. Aber 
wie? Gibt es vieleicht eine Fat/SD-Library die das kann?

In kurz: Wie gleichzeitig eine Berechnung und eine SD-Ansteuerung 
umsetzen, wenn nicht genug CPU-Zeit da ist um auf die Übertragung zu 
warten, aber per DMA parallel geschrieben werden könnte?

von A. S. (rava)


Lesenswert?

Rechne mit 10k Schreibzyklen vor dem Defekt der Karte.
Wenn immer auf einen Sektor geschrieben würde, wäre die Karte nach 5sek 
hin.


Zum Glück verteilst du die Auslastung auf mehrere Sektoren. Aber auf wie 
viele?

von Programmierer (Gast)


Lesenswert?

A. S. schrieb:
> Rechne mit 10k Schreibzyklen vor dem Defekt der Karte.
So wenige? Da haben ja manche Mikrocontroller mehr Flash-Zyklen. Nicht 
eher 10M?
> Wenn immer auf einen Sektor geschrieben würde, wäre die Karte nach 5sek
> hin.
Darum gehts natürlich nicht. Bei der gegebenen Rate ist eine 32GByte 
Karte nach >9h voll. Wenn ich 10000x eine Karte 9h lang vollschreiben 
kann (=> insgesamt >10 Jahre Betriebszeit), ist das vollkommen 
ausreichend.
> Zum Glück verteilst du die Auslastung auf mehrere Sektoren. Aber auf wie
> viele?
Das macht die Karte doch automatisch (Wear-Leveling).

von dummy (Gast)


Lesenswert?

>Das macht die Karte doch automatisch (Wear-Leveling).

Das wird dir auch den Strich durch die Rechnung machen alle 500µs
einen Sektor zu schreiben.

von Εrnst B. (ernst)


Lesenswert?

Programmierer schrieb:
> Das macht die Karte doch automatisch (Wear-Leveling).

Früher hatten manche SD-Karten-Controller nur ein Wear-Leveling für die 
Sektoren, auf denen die FAT lag, weil da am meisten geschrieben wurde.
(bzw: Für die ersten X Megabyte ein besseres Wear-Leveling als für den 
Rest)
Nachdem die Spezifikation FAT als Dateisystem vorgeschrieben hatte, war 
das garnicht so dumm..

Deswegen wäre hier interresant:

A. S. schrieb:
> Wenn immer auf einen Sektor geschrieben würde, wäre die Karte nach 5sek
> hin.

Welcher Sektor?

von Michael R. (mr-action)


Lesenswert?

Spannend ist auch, das die ne 16GB Karte nach ca. 4,5 Stunden voll wäre 
und wie sieht das eigentlich mit der max. Dateigröße von 2GB aus? Du 
müsstest also nach ca. 30min eine neue Datei anfangen... :-o

von Verwunderter Leser (Gast)


Lesenswert?

Schreibt die FatFs wirklich nur einen Block? Sollten doch 4 Blöcke sein.
Der Datenblock, FAT, Kopie der Fat, Dateigröße im Verzeichniss.

von Programmierer (Gast)


Lesenswert?

dummy schrieb:
> Das wird dir auch den Strich durch die Rechnung machen alle 500µs
> einen Sektor zu schreiben.

Warum? Dauert die Suche nach Blöcken so lange? Ich habe ca 16KB RAM 
frei, könnte man das durch Puffern ausgleichen?

Εrnst B✶ schrieb:
> Früher hatten manche SD-Karten-Controller
d.h. ich nehme einfach eine neue Karte?

Εrnst B✶ schrieb:
> Welcher Sektor?
Wie gesagt möchte ich sequentiell eine Datei immer länger werden lassen 
(Log halt), d.h. es ist kein einzelner Sektor, sondern die ganze Karte.

Michael R. schrieb:
> Spannend ist auch, das die ne 16GB Karte nach ca. 4,5 Stunden voll wäre
Also nehme ich eine 32GB Ka

von Verwunderter Leser (Gast)


Lesenswert?

> es ist kein einzelner Sektor

Solange du Rohdaten ohne Filesystem schreibst: Ja.

Wenn die FatFs jedes mal ein Update auf das Verzeichnisse macht, sieht 
es ganz anders aus.

von Programmierer (Gast)


Lesenswert?

Nachdem Android meinen Post zerstückelt hat hier die Fortsetzung:

Michael R. schrieb:
> wie sieht das eigentlich mit der max. Dateigröße von 2GB aus? Du
> müsstest also nach ca. 30min eine neue Datei anfangen... :-o
Das ist akzeptabel.

Verwunderter Leser schrieb:
> Schreibt die FatFs wirklich nur einen Block? Sollten doch 4 Blöcke sein.
> Der Datenblock, FAT, Kopie der Fat, Dateigröße im Verzeichniss.
Gute Frage. Werden wirklich bei jedem einzelnen Schreibvorgang alle 4 
Blöcke geschrieben?

Verwunderter Leser schrieb:
> Solange du Rohdaten ohne Filesystem schreibst: Ja.
Wie gesagt ist das nicht der Plan.

Verwunderter Leser schrieb:
> Wenn die FatFs jedes mal ein Update auf das Verzeichnisse macht, sieht
> es ganz anders aus.
Wenn das Schreiben von Daten auf eine SD-Karte so problematisch ist, 
wieso werden die dann überhaupt verwendet?
Könnte ich nicht einfach jede Datei zu Anfang auf 2 GB setzen und mit 
0en füllen, und dann im Betrieb mit Daten auffüllen? Dann müssen die 
Metadaten im Betrieb gar nicht aktualisiert werden... Andere verwenden 
ja auch SD-Karten zum loggen.

Wie sieht das jetzt mit FatFS & DMA aus? Kann man das so hinbekommen?

von Eduard S. (schneehase)


Lesenswert?

Programmierer schrieb:
> In kurz: Wie gleichzeitig eine Berechnung und eine SD-Ansteuerung
> umsetzen, wenn nicht genug CPU-Zeit da ist um auf die Übertragung zu
> warten, aber per DMA parallel geschrieben werden könnte?

Wenn du den Ganzen overhead mit Fat weglässt, dann kannst du immer 512 
einfach auf die SD-Karte schreiben. Das Auslesen am PC ist dann 
schwieriger, dafür ist ist dein µC Programm einfacher. Du brauchst nur 
SD-Card-Init und write Sektor.

Oder du musst die Lib ein wenig umschreiben, um das um zusetzten.

Dazu machst du am besten ganz zu Beginn deines Programms eine Datei auf, 
da am Anfang mehrere Sektoren gelesen werden müssen.

Dann brauchst du 2x 512 Byte Puffer. Einer kann mit Daten befüllt werden 
und Einer kann auf die Karte geschrieben werden.

Dann musst du die "write" Funktion so umschreiben, dass 512 Byte in 
einen der Puffer geschrieben werden (oder besser die Funktion kann 
direkt mit den 512 Byte arbeiten).
Dann startest du den Vorgang mit DMA und aktivierst einen Interrupt der 
ausgeführt wird sobald die 512 Byte geschrieben wurden.
In dem Interrupt wechselst du die Puffer (musst du dir mit einem Flag 
merken).

von dummy (Gast)


Lesenswert?

>Wenn das Schreiben von Daten auf eine SD-Karte so problematisch ist,
>wieso werden die dann überhaupt verwendet?

Sie sind gross und billig. Der Anwendungszweck ist doch eher
Audiodaten abzuspielen und Fotos zu speichern. Da macht
es nichts aus wenn die Karte beim speichern mal 300ms Pause
macht. Für Echtzeitanwendungen wurden die nicht konstruiert.

von Falk B. (falk)


Lesenswert?

@Programmierer (Gast)

>36000. Allerdings wäre es per DMA möglich, den Datenblock automatisch
>zum SPI rauszuschieben. Nur wie integriere ich das in die FatFs Library?

Das ist mit einigem Aufwand verbunden.

>Die ruft eine "disk_write" Funktion auf zum Schreiben auf die Karte und
>erwartet dass der Vorgang nach dessen Rückkehr fertig ist.

Ja.

> Ich müsste
>FatFs dazu bringen...
>* Den Schreibvorgang zu starten
>* DMA-Transfer zu starten
>* die CPU freizumachen für die Prozess-Steuerungs-Funktion (Rückkehr aus
>f_write ohne dass disk_write fertig ist??)
>und nach Abschluss des Blocktransfers das Schreiben abzuschließen. Aber
>wie? Gibt es vieleicht eine Fat/SD-Library die das kann?

Keine Ahnung.

Ein Forumsteilnehmer hat das mal probiert, die Lösung erscheint mir aber 
nicht sonderlich solide.

Beitrag "sd-Karte Elm Chan DMA"

Beitrag "SD-Card mit DMA beschreiben"

von Grundschüler (Gast)


Lesenswert?

Falk Brunner schrieb:
> Ein Forumsteilnehmer hat das mal probiert, die Lösung erscheint mir aber
> nicht sonderlich solide.

Die Lösung ist in Bezug auf den DMA-Teil solide und tragfähig. Der 
Linktable-Teil müsste überarbeitet werden, weil ich die Verwendung von 
Linktable bei Elm Chan nicht wirklich nachvollziehen konnte.

Bei Linktable legt Fat zuerst eine Datei bestimmter Größe an. 
Anschließend werden die in der Linktable aufgelisteten Sektoren dieser 
Datei mit Daten gefüllt. Die Daten können dann ohne den Fat-Überbau 
geschrieben werden.

von holger (Gast)


Lesenswert?

>Die Lösung ist in Bezug auf den DMA-Teil solide und tragfähig.

Das mag sein, aber auch das verhindert das Wearlevelling nicht.
Wenn die Karte Busy ist ist sie Busy. Da bringt
DMA fast keinen Vorteil. Seine Echtzeitanforderungen
kann er nur mit einem riesigen RAM Buffer einigermassen einhalten.
Pro Millisekunde Busy sind das bei ihm ein Kilobyte RAM.
Und von meinen Karten weiss ich das die gerne so von 40ms bis
300ms Busy sind beim Wearlevelling. Und das zu nicht vorhersehbaren
Zeiten. Die Folgen kann man sich ja ausrechnen.

von Grundschüler (Gast)


Lesenswert?

holger schrieb:
> Wenn die Karte Busy ist ist sie Busy. Da bringt
> DMA fast keinen Vorteil.

Der gemessene Vorteil ist 1,2MByte/sec bei DMA gegenüber knapp 
0,5MByte/sec mit normalem Spi. Weiterer Vorteil von DMA ist , dass die 
CPU nicht belastet wird und während des Schreibens andere Aufgaben 
erledigen kann.

Die Busy-Zeiten sind relativ kurz und spielen bei der Übertragung von 
512 Byte-Blöcken nur eine sehr untergeordnete Rolle.

von Programmierer (Gast)


Lesenswert?

Eduard Scheske schrieb:
> Dann musst du die "write" Funktion so umschreiben, dass 512 Byte in
> einen der Puffer geschrieben werden (oder besser die Funktion kann
> direkt mit den 512 Byte arbeiten).
> Dann startest du den Vorgang mit DMA und aktivierst einen Interrupt der
> ausgeführt wird sobald die 512 Byte geschrieben wurden.
> In dem Interrupt wechselst du die Puffer (musst du dir mit einem Flag
> merken).
Das heißt also man gaukelt FatFS vor die Daten seien schon geschrieben 
obwohl sie es nicht sind, und reicht das nach? Raffiniert.

dummy schrieb:
> Da macht
> es nichts aus wenn die Karte beim speichern mal 300ms Pause
> macht.
Wäre bei mir auch nicht so schlimm wenn der Log ein paar Lücken hat, 
wenn das nicht zu oft auftritt (max 1x pro 5sek oder so).
> Für Echtzeitanwendungen wurden die nicht konstruiert.
Welches Speichermedium ist das denn? SSD und Bänder?

Mir kam folgende Idee: die FatFS Library nicht modifizieren, aber ein 
(einfaches) Multithreading verwenden und in der disk_read/disk_write 
Funktion den DMA-Transfer starten, den "Thread anhalten" (rausspringen), 
und dadurch die CPU für die Prozess-Steuer-Funktion freimachen. Wenn der 
Transfer fertig ist zurückspringen und somit die FatFS Funktion 
fortsetzen. Das hat den Vorteil die FatFS Library nicht anfassen zu 
müssen, und dass das mit allen Funktionen funktioniert und man so 
beliebige Abläufe auf der Karte unterbrechbar ausführen kann. Was haltet 
ihr davon?

von Grundschüler (Gast)


Lesenswert?

Programmierer schrieb:
>> Für Echtzeitanwendungen wurden die nicht konstruiert.
> Welches Speichermedium ist das denn? SSD und Bänder?

Die Sd-Karte wurde schon für Echtzeitanwendungen konstruiert, nur nicht 
mit dem SPI-Modus. SDIO ist mit 4parallelen Datenleitungen wesentlich 
schneller.

Der Sinn des ganzen DMA-Aufwandes für einen Cortex-M3 stellt sich dann 
in Frage, wenn ein Cortex-M4 die Hardware für SDIO preiswert 
bereitstellt. Bei 30€ für ein komplettes STM32F429-board lohnen sich 
Entwicklungen für einen M3 eigentlich nicht mehr, wenn das bestenfalls 
erzielbare Ergebnis in Bezug auf die Datenrate bei weitem nicht die 
Möglichkeiten eines M4 erreichen kann.

von dummy (Gast)


Lesenswert?

>Die Sd-Karte wurde schon für Echtzeitanwendungen konstruiert, nur nicht
>mit dem SPI-Modus. SDIO ist mit 4parallelen Datenleitungen wesentlich
>schneller.

Das WearLevelling interessiert es einen Scheissdreck
von welcher Schnittstelle die Daten kommen. Das haut
einfach rein.

von Programmierer (Gast)


Lesenswert?

Grundschüler schrieb:
> SDIO ist mit 4parallelen Datenleitungen wesentlich schneller.
Die Geschwindigkeit ist mit 1MByte/ s ziemlich harmlos. Es geht um die 
Latenz beim Bank switching und so.

Grundschüler schrieb:
> Der Sinn des ganzen DMA-Aufwandes für einen Cortex-M3
Wer redet von M3? Es geht um einen STM32F373, Cortex-M4F, der hat kein 
SDIO. Den brauchen wir wegen dem SDADC. SDADC & SDIO in einem STM32 
gibt's nicht. Und ein zweites Board mit STM32F4 daneben passt nicht ins 
Gehäuse, außerdem ist die Platine mit F3 und Peripherie schon fertig 
entwickelt.

dummy schrieb:
> Das haut
> einfach rein.
Was macht das denn da solange?

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.