Hallo,
ein TFT hat SDCard-SPI,XPT2046 und SPIFlash alle auf die gleichen
SPI-Leitungen gelegt. Prinzipiell kann man sich auch noch einen RFM12
vorstellen, der da dranhängt. Es wird kein DMA genutzt.
SPIFlash kann mit 80MHz+ laufen, der XPT (10MHz glaube ich) wird
langsamer und für die ADC-Wandlung noch langsamer getaktet und die
SD-Karten laufen mit 400kHz/20MHz. Ein RFM12 mit 2.5MHz.
Derzeit mache ich es so, daß ich in allen Subs, die auf SPI zugreifen,
jeweils die Geschwindigkeit (bzw. das zugehörige Register) beim Eintritt
speichere, auf die jeweils angemessene Geschwindigkeit umschalte, und
bei Verlassen wieder den Wert zurückschreibe, der beim Eintritt gegeben
war. Kostet halt etwas Zeit.
Es stört mich nicht, es läuft gut, aber die Frage nach der
Geschwindigkeit könnte bei anderen ja auch aufgetaucht sein.
Kann man das besser machen?
Grüße Sauer
Sauer schrieb:> Derzeit mache ich es so, daß ich in allen Subs, die auf SPI zugreifen,> jeweils die Geschwindigkeit (bzw. das zugehörige Register) beim Eintritt> speichere, auf die jeweils angemessene Geschwindigkeit umschalte, und> bei Verlassen wieder den Wert zurückschreibe
Das Setzen beim Eintritt reicht völlig. Der Rest ist überflüssig.
mitlesa schrieb:> Und das Setzen nur dann wirklich ausführen wenn neue> Speed ungleich der alten ist.
Da rattert aber die Bartwickelmaschine im Keller.
Peter D. schrieb:> Da rattert aber die Bartwickelmaschine im Keller.
In deinem Keller mag das schon so sein, bei den Schilderungen
des TO schaut das aber anders aus.
mitlesa schrieb:> Peter D. schrieb:>> Das Setzen beim Eintritt reicht völlig.>> Und das Setzen nur dann wirklich ausführen wenn neue> Speed ungleich der alten ist.
Das muß man ausprobieren, es kann sehr gut sein daß man mit der Prüfung
mehr Zeit vertrödelt als man einsparen könnte.
Sauer schrieb:> Derzeit mache ich es so, daß ...
Kann es bei dir vorkommen, dass laufende SPI-Kommunikationen/Tansfers
unterbrochen werden? Nur dann würde es Sinn machen, einen "aktuellen"
Wert zu speichern und nach Gebruach des SPI-Interface wieder
herzustellen.
Weil solche Unterbrechungen aber überaus unüblich sind und garantiert
lustige Nebeneffekte mit sich bringen können. Hat jede Subroutine das
SPI-Interface für sich, muss es pssend für sich einrichten und kann
hinterher das Aufräumen einfach sein lassen. Weiß ja eh' keiner, wer als
Nächster den SPI verwenden will.
> jeweils die Geschwindigkeit (bzw. das zugehörige Register) beim Eintritt> speichere
Da hast du aber Glück, dass alle den selben SPI-Modus verwenden...
NichtWichtig schrieb:> Wie benehmen sich Chips die an den Inputs überfordert (Takt zu hoch)> werden?
Solange sie per inaktivem SS# deselektiert sind juckt die das nichts.
Wühlhase schrieb:> Das muß man ausprobieren, es kann sehr gut sein daß man mit der Prüfung> mehr Zeit vertrödelt als man einsparen könnte.
Ja, kommt auf den Controller an. Ein aktuell betroffener wurde
nicht genannt.
Peter D. schrieb:> Das Setzen beim Eintritt reicht völlig. Der Rest ist überflüssig.
Hm. Vielleicht muß ich dann den Programmierstil ändern (s.u.). Aber
genau darauf zielt auch die Eingangsfrage ab.
Lothar M. schrieb:> Sauer schrieb:>> Derzeit mache ich es so, daß ...> Kann es bei dir vorkommen, dass laufende SPI-Kommunikationen/Tansfers> unterbrochen werden? Nur dann würde es Sinn machen, einen "aktuellen"> Wert zu speichern und nach Gebruach des SPI-Interface wieder> herzustellen.
Ja, ich glaube, das kann passieren.
Aber genau weiß ich das nicht - tatsächlich muß ich nochmal genauer
drüber nachdenken. Wenn ein RFM dranhängt, kann der natürlich was
empfangen, interruptet, holt sich im Interrupt das Statusword mit der
Interruptquelle und stellt damit auf das langsames SPI um. Dann setzt
er ein Flag und verläßt den Interrupt.
Wenn da gerade von SPIFlash ein Block gelesen wird, wenn der Interrupt
kommt, kehrt er zurück in diese Flash-Routine - dann aber halt mit
langsamerer SPI-Geschwindigkeit.
Da wäre das zurückschreiben am Ende des Interrupts (bzw. in der
SPI-Leseroutine) schon sinnvoll. Oder könnte ich auch nur ein Flag
setzen und dann auch das Statusregister erst in der mainloop lesen, aber
da war irgendwas Zeitkritisches beim RFM mit dem kleinen FiFo.
> Da hast du aber Glück, dass alle den selben SPI-Modus verwenden...
Ist so, tatsächlich.
mitlesa schrieb:> Nein, der XPT2046 nur 2 MHz.
Stimmt, hab nachgeschaut. Im Treiber läuft er auf ~650kHz beim Wandeln
und auf 2MHz beim rausschieben.
Sauer schrieb:> Wenn da gerade von SPIFlash ein Block gelesen wird, wenn der Interrupt> kommt, kehrt er zurück in diese Flash-Routine - dann aber halt mit> langsamerer SPI-Geschwindigkeit.
Davon würde ich abraten, Instanzen von SPI im Main und im Interrupt
laufen zu lassen. Das geht beliebig in die Hose.
Das SPI ist nicht reentrant, wie ja UART oder I2C auch. Mehrere
Instanzen muß man daher gegeneinander verriegeln, z.B. mittels fopen,
fclose.
Sauer schrieb:>> Kann es bei dir vorkommen, dass laufende SPI-Kommunikationen/Tansfers>> unterbrochen werden? Nur dann würde es Sinn machen, einen "aktuellen">> Wert zu speichern und nach Gebruach des SPI-Interface wieder>> herzustellen.> Ja, ich glaube, das kann passieren.
Das sollte aber nicht passieren, denn SPI ist ohne ERHEBLICHE Klimmzüge
NICHT doppelt nutzbar, sprich NICHT reentrant! Es muss immer erst ein
SPI-Zugriff beendet werden, eher ein neuer erfolgen kann, egal wer das
macht.
> Aber genau weiß ich das nicht - tatsächlich muß ich nochmal genauer> drüber nachdenken. Wenn ein RFM dranhängt, kann der natürlich was> empfangen, interruptet,
AUA! Es UNTERBRICHT!
> holt sich im Interrupt das Statusword mit der> Interruptquelle und stellt damit auf das langsames SPI um.
Und was macht dein toller Interupt, wenn gerade eine SPI-Übertragung
läuft?
> Dann setzt> er ein Flag und verläßt den Interrupt.> Wenn da gerade von SPIFlash ein Block gelesen wird, wenn der Interrupt> kommt, kehrt er zurück in diese Flash-Routine - dann aber halt mit> langsamerer SPI-Geschwindigkeit.
Nö, das geht so nicht, denn dein Flash ist ja gerade aktiviert worden,
CS ist LOW und du bist mitten in der Befehlssequenz.
> Da wäre das zurückschreiben am Ende des Interrupts (bzw. in der> SPI-Leseroutine) schon sinnvoll.
Nö, es geht PRINZIPIELL nicht so!
> Oder könnte ich auch nur ein Flag> setzen und dann auch das Statusregister erst in der mainloop lesen,
Das wäre eine Möglichkeit.
> aber> da war irgendwas Zeitkritisches beim RFM mit dem kleinen FiFo.
Mag sein, aber deine oben beschriebene Lösung funktioniert so NICHT!
Eine mögliche Lösung wäre, per Flag ein Zeitfenster freizugeben, indem
garantiert KEINE Interrupt vom RFM12 Modul ausgelöst werden (weil sie
gesperrt sind). Das kann man u.a. dadurch erreichen, indem man VOR einem
SPI-Zugriff auf andere Module erstmal das RFM12 auf kritischen
FIFO-Stand prüft. Dazu braucht es nicht mal einen Interrupt. Danach hat
man x ms Zeit, andere Sachen mit dem SPI zu machen.
Falk B. schrieb:> Nö, das geht so nicht, denn dein Flash ist ja gerade aktiviert worden,> CS ist LOW und du bist mitten in der Befehlssequenz.
Ok, DAS ist tatsächlich wahr. Dann knallt es sogar hardwaremässig an den
MISOs, die dann beide nicht tristaten. Böse.
> Mag sein, aber deine oben beschriebene Lösung funktioniert so NICHT!
Sagen wir so: Das Zeug läuft seit Jahren so, aber ich hatte mit diesen
TFTs Ärger beim Programmieren bis sie gut liefen (ein RFM12 hing da
nicht dran).
Tatsächlich habe ich nicht an die CS-Leitung gedacht, da war Dein
Beispiel sehr einleuchtend.
Peter D. schrieb:> Wenn es zeitkritsch ist, benutzt man besser mehrere SPI. Z.B. der> ATmega2560 kann bis zu 5 SPI-Master bereitstellen.
Das war auch mein neuer Ansatz und deshalb bin ich auf STM32 mit 6 SPIs
umgestiegen, von denen ich bisher maximal 5 benutzt habe. Die 'alten'
F407 benutze ich dann für solche Zwecke besser nicht mehr.
Eine zeitlang hatte ich auch die Routinen gelockt mit einem busyflag,
was erst die SPI freigab, wenn eine Aktion komplett abschgeschlossen
war, aber das geht schlecht bei zeitkritischen Sachen.
Danke für euren Input. Die SD-Card und das Flash von diesen Displays
mache ich beim nächsten Mal separat an andere SPIs, der Touch darf
bleiben :-)