Hi,
beschäftige mich gerade mit dem STM32F4 (STM32F405RG).
Ich möchte per DMA Daten per SPI ausgeben. Ich möchte zunächst ohne HAL
/ CubeMX arbeiten, es ist aufgrund der Einfachheit auch eigentlich nicht
notwendig (der F405 ist nur aufgrund des ausreichenden RAMs notwendig,
ansonsten wäre die Applikation auch mit einem F030 möglich gewesen).
Hier ist der Schnipsel:
Der SPI funktioniert soweit wenn ich die Daten direkt in das DR
schreibe.
Aber der DMA deaktiviert sich nach dem aktivieren sofort wieder und
setzt im LISR einen Transfer Error (TEIF) und Fifo Error (FEIF) für
Stream 3.
Dabei ist der DMA FIFO garnicht aktiviert (DMDIS im S3FCR ist 0).
Irgendeine Idee? Ja ich weiß, CubeMX und HAL (_LL) existieren, aber
eigentlich ist das völlig überzogen hier...
Was ich da am Code vermisse ist das löschen der Statusflags vorm DMA
einschalten. Das muss laut DB geschene bveor der DMA kanal akriviert
wird.
Weiterhin erst den DMA Kanal initialisieren und danach das DMA Bit in
der Periph setzen.
Den HAL nutz ich auch nicht ;)
Egal, ob man HAL benutzt oder nicht, könnte man ihn wenigstens als gute
oder auch schlechte Vorlage benutzen und schauen, wie's da gemacht wird.
Es hindert einen ja nix, es selbst besser zu machen.
Jörg S. schrieb:> Egal, ob man HAL benutzt oder nicht, könnte man ihn wenigstens als> gute> oder auch schlechte Vorlage benutzen und schauen, wie's da gemacht wird.>> Es hindert einen ja nix, es selbst besser zu machen.
So ein Blödsinn.
Um zu schauen, wie es gemacht wird, ist das Reference Manual da. Da
steht alles Nötige drin.
Markus M. schrieb:> Hier ist der Schnipsel:
Lass zum besseren Lesen die _Msk Defines weg. In der Header-Datei sind
die richtigen vorhanden.
Wozu setzt Du das BIDIOE Bit?
Mw E. schrieb:> Weiterhin erst den DMA Kanal initialisieren und danach das DMA Bit in> der Periph setzen.
Genauso ist es.
> Den HAL nutz ich auch nicht ;)
Gut so. Um die paar Bits zu setzen, muss man nicht Tausende von
Taktzyklen sinnlos verbraten.
Ist wie die Kinder mit dem 3Tonnen-SUV zum Kindergarten um die Ecke
bringen.
Machen auch immer mehr, ist dadurch aber nicht intelligenter.
Hi,
okay, das mit der Reihenfolge werde ich mal ausprobieren.
Ich hatte sogar anfangs probiert, die HAL zu verwenden. Aber es gibt
wohl ein Versions-Mismatch zwischen den Code/Includes die die IDE
mitbringt und der Verison der StdPeriphLib zum Download bei ST,
jedenfalls liess sich die HAL nicht ohne obskure Fehler übersetzen. Ohne
HAL hatte ich dann wenigstens schonmal den SPI nach kurzer Zeit am
Funktionieren.
Der Blick in die HAL (StdPeriphLib und CubeMX/HAL_LL) hat wieder
gezeigt, dass es NULL Abstraktion ist, sondern nur ein Umherschieben von
Bits / Umwandlung von enum-Werten.
Das BIDIOE ist obsolet, stimmt. Hatte vorher noch BIDIMODE gesetzt.
Das mit _Msk / _Pos ist Geschmackssache. Die Definitionen ohne _Msk habe
ich sonst auch immer benutzt, allerdings finde ich es sprechender mit
_Msk und _Pos.
Markus M. schrieb:> Das mit _Msk / _Pos ist Geschmackssache.
Nein.
Maske versteht "man" landläufig / weitläufig anders.
Du benutzt "Maske" zum Setzen von Bits. Dabei ist gerade
das Programmieren mit einer Maske (auf professioneller Seite)
dazu gedacht Gruppen von Bits in einem Wort zu löschen.
Man schaue sich nur diverse Header-Dateien von Atmel oder
ST an.
Jan K. schrieb:> Magst du mal dazu ein Beispiel zeigen?
Das ist völlig wurscht.
Fakt ist, daß man zum tatsächlichen Verstehen des geposteten Codes die
Definitionen der verwendeten Bezeichner benötigt.
Oftmals rennen die Leute in die Falle, indem sie so einen Bezeichner
versehentlich für ein Register verwenden, für das er nicht gedacht ist.
Aber selbst wenn Bezeichner und Register zueinander passen, ist immer
noch die Frage, WIE der Bezeichner definiert ist. Wir hatten vor
kurzem hier das Problem bei einer Diskussion über "Üblichkeiten" zw.
Atmel und Cortex:
#define karlheinz (1<<9)
oder
#define karlheinz 9
was bei der Verwendung natürlich erhebliche Unterschiede macht, wobei
man beim schieren Betrachten der Verwendungsstelle einen Bug gar nicht
bemerken kann.
W.S.
Interessant, dass sich zum Thema Registerbit defines genau jetzt
derjenige meldet, der eh Magic Numbers in die Register schiebt.
Siehe hier:
Beitrag "Re: STM32F3: IRQ-Prioritäten"
Aber W.S. sagt ja, dass man eben doch genau wissen muss, wie die
Bezeichner definiert sind, also als Maske (1<<x) oder als Bitnummer x.
Ist das die Argumentation für die Magic Numbers?
Ich denke, wenn die Bezeichner vernünftig definiert sind, sollte es klar
sein.
Würde mich dennoch interessieren, was "Grummel Grummel (Gast)" oben
meint und warum man keine Masken zum Bits setzen verwenden soll.
Habe inzwischen wohl die Ursache für mein Problem, den DMA Transfer-bzw.
Bus-Error gefunden:
"CCM (core coupled memory) mapped at address 0x1000 0000 and accessible
only by the CPU through the D-bus."
In der Tat liegen meine (DMA-) Daten in diesem Bereich. Ich muss mal
schauen wie ich eine getrennte Section anlege, damit die Daten im
"allgemeinen" SRAM liegen.
Den Fehler konnten wir jetzt nicht sehen, weil das nicht im Code steht.
Aber eigentlich sollt ers nicht sofort ins CCM packen, weil der eher
klein ist.
Damit ers macht muss man schon am Linkerscript spielen.
Womit baust du dein Programm und zeig mal dein LInkerscript.
Man sieht also, dass die section für das 128k große RAM2 dann ".bss2"
sein muss. Mir war diese Segmentierung nicht präsent, programmiere zum
ersten mal einen Controller > F0.
Mit einem entsprechenden "attribute" funktioniert nun auch der DMA:
Und der Hinweis dass man den DMA in der Peripherie erst aktivieren darf
nachdem man den Stream konfguriert hat war auch goldrichtig.
Habe ich auch in der Application Note AN4031 dann gefunden. Aber auch
dort wird das mit dem CCM RAM nicht erwähnt...
Also DANKE, DMA funktioniert nun.
Warum auch immer Segger .data / .bss in das CCM gepackt hat und es
auchnoch RAM heißt.
Da dein Array laut obigem Code initialisiert ist, sollte es aber eher
nach .data2 .
Weil der 405 hat drei RAMs.
-den Data CCM direkt am ARM Kern D-Bus
-SRAM1
-SRAM2
Die haben SRAM 1 und 2 zusammengepackt und nennen es RAM2.
Der DCCM ist für den Stack und für Datenstrukturen auf die shcnell
zueggriffen werden muss.
SRAM1 ist der "normale" RAM.
SRAM2 nutzt man dann speziell für den DMA.
Durch die Busmatrix kann der ARM Kern auf SRAM1 zugreifen und einer der
DMA auf SRAM2 und das gleichzeitig ohne dass sich beide in die Quere
kommen.
Was mit dem Segger Linkereinstellungen nicht mehr geht.
Danke für die Info.
Ich werde mal versuchen es durch Modifikation der .xml Files
entsprechend zu ändern / trennen.
Das SRAM2 ist ja relativ klein (16kB), wäre als DMA-Bereich genau
richtig, da die Daten vorher sowieso noch aufbereitet und somit kopiert
werden müssen.
Das mit dem festen initialisierten Array war nur ein Test.