Forum: Mikrocontroller und Digitale Elektronik ATXMega, TWI (I2C) bleibt hängen


von noips (Gast)


Lesenswert?

Hallo zusammen,

ich arbeite mit einem XMega128, an den 4 I2C-Porterweiterungs-ICs 
PCA9555 angeschlossen sind. Diese ICs schalten bzw. lesen über 
Optokoppler 24V-Spannungspegel. Die 24V-Spannung wird extern 
eingespeist. Die Erweiterungs-ICs werden aber von der internen 
Boardspannung gespeist, an der auch der XMega hängt.

Nun passiert immer wieder, wenn die externe 24V-Spannung ausgeschaltet
und eingeschaltet wird, dass sich der XMega aufhängt. Er bleibt an der
Programmzeile hängen, in der abgefragt wird ob die TWI-Übertragung
abgeschlossen wurde. Dabei bleibt der Busszustand laut BUSSTATE-Bits auf
BUSY stehen und RXACK-Bit, das ja den zuletzt empfangenen
acknowledge-Bit anzeigt, ist gesetzt, es wurde folglich NACK empfangen.

Nun, das TWI-Modul im XMega hat ja die TIMOUT-Bits, die, wenn gesetzt,
den Bus wieder in den IDLE-Zustand zurückbringen, wenn er "lange"
inaktiv bleibt. Ich habe diese Bits jetzt auch gesetzt, aber das
Programm bleibt trotzdem hängen und wartet bis der Bus wieder frei ist.

Veilleicht hatte ja jemand von euch ein solches Problem und könnte mich
wissen lassen, wie er das gelöst hat. Ich wäre für die Hinweise seht
dankbar!

von noips (Gast)


Lesenswert?

Hat niemand eine Idee?

von Tim K. (timmey)


Lesenswert?

nur die ruhe die ingeneure schlafen noch ;-) (ich wart schon seit 
gestern daruf das mein Beitrag mal beachtung findet :-D)

von TrippleX (Gast)


Lesenswert?

Warte doch einfach ein wenig... es kann doch nicht immer sofort
geantwortet werden.

von noips (Gast)


Lesenswert?

Ich habe mir gedacht, 1 Stunde ist schon eine gute Wartezeit :-)

von Daniel V. (danvet)


Lesenswert?

noips schrieb:
> Ich habe mir gedacht, 1 Stunde ist schon eine gute Wartezeit :-)

Die Suchfunktion hast du benutzt?
Soweit ich weiß gibt es (auch) einen Hardwarebug, finde aber den Link 
nicht mehr...

ach ja:ohne SourceCode wird dir wenig geholfen werden können...

von Helmut R. (heru01)


Lesenswert?

Hallo noips, guten morgen Tim,

irgendein Fehler in HW? Also wenn der PCA9555 und der XMega versorgt 
bleiben, funktioniert auch I2C. Ich hatte das Problem mal, dass bei der 
MegaXX Serie I2C des Empfängers stromlos wurde - dann hat sich der Bus 
aufgehängt.

Deine Abhilfe in SW: die Atmel Treiber haben viele do{...}while... 
Konstrukte ohne Fehler abzufangen ==> Controller bleibt 'stecken'
Abhilfe:
1
ulTimeOutCtr = 0xFFF...
2
do
3
{
4
  ulTimeOutCtr--;
5
} while ...
6
7
if (!ulTimeOutCtr)
8
  //Reset I2C
9
else
10
...

Gruß
Helmut

von noips (Gast)


Lesenswert?

>Die Suchfunktion hast du benutzt?
>Soweit ich weiß gibt es (auch) einen Hardwarebug, finde aber den Link
>nicht mehr...

Gesucht habe ich davor schon. Nur nichts gefunden, was mir weiterhilft. 
In den entsprechenden Threads wird empfohlen, einen Timeout-Counter 
laufen zu lassen und bei zu langer Inaktivität des Busses den Bus zu 
"reseten" sozusagen. Ich denke aber, dass die von mir erwähnten 
TIMEOUT-Bits des XMega dafür sorgen sollten, was diese bei mir aber 
nicht tun. Drum habe ich fragen wollen, was da falsch sein könnte.

Was den Code betrifft, es werden die Softwaretreiber von Atmel benutzt. 
Sie wurden ergänzt durch die folgende Funktion, die auf die 
Treiberfunktionen zurückgreift und die aus dem Hauptprogramm aufgerufen 
wird:
1
bool ReadDigitalIO(TWI_Master_t *twi,uint8_t *input)
2
{
3
    uint8_t command=0;
4
5
    command = TWI_PCA_IN_PORT_0;
6
    while (twi->status != TWIM_STATUS_READY); //Wait until transaction is complete.
7
8
    TWI_MasterWriteRead(twi,TWI_SLAVE_1,&command,1,1);
9
    while (twi->status != TWIM_STATUS_READY); //Wait until transaction is complete.
10
    input[0]=~twi->readData[0];
11
 
12
    return true;
13
}


Das Programm bleibt hängen an der Zeile
while (twi->status != TWIM_STATUS_READY);
nachdem TWI_MasterWriteRead aufgerufen wurde.

von GG (Gast)


Lesenswert?

Hallo,

wie kann eien externe Spannung von 24 Volt mit den Prozessor in 
Verbindung kommen?

Opto's trennen doch die hohe Spannung von der eigentlichen 
Betriebsspannung (z.B 3,3 Volt).

Beim Senden über den Prozessor werden die Led der Opto mit ca. 3 Volt 
versorgt. In der Gegenrichtiung hängen die die Led auf der 24 
Volt-Seite. Das  Aus-und Einschalten der 24 Volt Spannung darf doch die 
I2C-Übertragung nicht stören.

Gruß GG

von Peter D. (peda)


Lesenswert?

noips schrieb:
> while (twi->status != TWIM_STATUS_READY);

Du solltest zuerst das Interruptbit testen, d.h. ob eine I2C-Aktion auf 
Behandlung wartet.
Erst dann kannst Du den Status auslesen. Du mußt dann jeden Status 
behandeln, da durch Störimpulse auf dem Bus jeder Status möglich ist.
Nur einen bestimmten Status zu erwarten, ist daher ne ganz schlechte 
Idee.

Z.B. kann der Master high senden, aber ein Störimpuls low anlegen und 
dann geht der Master in den Arbitration-Lost-Status.


Peter

von noips (Gast)


Lesenswert?

>Das  Aus-und Einschalten der 24 Volt Spannung darf doch die I2C-Übertragung 
>nicht stören.

Das sehe ich ja auch so, darum verstehe ich nicht warum die Störung 
auftritt. Aber nicht das ist das eigentliche Problem. Die Folge der 
Störung kann man ja beseitigen, wenn man den Bus wieder in Bereitschaft 
zurücksetzt.


@  Peter Dannegger
In den Beispiel-Codes von Atmel wird es aber genau so gemacht. Es wird 
eine I2C-Übertragung ausgelöst und danach wird mit while gewartet, bis 
der Stauts wieder READY ist. Erst dann führt man das Programm weiter 
aus. Die anderen möglichen Zustände am Bus verden durch Interrupts und 
die in der Treiber-Software von Atmel vorhandenen Interrupt-Handler 
behandelt.

von Peter D. (peda)


Lesenswert?

noips schrieb:
> In den Beispiel-Codes von Atmel wird es aber genau so gemacht.

Beispielcodes sollen immer nur das Prinzip verdeutlichen.
Niemand bei Atmel oder einem anderen IC-Hersteller wird Dir garantieren, 
daß sie auch praxistauglich sind.

Ich kenne die XMega nicht, ich benutze die ATmega.
Und da habe ich ne Switch-Anweisung im I2C-Interrupt, die alle 32 
möglichen Status-Case behandelt.

Zusätzlich habe ich noch ein Timeout, was das I2C kurz mal abschaltet, 
falls es sich richtig verklemmt hat (die ATmega haben leider nen bösen 
Multimaster-Bug).


Peter

von wt (Gast)


Lesenswert?

hast du auf die IIC Leitungen mit dem Oszi geschaut. Vielleicht ist es 
doch die EMB.

von noips (Gast)


Lesenswert?

wt schrieb:
> hast du auf die IIC Leitungen mit dem Oszi geschaut. Vielleicht ist es
> doch die EMB.

Ähm, was ist die EMB?

von noips (Gast)


Lesenswert?

Kennt vielleicht noch jemand dieses Problem beim XMega und könnte mir 
einen Tipp geben!

von noips (Gast)


Lesenswert?

Ich versuche jetzt seit Stunden dem Problem auf den Grund zu gehen. 
Dabei scheint der XMega sich nicht immer so zu verhalten, wie es im 
Manual beschrieben ist. Vielleicht hat jemand ähnliche Sachen bei 
XMega-TWI-Modul schon beobachtet. Wäre sehr dankbar, wenn sich jemand 
meldet.

von Peter D. (peda)


Lesenswert?

noips schrieb:
> Ich versuche jetzt seit Stunden dem Problem auf den Grund zu gehen.

Wie?
Versuch mal systematisch vorzugehen.

Wenn er hier hängt:
> while (twi->status != TWIM_STATUS_READY);
Also nie "TWIM_STATUS_READY" wird.
Was steht dann in "twi->status"?
Was bedeutet es?


Peter

von noips (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Wie?
> Versuch mal systematisch vorzugehen.

Das versuche ich ja auch!

Ich verwende die von Atmel in Apl.-Notes vorgeschlagene 
TWI-Treibersoftware TWI_MASTER_DRIVER.c (mit der dazugehörigen 
.h-Datei). Da gibt es eine Interrupt-Handler-Funktion, die prüft, ob 
Master-Write-Interrupt oder Master-Read-Interrupt aufgetreten ist und 
ruft dementsprechend entweder den Write-Interrupt-Handler oder den 
Read-Interrupt-Handler. In diesen Handlern wird Schreib- bzw. 
Lesevorgang gestartet und wenn alles geschrieben/gelesen wurde wird eine 
STOP-Condition gesendet und twi->status auf READY gesetzt, aber davor 
wird geprüft, ob Arbitration-Lost, Buss-Error oder Not-Acknoledge (vom 
Slave) aufgetreten ist (zu jedem dieser drei Fälle gibt es Bits in einem 
Register). Ist einer der Fälle aufgetreten, so wird (neben einigen 
anderen Dingen) durch Setzen von CMD-Bits das Senden einer 
STOP-Condition vom Master veranlasst. Laut Manual, muss die TWI-Logik im 
XMega bei Erkennen einer STOP-Condition auf dem Bus, das TWI-Modul aus 
den Zuständen BUSY oder OWNER wieder in den Zustand IDLE zurückholen. 
Ich sehe im Debugger, wie die CMD-Bits auch gesetzt werden und folglich 
auch STOP-Condition auch gesendet wird, aber nicht immer geht das 
TWI-Modul in den IDLE-Zustand über. twi-status wird aber immer auf READY 
in der Software gesetzt. Wenn dan der nächste Schreibvorgang durch 
Software ausgelöst wird, kommt kein Interrupt mehr, vermutlich weil das 
TWI-Modul nicht in IDLE ist. Dann wartet die Software vergeblich auf die 
Bedingung (twi->status = TWIM_STATUS_READY), denn damit diese Bedingung 
eintritt, muss ein Interrupt-Handler aufgerufen werden.

von wt (Gast)


Lesenswert?

immer noch nicht gelöst? vielleicht doch EMB (Elektromagnetische 
Bombe):)

von Dominik M. (lauso)


Lesenswert?

Hallo ich kenne das Problem und habe damit auch zu kämpfen gehabt.
1
while (twiMaster.status !=TWIM_STATUS_READY)
2
        {// Warte bis Transaction Fertig         }
Hier wird gewartet bis die Kommunikation mit dem angeschlossen Slave 
beendet ist.
Sofern nicht dieser Interrupt auslöst
1
ISR(TWIE_TWIM_vect)
2
    {
3
      TWI_MasterInterruptHandler(&twiMaster);
4
    }
Auch wenn dies wie gewünscht untergebracht wird heist es noch lange 
nicht das es klappt wenn nicht auf den Interrupt Vector geschrieben 
wird.
1
// The interrupt vectors will be placed at the start of the Application FLASH section
2
n=(PMIC.CTRL & (~(PMIC_RREN_bm | PMIC_IVSEL_bm | PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm ))) |
3
    PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm | TWIE_TWIM_vect;
Als ich das alles eingefügt hatte klappte es.
Sollte es grundsätzlich bei Dir funktionieren gibt es zwei Möglichkeiten
1. Watchdog
2. T/C Interrupt zählen und in der While Schleife eine bedingung 
schaffen mit der aus der Schleife gesprungen werden kann.
Allerdings muß dann der TWI neu eingerichtet und gestartet werden.
Ich hoffe es war hilfreich.

von Rolf G. (rogeh)


Lesenswert?

noips schrieb:
> Peter Dannegger schrieb:
>> Wie?
>> Versuch mal systematisch vorzugehen.
>
> Das versuche ich ja auch!
>
> Ich verwende die von Atmel in Apl.-Notes vorgeschlagene
> TWI-Treibersoftware TWI_MASTER_DRIVER.c (mit der dazugehörigen
> .h-Datei). Da gibt es eine Interrupt-Handler-Funktion, die prüft, ob
> Master-Write-Interrupt oder Master-Read-Interrupt aufgetreten ist und
> ruft dementsprechend entweder den Write-Interrupt-Handler oder den
> Read-Interrupt-Handler. In diesen Handlern wird Schreib- bzw.
> Lesevorgang gestartet und wenn alles geschrieben/gelesen wurde wird eine
> STOP-Condition gesendet und twi->status auf READY gesetzt, aber davor
> wird geprüft, ob Arbitration-Lost, Buss-Error oder Not-Acknoledge (vom
> Slave) aufgetreten ist (zu jedem dieser drei Fälle gibt es Bits in einem
> Register). Ist einer der Fälle aufgetreten, so wird (neben einigen
> anderen Dingen) durch Setzen von CMD-Bits das Senden einer
> STOP-Condition vom Master veranlasst. Laut Manual, muss die TWI-Logik im
> XMega bei Erkennen einer STOP-Condition auf dem Bus, das TWI-Modul aus
> den Zuständen BUSY oder OWNER wieder in den Zustand IDLE zurückholen.
> Ich sehe im Debugger, wie die CMD-Bits auch gesetzt werden und folglich
> auch STOP-Condition auch gesendet wird, aber nicht immer geht das
> TWI-Modul in den IDLE-Zustand über. twi-status wird aber immer auf READY
> in der Software gesetzt. Wenn dan der nächste Schreibvorgang durch
> Software ausgelöst wird, kommt kein Interrupt mehr, vermutlich weil das
> TWI-Modul nicht in IDLE ist. Dann wartet die Software vergeblich auf die
> Bedingung (twi->status = TWIM_STATUS_READY), denn damit diese Bedingung
> eintritt, muss ein Interrupt-Handler aufgerufen werden.

Hallo Zusammen,

ich habe genau das hier beschriebene Problem. Wurde das inzwischen 
gelöst, bzw. gibt es einen Workaround?
Ich verwenden den TWI_MASTER_DRIVER.c im Originalzustand. Eine Zeit lang 
läuft die Übertragung einwandfrei, dann kommt kein Write Interrupt mehr, 
obwohl das WIF Flag gesetzt ist.
Ich verwende Atxmega192A3.

@noips wie bust du weiter gekommen?

Gruß
Rolf

von Henrik E. (Gast)


Lesenswert?

Hallo,

hatte auch das Problem, dass die SCL Leitung dauerhaft LOW war, wenn ich 
folgende Schleife benutzt habe, um sicher zu gehen, dass die 
Kommunikation beendet ist.
1
while (twiMaster.status != TWIM_STATUS_READY) {
2
/* Wait until transaction is complete. */
3
}

Habe jetzt bei der Initialisierung des TWI-Moduls das Interruptlevel auf 
HIGH gesetzt und es funktioniert jetzt, allerdings kann ich nicht 
erklären warum.

Viele Grüße
Hendrik

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.