Hi zusammen,
ich habe eine Frage zum Thema Interrupts:
Ich benutze einen SAMD21J18A und ATMEL START/ATMEL Studio (AFS4)
Umgebung, um ihn zu programmieren.
Jetzt habe ich folgendes Problem:
Ich habe einen SPI Bus, an dem verschiedene Sensoren dran hängen und
einen Eingangs-Pin, der bei fallender Flanke eine Interruptfunktion
auslösen soll, die mir einen bestimmten Sensor, über die SPI-Verbindung,
auslesen soll.
Wenn jetzt aber der Fall auftritt, dass gerade ein Sensor, der an
besagtem SPI Bus hängt, ausgelesen wird und dabei gleichzeitig die
Interruptfunktion aufgerufen wird, um einen anderen Sensor in diesem
Bussystem auszulesen, führt das zu Kuddelmuddel.
Die Interruptfunktion soll eine höhere Priorität haben, als das auslesen
des anderen Sensors. Sprich: Wenn gerade ein Sensor ausgelesen wird und
die Interruptfunktion ausgelöst wird, soll das auslesen des anderen
Sensors abgebrochen werden, die Interruptfunktion ausgeführt und dann
der Sensor erneut ausgelesen werden. Im Programmablauf müssten also nach
dem Interrupt ein paar (bereits ausgeführte) Schritte erneut ausgeführt
werden.
Daraus ergibt sich meine Frage: Gibt es in AFS4 einen Ansatz zu sagen:
"Wenn zwischen diesem (Startpunkt) und diesem Punk (Endpunkt) im Code
ein Interrupt getriggert wird, dann springe nach ausführen des
Interrupts zum Startpunkt(!) zurück."
Danke schonmal für konstruktive Vorschläge!
Hanna
Hanna schrieb:> Die Interruptfunktion soll eine höhere Priorität haben, als das auslesen> des anderen Sensors.
Das halte ich für eine verfehlte Architektur.
Mach die einzelnen Auslesefunktionen schnell / kurz, aber nicht
unterbrechbar. Sensoren, die eine lange Zeit brauchen, haben oft eine
Funktion, mit der sie zwischenzeitlich (während ihrer eigentlichen
Messphase) den Bus freigeben können. Sowas sollte man nutzen.
Ansonsten müsstest du Nägel mit Köpfen machen und uns sagen, welche Art
Sensor das ist. Dann kann man dich besser beraten.
Stefan ⛄ F. schrieb:> Macht die externe> Hardware das denn einfach so mit?
Da bin ich mir noch nicht sicher :D
Jörg W. schrieb:> Sensoren, die eine lange Zeit brauchen, haben oft eine> Funktion, mit der sie zwischenzeitlich (während ihrer eigentlichen> Messphase) den Bus freigeben können.
Das könnte eine Alternative sein. Da muss ich dann wohl nochmal
Datenblätter durchstöbern.
Hanna schrieb:>> Macht die externe>> Hardware das denn einfach so mit?> Da bin ich mir noch nicht sicher :D
Dann prüfe das erst mal, denn was du da vor hast ist schon seltsam.
Hanna schrieb:> Wenn jetzt aber der Fall auftritt, dass gerade ein Sensor, der an> besagtem SPI Bus hängt, ausgelesen wird und dabei gleichzeitig die> Interruptfunktion aufgerufen wird, um einen anderen Sensor in diesem> Bussystem auszulesen, führt das zu Kuddelmuddel.
In der Tat.
> Die Interruptfunktion soll eine höhere Priorität haben, als das auslesen> des anderen Sensors. Sprich: Wenn gerade ein Sensor ausgelesen wird und> die Interruptfunktion ausgelöst wird, soll das auslesen des anderen> Sensors abgebrochen werden, die Interruptfunktion ausgeführt und dann> der Sensor erneut ausgelesen werden. Im Programmablauf müssten also nach> dem Interrupt ein paar (bereits ausgeführte) Schritte erneut ausgeführt> werden.
Das geht schief.
> Daraus ergibt sich meine Frage: Gibt es in AFS4 einen Ansatz zu sagen:> "Wenn zwischen diesem (Startpunkt) und diesem Punk (Endpunkt) im Code> ein Interrupt getriggert wird, dann springe nach ausführen des> Interrupts zum Startpunkt(!) zurück."
Kuddelmuddel! Du brauchst ein anderes Konzept! Egal auf welchem
Prozessor.
Siehe die Antwort von Jörg. Die Frage ist, wie dringend muss der Sensor
WIRKLICH ausgelesen werden?
a) Nicht super dringend, die aktuelle Sensorabfrage kann noch beendet
werden. Dann reicht es, im Interrupt ein Flag zu setzen und das Auslesen
des Sensor in der passenden State machine im Hauptprogramm zu
machen, gleich nach der Beendigung des aktuellen Sensorzugriffs.
b) SUPER DRINGEND! Wenn das WIRKLICH der Fall ist (über wie viele
Millisekunden reden wir her?) muss man den Sensor ggf. an einen extra
SPI-Bus hängen und im Interrupt auslesen. Dann kommt sich auch nix in
die Quere.
c) SUPER DRINGEND und der Sensor kann NICHT an einen an einen extra
SPI-Bus gehängt werden. Dann liest man den Sensor im Interrupt direkt
aus und setzt ein "Hallo-ich hab mal dazwischengefunkt"-Flag. Dieses
wird von den normalen Funktion vor dem normalen Sensorzugriff gelöscht
und am Ende nochmal geprüft. Ist es dann gesetzt, hat der Interrupt
dazwischen gefunkt und der Zugriff muss wiederholt werden. Dafür braucht
es keinerlei exotische Programmfunktionalität.
SPI per Interrupt macht meist keinen großen Sinn. (Ausnahme: man hat
seeehr langsame SPI-Clients, die man nur mit vergleichsweise niedrigerer
Datenrate takten kann.)
Aber da muss uns Hanna erstmal schreiben, welche Sensoren sie da
überhaupt am Bus hat.
Route_66 H. schrieb:> Wären zwei SPI-Busse die Lösung?
Auch das kommt auf die externe Hardware an. Du kannst nicht bei jedem
Chip einfach die Kommunikation mitten im Takt pausieren.
Hanna schrieb:> einen Eingangs-Pin, der bei fallender Flanke eine Interruptfunktion> auslösen soll
Woher kommt das Signal das da an diesem "Eingangs-Pin" anliegt?
Interrupts nimmt man, wenn etwas, das nicht lange dauert, schnell
bearbeitet werden muss.
So, wie wenn du gerade einen Kuchen backst. Dann darf dich vielleicht
der Postbote ganz kurz unterbrechen. Das Öffnen und Auspacken des
Pakets bzw. das Bearbeiten der Post sowie das Bezahlen der Rechnungen
verschiebst du aber auf später.
Und wenn grade die Eier ins Mehl geschlagen hast und du siehst durchs
Fenster, dass draußen die Hecke geschnitten werden muss, dann merkst
du dir diese Aufgabe und verschiebst das auf später. Und backst davor
erst mal den Kuchen fertig.
Hanna schrieb:> Wenn jetzt aber der Fall auftritt, dass gerade ein Sensor, der an> besagtem SPI Bus hängt, ausgelesen wird und dabei gleichzeitig die> Interruptfunktion aufgerufen wird, um einen anderen Sensor in diesem> Bussystem auszulesen, führt das zu Kuddelmuddel.
Du gehst also einfach her und merkst dir im jeweiligen Interrupt, dass
du den entsprechenden Sensor auslesen musst. Und dann bearbeitest du
diese Aufgaben später hübsch nacheinander.
Stefan ⛄ F. schrieb:> Route_66 H. schrieb:>> Wären zwei SPI-Busse die Lösung?>> Auch das kommt auf die externe Hardware an. Du kannst nicht bei jedem> Chip einfach die Kommunikation mitten im Takt pausieren.
Dann ist es kein Jim Beam, ähhh, SPI. Aber OK, es gibt einige ICs, z.B.
AD-Wandler, welche mit dem SPI-Takt die Wandlung durchführen oder
zumindest starten.
Aber alles in allem ist es keine sonderlich gute Idee, das SPI im
Interrupt einfach so brachial zu übernehmen.
Falk B. schrieb:> Aber OK, es gibt einige ICs, z.B.> AD-Wandler, welche mit dem SPI-Takt die Wandlung durchführen oder> zumindest starten.
Genau das hatte ich dabei im Sinn.
Hi Zusammen,
um nochmal etwas Klarheit zu schaffen:
Die beiden Sensoren um die es geht sind
1. Ein Accelerometer, das hin und wieder ausgelesen werden soll (ca alle
200ms- 1 mal pro Sekunde). Ich benötige momentan 1.6ms für die gesamte
Kommunikation mit dem Accelerometer. (Hier ist vermutlich noch
Verbesserungspotenzial)
und
2. ein ADC, der (siehe Falk Bs Antwort) SUPER DRINGEND ausgelesen werden
muss. (ca. einmal pro ms und dann muss der Interrupt innerhalb weniger
us (genauere Werte habe ich hier noch nicht) aufgerufen werden).
Falk B. schrieb:> c) SUPER DRINGEND und der Sensor kann NICHT an einen an einen extra> SPI-Bus gehängt werden. Dann liest man den Sensor im Interrupt direkt> aus und setzt ein "Hallo-ich hab mal dazwischengefunkt"-Flag. Dieses> wird von den normalen Funktion vor dem normalen Sensorzugriff gelöscht> und am Ende nochmal geprüft. Ist es dann gesetzt, hat der Interrupt> dazwischen gefunkt und der Zugriff muss wiederholt werden. Dafür braucht> es keinerlei exotische Programmfunktionalität.
Bei dem Vorschlag mit der "Hallo-ich hab mal dazwischengefunkt"-Flag
wäre dann vorher vermutlich wieder die Frage ob die Hardware das so
einfach mitmacht...
Route_66 H. schrieb:> Wären zwei SPI-Busse die Lösung?
Zwei SPI-Busse sind keine Alternative
Hanna schrieb:> Bei dem Vorschlag mit der "Hallo-ich hab mal dazwischengefunkt"-Flag> wäre dann vorher vermutlich wieder die Frage ob die Hardware das so> einfach mitmacht...
klingt aber erstmal einfacher als meine erste Idee :D
Hanna schrieb:> Hi Zusammen,>> um nochmal etwas Klarheit zu schaffen:> Die beiden Sensoren um die es geht sind> 1. Ein Accelerometer, das hin und wieder ausgelesen werden soll (ca alle> 200ms- 1 mal pro Sekunde).
Also absolut unkritisch.
> Ich benötige momentan 1.6ms für die gesamte> Kommunikation mit dem Accelerometer. (Hier ist vermutlich noch> Verbesserungspotenzial)
Klingt so, denn in 1,6ms kann man selbst bei nur 1MHz SPI-Takt satte
1600 Bit bzw. 200 Bytes übertragen. Und ich glaube nicht, daß dein SPI
nur mit 1MHz läuft.
> und> 2. ein ADC, der (siehe Falk Bs Antwort) SUPER DRINGEND ausgelesen werden> muss. (ca. einmal pro ms und dann muss der Interrupt innerhalb weniger> us (genauere Werte habe ich hier noch nicht) aufgerufen werden).
AHA! Also ein periodischer Interrupt mit schon recht hoher Frequenz.
Aber daran erkennt man, daß es mit 1,6ms Auslesezeit für das
Accelerometer so oder so nicht geht, denn diese Zugriffe müssen in die
Lücken des ADCs passen. Und damit ist auch das Konzept klar. Der
Interrupt macht einen sofortigen, direkten ADC-Zugriff. Direkt danach,
noch im Interrupt wird geprüft, ob das Zeitfenster für das Accelerometer
erreicht ist. Wenn ja, wird es im Anschluß ausgelesen. Damit gibt es
keinerlei Überschneidungen beim SPI-Zugriff, alle Zugriffe finden an
einer Stelle nur im Interrupt statt.
Falk B. schrieb:> Also ein periodischer Interrupt mit schon recht hoher Frequenz.
Leider nicht ganz (Hätte ich vielleicht anders formulieren sollen).
Es gibt auch Phasen hin und wieder, da wird der Interrupt nur sehr
selten bis gar nicht ausgelöst. Trotzdem soll dann das Accelerometer
ausgelesen werden.
Hanna schrieb:> Leider nicht ganz (Hätte ich vielleicht anders formulieren sollen).> Es gibt auch Phasen hin und wieder, da wird der Interrupt nur sehr> selten bis gar nicht ausgelöst. Trotzdem soll dann das Accelerometer> ausgelesen werden.
Hmm, schon wieder ein sehr fragwürdiges Konzept.
Wenn das denn WIRKLICH so ist und so sein soll, hast du das Problem, daß
du auch in den Pausen das Accelerometer nicht in der Hauptschleife
auslesen kannst, denn der Interrupt kann ja jeden Moment zuschlagen.
Oder gibt es wenigstens eine Art Vorhersagemöglichkeit, daß man weiß,
OK, wir haben JETZT ca. ???ms Ruhe vom ADC, jetzt können wir das
Accelerometer auslesen. Wenn du das nicht hast, wird es ZIEMLICH
schwierig, das sauber zu lösen.
Hanna schrieb:> und 2. ein ADC, der (siehe Falk Bs Antwort) SUPER DRINGEND ausgelesen> werden muss. (ca. einmal pro ms und dann muss der Interrupt innerhalb> weniger us (genauere Werte habe ich hier noch nicht) aufgerufen werden).
Kann man den ADC nicht sauber per Timer die Wandlung triggern lassen und
dann ggf. sogar noch per DMA die Ergebnisse transferieren? (Ich weiß,
DMA und SPI vertragen sich nicht immer, je nachdem, wie das Select
erfolgt.)
Ansonsten sollte man vielleicht das aus einem Timer-Interrupt anwerfen,
der regelmäßig zuerst den ADC abfragt und dann ggf. noch das
Accelerometer.
Falk B. schrieb:> Oder gibt es wenigstens eine Art Vorhersagemöglichkeit, daß man weiß,> OK, wir haben JETZT ca. ???ms Ruhe vom ADC, jetzt können wir das> Accelerometer auslesen
Da will mir nichts einfallen...
Ich würde eher versuchen, die Kontrolle selbst zu übernehmen:
Lassen sich die Sensorwerte auch abfragen(*), oder ist man darauf
angewiesen, dass der Sensor sich meldet?
(*) Die Sensoren sollen in einem ausreichend feinen Zeitraster
abgefragt werden.
Jörg W. schrieb:> Kann man den ADC nicht sauber per Timer die Wandlung triggern lassen und> dann ggf. sogar noch per DMA die Ergebnisse transferieren? (Ich weiß,> DMA und SPI vertragen sich nicht immer, je nachdem, wie das Select> erfolgt.)
Wenn ich das richtig verstehe, funktioniert das leider nicht, da ich den
Wert vom ADC zu exakt (zumindest sehr genau zu) dem Zeitpunkt brauche,
an dem der Interrupt ausgelöst wird und in der Interruptfunktion
passieren noch andere Dinge, die unmittelbar mit dem ADC-Auslesen
zusammenhängen. (sprich: Reset von Integratoren).
Ralf G. schrieb:> Lassen sich die Sensorwerte auch abfragen(*), oder ist man darauf> angewiesen, dass der Sensor sich meldet?
Das verstehe ich nicht, im Moment melde ich mich beim Sensor: "Schick
mir doch bitte die Werte" woraufhin der Sensor mir die Werte schickt ;)
Ackerbau schrieb:>> dass der Sensor sich meldet?>> Er meint damit den Interrupt Pin, der dich dazu bewegt beim Sensor> anzufragen.
Achso... also man könnte auch den ADC auslesen und wenn der einen
bestimmten Wert ausgibt, dann könnte ich quasi die Interrupt Funktion
manuell ausführen, aber dann müsste ich ja wirklich fast durchgehend die
Werte vom ADC abfragen und ich weiß nicht, was mir das bringen würde...
Ahh, ich glaube, jetzt hab' ich's (nach mehrmaligem Durchlesen)...
Der Interrupt ist die Anforderung, dass jetzt bestimmte|alle Sensoren
abgefragt werden sollen.
Wie groß darf der Fehler sein?
- (Extrem '1') 'gegen null': dann sollte der Abruf möglichst aller
Sensoren innerhalb des kürzestmöglichen Interruptintervalles erfolgen
können
- (Extrem '2') 'naja, geht so': Sensoren reihum auslesen und speichern,
bei Interrupt Daten aus 'Datenbank' übermitteln (auch wenn die dann
vielleicht nicht millisekundenaktuell sind)
Lese gerade:
Hanna schrieb:> aber dann müsste ich ja wirklich fast durchgehend die> Werte vom ADC abfragen und ich weiß nicht, was mir das bringen würde...
Du legst fest, was passiert! Sonst quatschen alle durcheinander...
Nochmal zu:
'Ahh, ich glaube, jetzt hab' ich's'...
... wahrscheinlich doch nicht? Der Sensor löst einen Interrupt aus, wenn
er was zu melden hat?
Hanna schrieb:> Falk B. schrieb:>> Oder gibt es wenigstens eine Art Vorhersagemöglichkeit, daß man weiß,>> OK, wir haben JETZT ca. ???ms Ruhe vom ADC, jetzt können wir das>> Accelerometer auslesen>> Da will mir nichts einfallen...
D.h. die Interrupts kommen sporadisch und trotzdem mit hoher Frequenz?
Falk B. schrieb:> D.h. die Interrupts kommen sporadisch und trotzdem mit hoher Frequenz?
Könnte man so sagen...
Also es kommt aufs Eingangssignal drauf an, das ich messen möchte.
Wesentlich ist:
Bei großem Eingangssignal kommt der Interrupt häufiger (bis zu 1x pro
1ms)
Bei kleinem Eingangssignal seltener (nur 1x pro Minute o.ä.)
Das Eingangssignal ist nicht vorhersehbar, sprich folgt keinem
bestimmten Muster (Sinusfrequenz o.ä.)
Hanna schrieb:> Könnte man so sagen...> Also es kommt aufs Eingangssignal drauf an, das ich messen möchte.> Wesentlich ist:> Bei großem Eingangssignal kommt der Interrupt häufiger (bis zu 1x pro> 1ms)> Bei kleinem Eingangssignal seltener (nur 1x pro Minute o.ä.)> Das Eingangssignal ist nicht vorhersehbar, sprich folgt keinem> bestimmten Muster (Sinusfrequenz o.ä.)
Was ist das denn für ein komischer ADC? Klingt nach einem
selbstgestrickten ADC mit Zählverfahren. Was muss denn im Interrupt aus
dem ADC ausgelesen werden?
Ralf G. schrieb:> Ahh, ich glaube, jetzt hab' ich's (nach mehrmaligem Durchlesen)...> Der Interrupt ist die Anforderung, dass jetzt bestimmte|alle Sensoren> abgefragt werden sollen.>> Wie groß darf der Fehler sein?> - (Extrem '1') 'gegen null': dann sollte der Abruf möglichst aller> Sensoren innerhalb des kürzestmöglichen Interruptintervalles erfolgen> können> - (Extrem '2') 'naja, geht so': Sensoren reihum auslesen und speichern,> bei Interrupt Daten aus 'Datenbank' übermitteln (auch wenn die dann> vielleicht nicht millisekundenaktuell sind)>> Lese gerade:> Hanna schrieb:>> aber dann müsste ich ja wirklich fast durchgehend die>> Werte vom ADC abfragen und ich weiß nicht, was mir das bringen würde...>> Du legst fest, was passiert! Sonst quatschen alle durcheinander...>> Nochmal zu:> 'Ahh, ich glaube, jetzt hab' ich's'...> ... wahrscheinlich doch nicht? Der Sensor löst einen Interrupt aus, wenn> er was zu melden hat?
Nicht ganz... Der eine Sensor (ADC) soll ausgelesen werden, wenn ein
bestimmter I/O Pin seinen Zustand von high auf low wechselt (das
passiert bis zu 1000x pro Sekunde, muss aber nicht).
Ein anderer Sensor (der Accelerator) soll in regelmäßigen Zeitabständen
(z.B. alle 200ms) ausgelesen werden.
Beide Sensoren hängen im gleichen SPI-Bussystem.
Beim ADC ist das Timing sehr(!) wichtig. Beim Accelerator eher weniger.
Falk B. schrieb:> Hanna schrieb:>> Könnte man so sagen...>> Also es kommt aufs Eingangssignal drauf an, das ich messen möchte.>> Wesentlich ist:>> Bei großem Eingangssignal kommt der Interrupt häufiger (bis zu 1x pro>> 1ms)>> Bei kleinem Eingangssignal seltener (nur 1x pro Minute o.ä.)>> Das Eingangssignal ist nicht vorhersehbar, sprich folgt keinem>> bestimmten Muster (Sinusfrequenz o.ä.)>> Was ist das denn für ein komischer ADC? Klingt nach einem> selbstgestrickten ADC mit Zählverfahren. Was muss denn im Interrupt aus> dem ADC ausgelesen werden?
Damit meine ich nicht das Eingangssignal vom ADC, sondern ein anderes.
Ich möchte im Grunde einen Strom messen. Der ADC soll natürlich nur die
Eingangsspannung messen, bei großen Strömen halt häufiger.
Hanna schrieb:>> Was ist das denn für ein komischer ADC? Klingt nach einem>> selbstgestrickten ADC mit Zählverfahren. Was muss denn im Interrupt aus>> dem ADC ausgelesen werden?>> Damit meine ich nicht das Eingangssignal vom ADC, sondern ein anderes.> Ich möchte im Grunde einen Strom messen. Der ADC soll natürlich nur die> Eingangsspannung messen, bei großen Strömen halt häufiger.
Und dafür macht du so ein Theater? Lies den ADC REGELMÄßIG aus, dann
weißt du, wann Pausen für andere Dinge sind.
Ich würde eine Globle Variable setzt z.b. stoped = false
Die Interruptroutine wird so gecodet
Sub Interrupt
If stoped = true then exit sub
if stoped = false then
stoped = true
call gemuetlich_auslesen
end if
exit sub
sub gemuetlich_auslesen
lese_senor_1_aus
lese_senor_2_aus
lese_senor_3_aus
stoped = false
end sub
Problem gelöst.
Ach ja ich code unter B4a da würde der Code funktioniern
Falk B. schrieb:> Ohje, jetzt kommen die BASCOM-Philosophen.
Ich code nicht in Bascom. Das ist B4R um genau zu sein. B4R schreibe
einen Arudino-IDE fähigen Code. Ruft die IDE auf, compiliert und die
Arduino-IDE schiebt ihn auf den Chip.
Ich bin einfach nur ein Mensch der Geschweifte Klammern hasst. ;)
Nachtrag :
https://www.b4x.com/android/forum/
Der fast gleiche Code (Programm-Engine) (besondere Eigenheiten der
Geräte müssen berücksichtigt werden) funktioniert auf Raspberry, Java,
Android und für 100 Euro im Jahr auch auf Apple-Zeug. Ergo : Alles was
nicht MS + VB ist code ich damit.
Und der Editor ist Visual-Basic like.
Also wieso 100 Syntax für den selben Mist. und Wieso teures Bascom
bezahlen. ??!
Falk B. schrieb:> nd dafür macht du so ein Theater? Lies den ADC REGELMÄßIG aus, dann> weißt du, wann Pausen für andere Dinge sind.
Ich dachte das könnte ich mir sparen, denn ich tue viele andere Dinge :D
Hanna schrieb:>> nd dafür macht du so ein Theater? Lies den ADC REGELMÄßIG aus, dann>> weißt du, wann Pausen für andere Dinge sind.>> Ich dachte das könnte ich mir sparen, denn ich tue viele andere Dinge :D
Was denn? Nebenbei Instagrammen und Influencen? ;-)
Sag doch mal, was das für ein komischer ADC sein soll und was der wie
mißt und warum du glaubst, das mit derartig sporadischen, dann aber
mikrosekundengenauen SPI-Zugriffen machen zu müssen. Bei den meisten
ADCs ist das nicht so, die halten ihre Ergebnisse bis zum Sankt
Nimmerleinstag in den Registern, die kann man beliebig langsam auslesen,
wenn gleich die nächste Wandlung dann warten muss.
> 1. Ein Accelerometer, das hin und wieder ausgelesen werden soll (ca alle> 200ms- 1 mal pro Sekunde). Ich benötige momentan 1.6ms für die gesamte> Kommunikation mit dem Accelerometer. (Hier ist vermutlich noch> Verbesserungspotenzial)>und> 2. ein ADC, der (siehe Falk Bs Antwort) SUPER DRINGEND ausgelesen werden> muss. (ca. einmal pro ms und dann muss der Interrupt innerhalb weniger> us (genauere Werte habe ich hier noch nicht) aufgerufen werden).
Die beiden Forderungen sind mit einem einzelnen SPI-Bus nicht unter
einen Hut zu bekommen.
a) Wenn der ADC jede Millisekunde eine Abfrage fordert, bleiben keine
1.6ms mehr für den Beschleunigungssensor übrig.
b) Wenn das Auslesen des Accelerometer gerade läuft und dann eine
Anforderung des ADC ankommt, kann diese nicht sofort bedient werden.
Selbst falls die Abfrage des Accelerometers unterbrochen werden könnte,
dauert das einige SPI-Takte und du hast dann einen Jitter auf dem
ADC-Abfragezeitpunkt.
Ehe man so ein Zippel Zappel an einem SPI Bus macht, schliesst man das
Acceldings an ein paar freie Pins an und bitbangt die paar Bytes ein.
Dann bleibt die ganze ISR/SPI Hardware frei für diesen ADC.
Matthias S. schrieb:> Dann bleibt die ganze ISR/SPI Hardware frei für diesen ADC.
Naja, ein SAMD21 hat sechs(!) SERCOMs, daran allein kann es eigentlich
auch nicht liegen …
Eventsystem mit DMA Controller ist keine Lösung für dein ADC?
Falls der ACC Sensor länger als 1ms zum Auslesen benötigt muss der dann
natürlich an einen anderen SPI...
/Bei dem Vorschlag mit der "Hallo-ich hab mal dazwischengefunkt"-Flag
wäre dann vorher vermutlich wieder die Frage ob die Hardware das so
einfach mitmacht.../
man nimmt da einfach ein Register und setzt dort ein einzelnes Bit, dies
ist das das oben genannte "Hallo-ich hab mal dazwischengefunkt"-Flag.
Mir ist noch kein µC begegnet der das nicht gekonnt hätte.
00000000 Interrupt xyz hat nicht dazwischengefunkt
00000001 Interrupt abc hat dazwischengefunkt
00000010 Interrupt 123 hat dazwischengefunkt
Für mich hört sich das so an als ob du diesen Wert gar nicht alle 1mSek
benötigst, warscheinlich ist dieser eh veraltet da ihn der Sensor
vielleicht schon vor 5 mSek gemessen hat und du ihn jetzt erst abrufst.
ansonsten dein µC hat doch passende ADC's onboard, wieso dann nicht
gleich den passenden Sensor nehmen und auf die SPI Krücke verzichten.
*12-bit, 350ksps Analog-to-Digital Converter (ADC) with up to 20
channels
Differential and single-ended input
*1/2x to 16x programmable gain stage
*Automatic offset and gain error compensation
*Oversampling and decimation in hardware to support 13-, 14-, 15- or
16-bit resolution
>> Bei dem Vorschlag mit der "Hallo-ich hab mal dazwischengefunkt"-Flag>> wäre dann vorher vermutlich wieder die Frage ob die Hardware das so>> einfach mitmacht...>> Mir ist noch kein µC begegnet der das nicht gekonnt hätte.
Mit Hardware ist nicht der Prozessor sondern die SPI-Peripherie gemeint.
Hanna schrieb:> Sprich: Wenn gerade ein Sensor ausgelesen wird und> die Interruptfunktion ausgelöst wird, soll das auslesen des anderen> Sensors abgebrochen werden, die Interruptfunktion ausgeführt und dann> der Sensor erneut ausgelesen werden.
Das ist Unfug^³.
SPI ist nicht reentrant. Entweder alles als Interrupt oder als Main.
Die Main-Funktionen können ja einfach in einen Puffer schreiben, den der
SPI-Interrupt dann abarbeitet.
Wenn es aber unbedingt so sein muß (muß es nie), dann nimmt man einfach
einen MC mit mehreren SPI. Z.B. der ATmega2560 kann bis 5 SPI-Master
parallel benutzen, die 4 UARTs können auch SPI.
Peter D. schrieb:> dann nimmt man einfach einen MC mit mehreren SPI
Hat sie doch, schrieb ich oben: stolze 6 SERCOMs sind zur Verfügung.
Inwiefern natürlich ggf. das Hardware-Layout vergurkt ist und an wie
viele man davon rankommt, muss sie selbst klären.
Hanna schrieb:> Wenn jetzt aber der Fall auftritt, dass gerade ein Sensor, der an> besagtem SPI Bus hängt, ausgelesen wird und dabei gleichzeitig die> Interruptfunktion aufgerufen wird, um einen anderen Sensor in diesem> Bussystem auszulesen, führt das zu Kuddelmuddel.
Auf einem Controller mit einem einzigen Kern gibt es kein "gleichzeitig"
;-)
Der Interrupt kann die erste Lesefunktion nur unterbrechen, wenn du es
ihm erlaubst. Alles andere ist eine Frage der Softwarearchitektur - und
ganz richtig - zwei verschachtelte Leseoperationen auf dem selben Bus
gehen schief.
>Es gibt auch Phasen hin und wieder, da wird der Interrupt nur sehr>selten bis gar nicht ausgelöst.
Man kann eine CPU nicht mit mit beliebig kurzen aufeinanderfolgenden
INT-Anforderungen belasten. Irgentwann packt die es nicht mehr, und jede
ISR benötigt eine gewisse Anzahl von Takten (je weniger desto besser).
Je öfter/schneller das passieren soll desto höher die INT-Priorität
desto weniger die Takte in der ISR (sonst fährt das System sich fest).
Betr dem ADC wäre die Frage:
Wie genau, bzw wie einfach könnte das Timing (!) gemacht werden; ob
nicht vieleicht sogar ein period. Abfrage (1 ms) gehen würde / gemacht
werden sollte, was einfacheres Timing wäre. (Es schadend nichts, wenn
CPU manchmal einige Werte 'zuviel' liest, die gar nicht benötigt werden,
diese Werte später aber wieder da sind wenn sie benötigt werden (im
worstcase wären es vermutlich sowiso 1ms)).
Und wenn ein Sensor bsp. nur alle 50ms mal abgefragt werden soll heist
das nicht, dass die Abfrage selbst 50ms dauern muss. Dies Abfrage passt
doch problemlos in ein 1ms 'Protokoll' hinein.
MCUA schrieb:>>Es gibt auch Phasen hin und wieder, da wird der Interrupt nur sehr>>selten bis gar nicht ausgelöst.> Man kann eine CPU nicht mit mit beliebig kurzen aufeinanderfolgenden> INT-Anforderungen belasten. Irgentwann packt die es nicht mehr, und jede> ISR benötigt eine gewisse Anzahl von Takten (je weniger desto besser).> Je öfter/schneller das passieren soll desto höher die INT-Priorität> desto weniger die Takte in der ISR (sonst fährt das System sich fest).
Mann O Mann, dümmer kann man wohl kaum antworten! Da spricht der OP von
selten bis gar nicht bzw. maximal 1x pro Millisekunde und ein "Experte"
faselt was von beliebig kurzen Interruptanforderungen!
Setzen, Sechs! Thema verfehlt!
In Größenordnungen um 1ms sind Interruptroutinen meistens sowieso das
falsche Mittel. Da geht man mit Hardware ran, die Daten ganz alleine
erfasst und in Puffer schreibt.
-> Siehe Soundkarten und Grafikkarten (bzw. Chipsätze) im PC
Die CPU kann die gepuffertem Daten wesentlich effizienter blockweise
abarbeiten.
Stefan ⛄ F. schrieb:> In Größenordnungen um 1ms sind Interruptroutinen meistens sowieso das> falsche Mittel. Da geht man mit Hardware ran, die Daten ganz alleine> erfasst und in Puffer schreibt.
Unsinn, wir leben nicht mehr im Jahr 1970, wo Mikrocontroller
bestenfalls dreistellige kHz Taktraten hatten. 1ms ist selbst für kleine
Mikrocontroller ala AVR, PIC & Co eine kleine Ewigkeit.
> -> Siehe Soundkarten und Grafikkarten (bzw. Chipsätze) im PC>> Die CPU kann die gepuffertem Daten wesentlich effizienter blockweise> abarbeiten.
OMG! Du vergleichst Melonen mit Erdnüssen!
>Setzen, Sechs! Thema verfehlt!
von wegen...
du musst dich setzen!
Auch kannst du nicht lesen!
Der TO hat von us-genauer Anforderung geschrieben.
Im Gegensatz zu deinem Gesülze ist an meinem Beitrag Rein Gar Nichts
auszusetzen.
> In Größenordnungen um 1ms sind Interruptroutinen meistens sowieso das> falsche Mittel.
Nö, grade nicht.
Sind bei 100MHz ganze 100000 Takt-Cyclen (also bestenfalls so viele
Befehle), mit denen du arbeiten kannst.
wenn ich die Frage richtig verstanden habe,
dann seh ich auch den grösseren Nutzen darin den "unkritischen" Sensor
in einer schleife zu lesen,
dessen Wert kann damit ruhig einen Schleifendurchlauf altern (eben
unkritisch)
solange der ADC (was auch immer dran hängt) das nicht tut, der bleibt in
einer ISR.
Im Grunde braucht es also zwei globale variablen
einen für den alternden wert,
den anderen für die Abfrage ob die ISR aufgerufen wurde wurde
das kostet Taktzyklen leider.. ich glaub 5?
in pseudo code in etwa
1
//global vars
2
accsensordata; //kA was rein soll, int array würde ich vermuten
3
isrtriggered = false; // 'ne boolean
4
.......
5
isr()
6
{
7
read_adcvalue();
8
isrtriggered = true;
9
report_isrdata();
10
.......
11
}
12
13
main() //Hauptschleife, im Grunde irgendeine while(1) oder so
14
{
15
........
16
loopstart:
17
isrtriggered = false; // ab hier ist nichtmehr egal ob der isr ausgelöst wurde
18
// hier sollte nur was zwischen was auch den Beschleunigungssensor betrifft.
19
preaparation(&sens);
20
some_random_stuff(&sens);
21
if(isrtriggered) goto loopstart; //bis hier ist alles 'geschützt'
22
accsensordata = read_accsensor(&sens);
23
report_sensordata();
24
........
25
}
Nachteil:
das Auslesen des Beschleunigungssensors (das war doch der unkritische,
oder?)
über irgendetwas anderes als mundgemaltes Assembler vermutlich
eine mehrzeilige ungesicherte Lücke lässt in der der Interrupt die ISR
auslösen kann.
ich glaube nicht, dass der isr zu jedem Taktzyklus ausgelöst werden
kann,
ich meine immer nur vor oder nach einem assembler Befehl (nie probiert);
Also müsste die Abfrage ob der isr auslöste (isrtriggered) so nah wie
möglich an das neuschreiben der Speicherzelle (accsensordata)
wenn es mehrere speicherzellen sind (array?) eventuell sogar vor jede
davon.
Assembler verknotet mir aber zu sehr das Gehirn um das auch nur
annäherend logisch/inhaltlich korrekt hier hinkritzeln zu können.(da
brauch ich cheatsheets und Kaffee und jmd der mir die Hand hält für)
Das kann bestimmt jmd anderes besser als ich ;)
Das Prinzip bleibt dasselbe.
nachdem der immens wichtige Senor durch den interrupt ausgelöst wurde,
setzt man ein flag,
das man in einer permanent laufenden schleife
exakt vor dem neuschreiben der Beschleunigungssensordaten prüft
um ggf zum Anfang der Schleife zurückzuspringen.
'okay' geht das in jeder Hochsprache die Sprungmarken akzeptiert (alle
mir bekannten)
'richtig gut' geht das mMn nur in Assembler, weil man nur da
sicherstellen kann, dass die Abfrage auch EXAKT einen Befehl vor dem
Schreiben des Speichers landet und man im Zweifel auch an bessere
Position zurückspringen kann.
'perfekt' geht das mMn garnicht,
da ich glaube der Interrupt kann keinen 'laufenden' assemblerbefehl
abbrechen,
Also könnte der interrupt im Zweifel trotzdem
exakt ausgelöst werden nachdem gepüft wurde ob der isr aufgerufen worden
ist, womit der Speicher in dieser Schleife dennoch mit dem
möglicherweise schon veralteten 'neuen Wert' beschrieben würde.
Glücklicherweise ist das aber ja der unkritische von beiden ;)
Ich mag aber auch die Frage falsch verstanden haben, und der acc-sensor
muss ebenfalls unbedingt via interrupt Aufruf seine Daten preisgeben.
#schulterzuck
In dem Fall würde man den interrupt des 'unkritischen' während der isr
des 'dringenden' löschen müssen und erst nach dessen Ausführung wieder
zulassen.
'sid
Wie viele Daten müssen vom Accelerometer geholt werden?
Kann man die in kleineren Häppchen holen?
Lässt der/die/das Accelerometer das zu?
Dann wäre folgendes möglich:
jede 1ms ADC lesen und im Anschluss ein Häppchen vom Accelerometer
>da ich glaube der Interrupt kann keinen 'laufenden' assemblerbefehl>abbrechen,
Ein Interrupt unterbricht i.d.R. keinen ASM-Befehl, braucht er auch gar
nicht, da ein ASM-Befehl, norm. sehr kurz ist.
(Ausnahme vielleicht umfangreiche Befehle, MUL, MAC, RMAC, Stingbefehle
usw, die umfassendere Hardware erfordern. Bei einigen CPUs sind solche
Befehle unterbrechbar (ggfs je nach INT-Priorität), bei anderen nicht.
Man sollte also je nach Timing-Anforderung (sofern man 'ms' und 'us'
unterscheiden kann) drauf achten, zu lang andauernde Befehle ggfs. nicht
zu benutzen, auch dürfen u.U. wegen Abhängigkeiten zusammenhängende
Befehlsfolgen gar nicht unterbrochen werden.)
>Unsinn, wir leben nicht mehr im Jahr 1970, wo Mikrocontroller>bestenfalls dreistellige kHz Taktraten hatten.
Im Jahr 1970 gab es keine Mikrocontroller.
Hanna schrieb:> Ich benutze einen SAMD21J18A und ATMEL START/ATMEL Studio (AFS4)> Umgebung, um ihn zu programmieren.
Das ist hier völlig nebensächlich. Nimm als Toolchain was dir gefällt,
es spielt für einen sinnvollen Aufbau einer Firmware keine Rolle.
> Jetzt habe ich folgendes Problem:> Ich habe einen SPI Bus, an dem verschiedene Sensoren dran hängen und> einen Eingangs-Pin, der bei fallender Flanke eine Interruptfunktion> auslösen soll, die mir einen bestimmten Sensor, über die SPI-Verbindung,> auslesen soll.>> Wenn jetzt aber der Fall auftritt, dass gerade ein Sensor, der an> besagtem SPI Bus hängt, ausgelesen wird und dabei gleichzeitig die> Interruptfunktion aufgerufen wird, um einen anderen Sensor in diesem> Bussystem auszulesen, führt das zu Kuddelmuddel.
Eben die Idee, so etwas machen zu wollen, ist der Grund für deinen
Kuddelmuddel. Also mal was Grundsätzliches zu Interrupts:
Ein Interrupt ist etwas, das von der µC-Peripherie aktiviert wird, wenn
eben genau DIESE ganz dringend einen Service benötigt. Die Betonung
liegt auf DIESE.
Du hast hingegen irgend einen Eingang, an dem irgend eine Schaltung dran
herumziehen kann, wenn sie meint, daß ein Sensor auszulesen sei. Ist ja
nett, aber das hat mit dem SPI und dem Sensor rein garnichts zu tun. Es
ist eine andere Aktivität als das Auslesen eines Sensors. Also hat so
etwas auch rein garnichts in einer Interruptroutine zu suchen.
Mach eines: Wenn dein von irgendwo ausgelöster Interrupt kommt, dann
generiere daraus einen Event, der in eine Event-Warteschlange eingereiht
wird. Und eben diese Event-Warteschlange wird schön der Reihe nach in
der Grundschleife in main abgearbeitet. Damit kannst du all die ganze
Ausleserei gut genug steuern.
Meinetwegen nenne deine Events "LiesSensor1aus", "LiesSensor2aus",
"LiesSensor4711aus" oder sonstwie und ordne diesen Events irgend eine
passende Nummer zu. Wenn du nicht mehr als rund 250 verschiedene
Eventarten brauchst, dann reicht pro Event ein simples Byte in der Queue
aus.
W.S.
> Event System mit DMA sollte das ohne CPU Intervention hinbekommen...
Das funktioniert wie oben erläutert über gleiches SPI (mehrere Sensoren
...) bis zu einer bestimmten Timing-Anforderung (sofern man Lesen kann
und nicht auf Anfänger-Gesülze hört) über SPI-FIFO.