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?
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?
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).
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?
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
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
> 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.
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?
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).
>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.
@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"
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.
>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.
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.
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?
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.
>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.
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?