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
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!
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.
Schade, auch bei ST finde ich dazu kein verwertbares Feedback. Irgendwie passt das wieder einmal mehr zum desolaten Zustand des ARM-Ökosystems :-(
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?
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.
Warum muss es den der STM32F10x sein? Den gibt gibt es schin 10 Jahre, und ST hat einiges an der Peripherie verbessert.
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?
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.