Forum: Mikrocontroller und Digitale Elektronik STM32: SPI-Transfer laut Datenblatt ohne Interrupts


von Sven P. (Gast)


Lesenswert?

Hallo,

beim STM32F10x heißt es im Datenblatt zum SPI für Transfers im 
Master-Modus:
> The software has to follow this procedure to transmit and receive data:
> 1. Enable the SPI by setting the SPE bit to 1.
> 2. Write the first data item to be transmitted into the SPI_DR register
>    (this clears the TXE flag).
> 3. Wait until TXE=1 and write the second data item to be transmitted.
>    Then wait until RXNE=1 and read the SPI_DR to get the first received
>    data item (this clears the RXNE bit). Repeat this operation for each
>    data item to be transmitted/received until the n–1 received data.
> 4. Wait until RXNE=1 and read the last received data.
> 5. Wait until TXE=1 and then wait until BSY=0 before disabling the SPI.

(Seite 710)

Das ganze ziehlt wohl auf das doppelte gepufferte Datenregister ab. 
Allerdings frage ich mich, ob die Beschreibung tatsächlich etwas naiv 
ist:

Man schreibt also ein Byte ("first data item") rein und das SPI beginnt 
mit der Übertragung, wodurch das Pufferregister frei wird und man schon 
ein Byte nachladen ("second data item") kann. Dann wartet man implizit 
auf das Ende der Übertragung des ersten Bytes ("RXNE"), durch das ja 
gleichzeitig auch ein Byte empfangen wurde, welches man dann lesen soll 
("first received data item"), um direkt im Anschluss wieder ein Byte zum 
Versand nachzuladen.

Wenn man allerdings nun ein Byte nicht rechtzeitig liest, etwa weil ein 
Interrupt dazwischenkommt, dann geht dieses doch schlimmstenfalls 
verloren, oder? Denn im Puffer befindet sich ja wegen der 
verschachtelten Prozedur laut Datenblatt schon das nächste zu 
versendende Byte. Und wenn das fertig übertragen wurde, würde das 
dadurch gleichzeitig empfangene Byte wieder in den Puffer geschrieben. 
Damit wäre ein Byte überschrieben und verloren.

Übersehe ich da etwas?
Ich meine, es ist ja nicht so, dass diese Problematik nicht leicht 
durchschaubar wäre. Aber ich bin es eigentlich von Datenblättern anderer 
Mikrocontrollerfamilien gewohnt, dass solche Sachen beschrieben werden. 
Und im Datenblatt des STM32 bin ich darum etwas hin- und hergerissen:
(a) Das Datenblatt ist schon richtig so. Das heißt, ich übersehe 
irgendwas.
(b) Das Datenblatt ist naiv und geht aufgrund der Komplexität nicht 
auf jeden "Randfall" extra ein.
(c) Das Datenblatt ist Mist.

Fairerweise würde ich (a) annehmen wollen, aufgrund meiner Erfahrung 
gehe ich aber von (c) aus.


Danke & Grüße,
K

von Doctor Snuggles (Gast)


Lesenswert?

Sven P. schrieb:
> Übersehe ich da etwas?

Ja.
Zum einen gibt es ein Overflow-Flag, was anzeigt, dass Du etwas verpasst 
hast.
Zum anderen lässt sich das Verpassen auf verschiedene Art und Weise 
verhindern.
Zum einen kannst Du einen Interrupt mit ausreichender Priorität 
aktivieren, in dem Du sofort empfangene Daten abholst.
Zum anderen kannst Du DMA nutzen, dann läuft das im Hintergrund ab.

Das steht, wie Du es gewohnt bist, im Reference Manual. Dazu noch in 
thematischen Datenblättern wie z.B. für DMA richtig ausführlich.
Einfach lesen!

von Sven P. (Gast)


Lesenswert?

Doctor Snuggles schrieb:
> Einfach lesen!

Mir sind die 100 anderen Optionen ja durchaus bewusst, mit denen man das 
Problem umschiffen kann. Das ist aber nicht das, was ich hoffe, zu 
übersehen.

Ich hoff(t)e, einen Mechanismus im UART zu übersehen, der bei exakter 
Befolgung der Beschreibung im Datenblatt dafür sorgt, dass kein Byte 
verlorengeht.

Oder anders gesagt, ich kann die Beschreibung im Datenblatt so nicht 
nachvollziehen: Warum wird dort ein "kompliziertes" Verschachteln der 
Sende-/Empfangszyklen beschrieben?
- Es ist, so wie es dort steht, nicht sicher.
- Man könnte es problemlos so umsortieren, dass es sicher ist (d.h. 
nicht verschachteln, sondern immer auf das einlaufende Byte warten, 
bevor nachgeladen wird). Klar, ist dann langsamer.
- Es gibt DMA.
- Es gibt Interrupts mit Prioritäten.

Was also soll diese Vorschrift?

Einen Sinn würde die Vorschrift zum Beispiel ergeben, wenn der UART das 
erste empfangene Byte ins Pufferregister schiebt und das zweite dann im 
SPI-Schieberegister behält. Wenn nun ein drittes Byte reinkommt, ists 
natürlich wieder vorbei. Aber solange man ja nur zwei Bytes gesendet hat 
(das erste plus das nachgeladene), können auch nur zwei Bytes 
reinkommen. Dann könnte man in aller Ruhe das Puferregister lesen, 
wodurch das Byte aus dem Schieberegister ins Pufferregister nachrückt 
und so weiter.

Ich kann aber nirgends ersehen, ob das SPI so gebaut ist. Und ehrlich 
gesagt bezweifle ich es auch.

Die Vorschrift ist also strenggenommen Blödsinn oder wohlwollende 
Statistik a.k.a. schnell genug sein. Hat doch im Datenblatt nix verloren 
sowas.

von Sven P. (Gast)


Lesenswert?

Schade, auch bei ST finde ich dazu kein verwertbares Feedback.

Irgendwie passt das wieder einmal mehr zum desolaten Zustand des 
ARM-Ökosystems :-(

von STM Apprentice (Gast)


Lesenswert?

Sven P. schrieb:
> Irgendwie passt das wieder einmal mehr zum desolaten Zustand des
> ARM-Ökosystems :-(

Seltsam ... die ganze Welt macht SPI mit ARM-Prozessoren und
jammert nicht rum, und bei dir ist die Kacke am dampfen.

Was will uns das sagen?

von StinkyWinky (Gast)


Lesenswert?

Sven P. schrieb:
> Wenn man allerdings nun ein Byte nicht rechtzeitig liest, etwa weil
> ein Interrupt dazwischenkommt, dann geht dieses doch schlimmstenfalls
> verloren, oder?

Nur, wenn du in deinem Interrupt mehr Zeit vertrödelst, als die 
Übertragung eines Bytes benötigt.

von UweBonnes (Gast)


Lesenswert?

Warum muss es den der STM32F10x sein? Den gibt gibt es schin 10 Jahre, 
und ST hat einiges an der Peripherie verbessert.

von PittyJ (Gast)


Lesenswert?

Ist das nicht egal bei SPI? Da bestimmt der Master doch auch den Takt. 
Und der kann AFAIK sich während einer Übertragung ändern. Dat hat man 
doch genug Zeit, das Byte abzuholen, weil der Takt erst dann generiert 
wird, wenn man das nächste Zeichen sendet.

Oder sehe ich das falsch?

von A. B. (Gast)


Lesenswert?

Sven P. schrieb:
> Man schreibt also ein Byte ("first data item") rein und das SPI beginnt
> mit der Übertragung, wodurch das Pufferregister frei wird und man schon
> ein Byte nachladen ("second data item") kann. Dann wartet man implizit
> auf das Ende der Übertragung des ersten Bytes ("RXNE"), durch das ja
> gleichzeitig auch ein Byte empfangen wurde, welches man dann lesen soll
> ("first received data item"), um direkt im Anschluss wieder ein Byte zum
> Versand nachzuladen.

Wenn man sich die Überschrift zu Fig. 241 im RM ansieht, ist klar, warum 
das so gemacht werden soll: continuous

Schreibt man nur jeweils ein Byte ins Sende-Register und wartet auf das 
RXNE, liest das empfangene Byte und scheibt erst danach das nächste Byte 
ins Sende-Register, gibt's zwischen den einzelnen Bytes immer ein Pause, 
aber man verpasst garantiert nichts.

> Wenn man allerdings nun ein Byte nicht rechtzeitig liest, etwa weil ein
> Interrupt dazwischenkommt, dann geht dieses doch schlimmstenfalls
> verloren, oder? Denn im Puffer befindet sich ja wegen der

Klar. Wenn man es so macht wie im RM beschrieben (um eben KEINE Pausen 
zu haben), muss man natürlich immer
(a) rechtzeitig für Nachschub sorgen und
(b) rechtzeitig die empfangenen Daten abholen ...

Ansonsten bleibt ja der einfachere Weg, wo halt kein kontinuierlicher 
Transfer stattfindet.

Die Frage ist letzlich, ob die "Gegenstelle" solche Pausen verdaut oder 
sich daran verschluckt.

von Sven P. (Gast)


Lesenswert?

UweBonnes schrieb:
> Warum muss es den der STM32F10x sein? Den gibt gibt es schin 10 Jahre,
> und ST hat einiges an der Peripherie verbessert.
Naja, er ist halt gängig. Zumindest hatte ich den Eindruck, als ich mich 
vor ca. 2 Jahren damit erstmalig beschäftigt habe und nach einem 
Einstiegsmodell gesucht habe.

PittyJ schrieb:
> Oder sehe ich das falsch?
Ja, siehst du. In o.g. Beispiel aus dem Reference Manual ist das nächste 
Byte ja schon sendebereit. Das ist ja genau das Problem.

STM Apprentice schrieb:
> Seltsam ... die ganze Welt macht SPI mit ARM-Prozessoren und
> jammert nicht rum, und bei dir ist die Kacke am dampfen.
Und das macht die konkrete Peripherie samt Beschreibung im STM32F103 nun 
irgendwie "gut" oder "besser"?

Das ist ja ein triviales Problem hier. Mir sind, wie ich ja schon 
schrieb, diverse Lösungen dafür bekannt.
Aber es ist m.M.n. ziemlich repräsentativ dafür, wie dünn das RM ist. 
Irgendwie habe ich oft das Gefühl, dass Peripherie nur grob umrissen 
wird und ich vieles wirklich ausprobieren muss, wenn es um Randfälle und 
so geht.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Sven P. schrieb:
> Wenn man allerdings nun ein Byte nicht rechtzeitig liest, etwa weil ein
> Interrupt dazwischenkommt, dann geht dieses doch schlimmstenfalls
> verloren, oder? Denn im Puffer befindet sich ja wegen der
> verschachtelten Prozedur laut Datenblatt schon das nächste zu
> versendende Byte. Und wenn das fertig übertragen wurde, würde das
> dadurch gleichzeitig empfangene Byte wieder in den Puffer geschrieben.
> Damit wäre ein Byte überschrieben und verloren.

Ein Paradebeispiel von "Ich hätte gerne ein Problem".
Wenn man den SPI auf max Takt betreibt und im IRQ Fibonaccis rekursiv 
berechnet dann geht das verloren.

Der SPI im F103 kann maximal 18MBit, der CPU Kern kann bis zu 72MHz.
Also pro SPI CLK verspeist die CPU 4 Befehle.
Nun sind es aber 8Bit pro SPi Übertragung, also 32 Befehle.
Wird knapp wenn da nen IRQ mit Registerstacking reinpfuscht.

Aber Volldampf senden ohne DMA war noch nie eine gute IDee, mit 1-4MHz 
auf dem SPI sollts keine Probleme geben.
Also b)

Und wieso wird auf einmal vom UART gefaselt wenns eigentlich um den SPI 
geht?

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.