Forum: Mikrocontroller und Digitale Elektronik I2C Sniffer with onboard analyzer


von David S. (Gast)


Lesenswert?

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.

von Dr. Sommer (Gast)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von Draco (Gast)


Lesenswert?

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?!

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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 ?

von Draco (Gast)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von Stefan (Gast)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

von Gerd E. (robberknight)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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
von David S. (Gast)


Lesenswert?

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.

von OPi (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.