Forum: Mikrocontroller und Digitale Elektronik STM32 SPI1 und DMA (für Rx und Tx)


von el84 (Gast)


Lesenswert?

Ich beschäftige mich jetzt schon eine gute Weile mit SPI/DMA auf dem 
STM32 und komme einfach nicht weiter. Die Initialisierung erledige ich 
wie in diesem Beitrag:

http://www.st.com/mcu/forums-cat-8238-23.html

allergings läuft Frameworkbedingt die SPI-Initialisierung vor der 
DMA-Initialisierung ab, sprich: SPI wird auch vor der 
DMA-Initialisierung auf enabled gesetzt. (Ist das problematisch?) Mein 
momentaner Code crasht immer ein paar Befehle nachdem ich DMA auf 
enabled gesetzt habe.

Die Initialisierten Werte finde ich auch so im Speicher wieder, soweit 
sollte das korrekt sein

(Abweichende Werte zum Link:

DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32) pReadBuffer;
DMA_InitStructure.DMA_BufferSize = wByteCount;

wobei pReadBuffer bzw. pWriteBuffer ein (Byte-)Pointer auf einen vorher 
schon existierenden Puffer ist und wByteCount dessen Anzahl an Bytes 
enthält).

Es funktioniert weder mit noch ohne initialisierte Interrupts (und 
DMA_IT_TC, ENABLE).

Leider habe ich keine Application Note zu SPI/DMA gefunden. In der 
AN2548 wird zwar in der Beschreibung erwähnt, dass für SPI1_RX DMA1 Ch2 
verwendet wird, im Code wurde das aber offensichtlich vergessen und nur 
der ADC mit DMA implementiert.

Hat eventuell jemand einen funktionierenden Codeausschnitt oder kann mir 
Tipps zur Fehlersuche geben? Ich kann auch gerne weiteren Code posten, 
allerdings ist meiner weitestgehend gleich dem im obigen Link.

Ich bin für jeden Tipp dankbar, da mich das Problem jetzt schon ein paar 
Tage aufhält.

Vielen Dank!

von (prx) A. K. (prx)


Angehängte Dateien:

Lesenswert?

Mein Testcode für SPI via DMA. Compilierbar ist er so nicht, weil etwas 
eigener Kram für Bitbanding und GPIO Konfiguration fehlt, ebenso ein 
paar Bezeichner für die I/O, aber vielleicht hilft es für's Prinzip.

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

el84 schrieb:
>...
> Hat eventuell jemand einen funktionierenden Codeausschnitt...
>...

http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/arm_memcards/index.html#stm32_memcard
--> [Download]
--> sd_spi_stm32.c

von el84 (Gast)


Angehängte Dateien:

Lesenswert?

Vielen Dank für die Codebeispiele. Ich habe inzwischen den Code im 
Anhang daraus gebaut. Dieser ersetzt die vorher vorhandene 
Sende/Empfang-Funktion für SPI ohne DMA (das heißt: auch die 
SPI-Initialisierung steht wo anders). Momentan verwende ich nur SPI1. 
Ich sende erst den gesamten Tx-Puffer mit DMA, dann lese ich den 
gesamten Rx-Puffer mit DMA. Kann man das so machen oder habe ich da 
einen fatalen Denkfehler?

Leider bringt es auch noch nicht das erwartete Ergebnis, beim Lesen 
steht der Puffer voll mit FF. Außerdem crasht mein Projekt nach wie vor, 
aber da vermute ich Timing-Probleme. Im Single-Step-Betrieb per JTAG 
läuft es wenigstens problemlos durch.

Es wäre schön, wenn mir jemand einen Hinweis geben könnte, dass 
wenigstens mein angehängter DMA-Code läuft. Der andere Fehler ist 
vermutlich Projektbedingt und erstmal zweitrangig.

von embedded-os (Gast)


Lesenswert?

schau Dir mal meinen Demo-Code zu SD-Karten unter SPI auf verschiedenen 
MCUs an (auch STM32).

http://www.embedded-os.de/index.html?pcfat_port.htm

von el84 (Gast)


Lesenswert?

So, danke für die Antworten. Wollte mich nur mal zurückmelden und sagen, 
dass es inzwischen funktioniert. Da in meiner Routine wie gesagt 
gleichzeitig gelesen und geschrieben wird, konnte ich die 
Initialisierung noch kompakter gestalten:

    /* DMA configuration SPIx RX ------------------------*/
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pReadBuffer;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_Init(DMA_Channel_SPIx_RX, &DMA_InitStructure);

    /* DMA configuration SPIx TX ------------------------*/
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pWriteBuffer;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_Init(DMA_Channel_SPIx_TX, &DMA_InitStructure);

Danach werden die DMA-Kanäle enabled, SPI TX/RX request enabled, 
gewartet, bis die Übertragung abgeschlossen ist, die DMA-Kanäle wieder 
disabled und  SPI TX/RX request disabled. Wie im obigen Code auch. Das 
wars.

Mein Problem war ein ganz anderes und deswegen schreibe ich das jetzt 
hier auch nochmal so deutlich, da sicher etliche noch das selbe Problem 
haben werden:

!!!DER PUFFER ZUM LESEN UND SCHREIBEN _MUSS_ IM INTERNEN SRAM 
LIEGEN!!!

In meinem Fall also SPITxBuffer und SPIRxBuffer. Es funktioniert nicht, 
wenn er im externen RAM allokiert ist. Deswegen crashte mein Projekt 
regelmäßig, deswegen funktionierte nichts. Ich hoffe, dass das hiermit 
ausreichend für die Nachwelt festgehalten ist. ;)

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.