Hallo, ich versuche zur Zeit mit einem STM32-P103 Board (72Mhz) einen I2C Bus zu sniffen, die Daten onboard zu analysieren und via CAN wieder rauszuschicken. I2C Bus Speed bis max 200kbit soll unterstützt werden. Zum Sniffen nutze ich GPIO's die als Interrupts konfiguriert sind und auf SCL und SDA, falling und rising edge triggern um I2C nachzustellen. Nun habe ich das Problem, dass ich nicht alle Nachrichten mitbekomme und der Interrupt seltener aufgerufen wird als er sollte. Nach meinen Berechnungen habe ich 180 Controller Ticks Zeit den Interrupt zu bearbeiten, wenn ich nur die I2C Clock betrachte. Nun würde ich gerne wissen, ob ich mein Board zu schwach dimensioniert habe oder mein aktueller Ansatz vielleicht aus anderen gründen nicht möglich ist.
Externe Interrupts sind immer etwas schwierig. Versuche es mal mit einer Endlosschleife in der main () die ständig die GPIO ausliest. Alternative: Verwende zwei der I2C Schnittstellen als Master und Slave und schalte sie zwischen die Kommunikation und leite alles durch. Das erhöht zwar die Latenzen, müsste aber funktionieren.
David S. schrieb: > Nun würde ich gerne > wissen, ob ich mein Board zu schwach dimensioniert habe oder mein > aktueller Ansatz vielleicht aus anderen gründen nicht möglich ist. Dein Board ist mit Sicherheit nicht zu schwach. Ich habe das mal mit Tiny2313, 400KHz und Bitbanging gemacht, also muss es ein STM32 erst recht schaffen. Vor allem, da bei 100KHz tSU:STA und tHD:STA in us Bereich sind.
Dr. Sommer schrieb: > Externe Interrupts sind immer etwas schwierig. Versuche es mal mit einer > Endlosschleife in der main () die ständig die GPIO ausliest. o.O Wie kommt man denn auf sowas?!
Draco schrieb: > Dr. Sommer schrieb: >> Externe Interrupts sind immer etwas schwierig. Versuche es mal mit einer >> Endlosschleife in der main () die ständig die GPIO ausliest. > > o.O Wie kommt man denn auf sowas?! Wieso eigentlich nicht ? Was hat ein I2C_Sniffer sonst zu tun ?
Marc V. schrieb: > Wieso eigentlich nicht ? > Was hat ein I2C_Sniffer sonst zu tun ? Naja, aber Interrupt gesteuert auf der SCL Line zu lauschen ist doch effektiver als Polling in einer Main. Er will ja auch noch "analyzern". Sprich: ein wenig rechnen muss der STM ja auch :-D Über die Performance des STM kann ich nichts sagen - da ich da keine Erfahrung habe. Aber ich rechne mal mit ca. 40 mips per ISR: 200.000 Impulse * 40 mips sind dann 8 Mhz für die ISR alleine um alle abzufangen.
Draco schrieb: > Naja, aber Interrupt gesteuert auf der SCL Line zu lauschen ist doch > effektiver als Polling in einer Main. Stimme ich zu, aber er darf nur nicht START verpassen, von da ab kann es clockgesteuerte Interrupts geben, da ist selbst bei 400KHz genug Zeit zwischen den Flanken um alles, auch evtl. Fehler zu "analyzern". Das eigentliche Problem liegt gerade in SCL - START wird mit SCL high und fallender Flanke von SDA eingeleitet. Da kann es keinen Interrupt auf SCL geben, oder man müsste in der ISR auf fallende SDA Flanke warten - und das kann ewig dauern - da kann man genauso gut in main() warten...
:
Bearbeitet durch User
Marc V. schrieb: > Das eigentliche Problem liegt gerade in SCL - START wird mit SCL > high und fallender Flanke von SDA eingeleitet. Da kann es keinen > Interrupt auf SCL geben, oder man müsste in der ISR auf fallende > SDA Flanke warten - und das kann ewig dauern - da kann man genauso > gut in main() warten... Nö, da gibt es kein Problem. Interrupts kann man im Betrieb ein und ausschalten. Es spricht also nichts dagegen, zunächst per Interrupt auf eine fallende Flanke an SDA zu warten und erst dann auf SCL zu wechseln. Ich denke, grundlegend hat es der TO auch vor, denn er spricht von InterruptS - Mehrzahl. Den Interrupt auf SDA würde ich halt nach Erkennung der Start-Condition abdrehen. Wegen möglicher Glitches auf der Leitung (z.B. bei Wechsel vom Master zu Slave beim ACK) bekommt man sonst recht viele Interrupts und da kann man sich dann schon mal verschlucken. Also: wenn man dem Bus nicht zwischen die Bits gucken will, alles schön synchron mit dem Takt einlesen.
Stefan schrieb: > Nö, da gibt es kein Problem. Interrupts kann man im Betrieb ein und > ausschalten. Es spricht also nichts dagegen, zunächst per Interrupt auf > eine fallende Flanke an SDA zu warten und erst dann auf SCL zu wechseln. Es spricht einiges dagegen. Erstens: SCL Hi und fallende Flanke an SDA muss nicht unbedingt START bedeuten, es können auch Glitches sein. Das kann aber mit Polling in main() um einiges einfacher festgestellt werden - welche Vorteile hat die Lösung mit Interrupt auf SDA ? Anstatt in loop in main() den Zustand von SDA und SCL gleichzeitig abzufragen und entsprechend zu reagieren, wird bei deiner "Lösung" folgendes gemacht: a) in einem leeren loop in main() auf Interrupt gewartet, um dann in der ISR den Zustand von SCL abzufragen ? b) in einem loop in main() wird nur der Zustand von SCL abgefragt und in dem Moment, wo es auf Low geht, werden die Interrupts auf SDA gesperrt ? Und wie geht es dann weiter ? Das kann doch nicht dein Ernst sein. Zweitens: Man soll es so einfach wie nur möglich machen - was soll ständiges Umschalten zwischen SDA und SCL bringen wenn man sowieso den einen oder anderen Zustand manuell dazu abfragen muss ? Drittens: Wie willst du mit Interrupt Repeated Start erkennen ? Viertens: Wie willst du STOP erkennen ? Irgendetwas posten nur um zu zeigen, dass man weiss wovon die Rede ist, ist nicht unbedingt produktiv.
Marc V. schrieb: > Stimme ich zu, aber er darf nur nicht START verpassen, von da ab kann > es clockgesteuerte Interrupts geben, clockgesteuerte Interrupts halte ich für gar keine gute Idee. Denn der I2C-Master kann mit seiner Clock quasi machen was er will solange er keine schnellere Clock verwendet als das langsamste Gerät auf dem Bus. Interrupts auf SCL und SDA halte ich daher für gar keine so schlechte Idee. Schön wäre es, wenn man beim DMA der STM32 auch EXTIs oder ähnliches als DMA-Request-Trigger verwenden könnte. Dann könnte man hier einfach bei jeder Änderung von SCL das DMA den gesamten Port (u.a. dann SCL und SDA) auslesen und in einen Ringpuffer schreiben lassen. Nur leider habe ich noch keine Möglichkeit gefunden das bei den STM32 so zu machen. Soweit ich weiß können das nur einige von den Kinetis-µCs.
Gerd E. schrieb: > clockgesteuerte Interrupts halte ich für gar keine gute Idee. Denn der > I2C-Master kann mit seiner Clock quasi machen was er will solange er > keine schnellere Clock verwendet als das langsamste Gerät auf dem Bus. Mit clockgesteurtem Interrupt meine ich Interrupt auf SCL. Vielleicht schlecht formuliert. > Interrupts auf SCL und SDA halte ich daher für gar keine so schlechte > Idee. Interrupt auf SDA ist auf jeden Fall eine schlechte Idee.
:
Bearbeitet durch User
Hey Leute, ich bedanke mich für die anregenden Kommentare und kann euch ein kleines Update geben. Bis 100 Kbit/s kann ich nun interruptgesteuert (SDA sowie SDL auf falling und rising edge) Nachrichten analysieren. Nun werde ich jedoch das Triggern von Start und Stop über D FLipFlops hardwareseitig regeln, sodass ich nur noch auf rising edge der SCL Leitung Triggern muss oder auch gegebenenfalls in der main danach polle. Das sollte einen guten performanceboost geben, sodass ich vielleicht auch höhere Geschwindigkeiten schaffe.
David S. schrieb: > Nun werde ich > jedoch das Triggern von Start und Stop über D FLipFlops hardwareseitig > regeln, sodass ich nur noch auf rising edge der SCL Leitung Triggern > muss oder auch gegebenenfalls in der main danach polle. Das ist doch völlig unnötig. Wieso nimmst du nicht die Compare Funktion je eines Timers (einer für SCL und einer für SDA) bzw. lass den anderen im Slave Modus laufen oder synchonisiere ihn ein. Wenn du's dir voll geben möchtest, dann nimm die DMA(s) dazu und dein Prozessorlast der Aquisition ist gleich Null. Nun kannst du die Daten in aller Ruhe im Speicher abholen.
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.