Forum: Mikrocontroller und Digitale Elektronik SAMC21 SPI Master DMA (Empfang)


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Adam P. (adamap)


Lesenswert?

Hallo zusammen,

ich habe hier ein SAMC21G18A und bin grad an der Implementierung vom 
SPI.
Das ASF wird verwendet.

Angeschlossen ist ein AFE4403.

Im Interruptbetrieb funktioniert alles super, auch der Empfang.
Ich takte eine write_buf heraus, dieser enthält die Registeradressen die 
ich lesen möchte und erhalte dann im read_buf, die Registerinhalte.

Nun habe ich es auf DMA umgebaut.
Das versenden vom write_buf funktioniert, Werte in Registern setzen.

Durch senden des write_buf mit den Registeradr. sehe ich auch mit dem 
LA, dass die vorher gesetzten Werte wieder herausgetaktet werden.

Grundsätzlich war meine Idee, dass ich einfach source und destination in 
der DMA Config. vertausche. Jedoch fängt er so nicht mals an zu takten.
1
dma_descriptor_get_config_defaults(&config);
2
3
config.beat_size            = DMA_BEAT_SIZE_BYTE;
4
config.dst_increment_enable = false;
5
config.block_transfer_count = length;
6
config.source_address       = (uint32_t) (&spi_master_instance.hw->SPI.DATA.reg);
7
config.destination_address  = (uint32_t) src + (uint32_t) length;

Funktioniert das "Lesen" überhaupt mit DMA?
Schliesslich muss ich erst 1 Byte Adresse heraustakten und dann die 
3Byte Registerwerte empfangen (für 1 Register).

Irgendwie fehlt mir grad die richtige Idee.

: Bearbeitet durch User
von Adam P. (adamap)


Angehängte Dateien:

Lesenswert?

OK.

Also theoretisch tut es jetzt.
Es müssen 2 DMA Kanäle erzuegt werden.
Erst den RX DMA Job starten dann den TX.

Beim RX DMA muss noch src_increment_enable = false gesetzt werden,
was ja klar ist, da er ja als source immer auf das Daten-Register 
zugriefen soll.

Jetzt ist es aber so, dass die Empfangenen Bytes im RX Buffer verschoben 
sind um 3 Byte, die hinten wiederrum fehlen.
Das versteh ich jetzt echt nicht.

von Stefan A. (king-crash)


Lesenswert?

Bekommt er aus unbekannten Gründen zu früh zu viele Trigger und liest 
aus dem SPI.DATA.reg 0?
Das könntest du ausprobieren indem du beispielsweise nur 4 Bytes sendest 
und dann abbrichst und schaust ob mehr Bytes überschrieben wurden.
Der Buffer ist im Ausgangszustand mit 0xaa initialisiert?

von Adam P. (adamap)


Lesenswert?

Stefan A. schrieb:
> Bekommt er aus unbekannten Gründen zu früh zu viele Trigger und liest
> aus dem SPI.DATA.reg 0?

Sobald ich den RX DMA aktivieren, bekomme ich schon mal die erste 0 
rein.
Evtl. die die noch im DATA reg. liegt?

Stefan A. schrieb:
> Der Buffer ist im Ausgangszustand mit 0xaa initialisiert?

Ja mein RAM wird beim Boot mit 0xAA initialisiert, bzgl. Ermittlung der 
max. Stack Nutzung.

Stefan A. schrieb:
> Das könntest du ausprobieren indem du beispielsweise nur 4 Bytes sendest
> und dann abbrichst und schaust ob mehr Bytes überschrieben wurden.

Also was ich schon mal sehen konnte, ich muss mehr takten als ich lesen 
möchte. Und zwar um diese 3 Byte.

Wo diese herkommen ist noch offen.
Ich dachte erst, das wären evtl. die 3 Byte = 24bit, die einer 
Registergröße entsprechen. Macht aber irgendwie kein Sinn.

1 Byte würde ich verstehen. weil ich ja erst die Adr. übermitteln muss 
bevor ich den Wert erhalte. Dieses eine Byte würde auf MISO 0 sein.

Muss ich mir morgen nochmal genauer anschauen.

Edit:
Also der Cortex-M0+ ist echt nice und easy aber schon allein der DMA 
Init. ist echt merkwürdig.
Da musst du als Start-Adr. nicht wirklich die Adr. vom Buffer angeben, 
sonder:
1
// + die Länge
2
config.destination_address  = (uint32_t) dst + (uint32_t) length;

da er dann aufgrund der zusätzlich Längenangabe sich das selbst 
zurückrechnet. Naja.
Kenne das so nicht, PDC macht es z.B. so wie man es erwartet, ab hier 
und soviel.

: Bearbeitet durch User
von Stefan A. (king-crash)


Lesenswert?

> Sobald ich den RX DMA aktivieren, bekomme ich schon mal die erste 0
> rein.
> Evtl. die die noch im DATA reg. liegt?

Das SPI Peripheral ist zu dem Zeitpunkt schon initialisiert?
Falls SERCOM.SPI.INTFLAG.RXC gesetzt ist und schon Daten vorhanden sind 
musst du erst einen Dummy read auf das DATA Register machen.

von Adam P. (adamap)


Lesenswert?

Stefan A. schrieb:
> Das SPI Peripheral ist zu dem Zeitpunkt schon initialisiert?

Ja das Init. vom SPI ist da schon fertig.

Stefan A. schrieb:
> Falls SERCOM.SPI.INTFLAG.RXC gesetzt ist und schon Daten vorhanden sind
> musst du erst einen Dummy read auf das DATA Register machen.

OK, das würde 1 Byte erklären.
Wo die anderen 2 herkommen muss ich heut mal herausfinden.

von Adam P. (adamap)


Lesenswert?

Stefan A. schrieb:
> musst du erst einen Dummy read auf das DATA Register machen.

Also ein Dummy Read nützt nichts.
Das 0x00 Byte kommt trotzdem.

Fazit:
1x 0x00 beim RX DMA Job start
1x 0x00 beim TX DMA Job start
=> 2 Byte zuviel.

Wenn ich nun 20 Byte lesen möchte, muss ich den RX Job auf 22 Byte 
einstellen und den TX auf 21 Byte (1 Byte bedingt durch die Shift 
Register).

So passt es nun.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.