Forum: Mikrocontroller und Digitale Elektronik stm32 Cortex I2C : Master zieht SCL auf Masse


von Sylvia H. (sandy)


Lesenswert?

Hi,
hat jemand schon einmal folgendes Phänomen erlebt:
Beim Versuch eine I2C2 Kommunikation mittels eines Cortex Stm32f103 auf 
zu bauen liegen SCL und SDA beide auf +3,3V, innerhalb eines bruchteils 
einer Sekunde (aber für das auge noch schön sichtbar) zieht der Cortex 
die Clockleitung auf Masse.
Elektrotechnisch hat die SCl Leitung keine Verbindung zur Masse, beide 
Leitungen (SCA und SDL) sind über einen 10 k Ohm Widerstand auf +3,3V 
gelegt.
Hier meine Initialisierung:
1
/* GPIOB clock enable */
2
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
3
4
  /* I2C2 clock enable */
5
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
6
    /* I2C1 SDA and SCL configuration */
7
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;
8
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
9
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
10
    GPIO_Init(GPIOB, &GPIO_InitStructure);
11
12
    //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
13
    GPIO_Init(GPIOB, &GPIO_InitStructure);
14
15
    /* Enable I2C2 reset state */
16
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, ENABLE);
17
    /* Release I2C2 from reset state */
18
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE);
19
20
/* I2C1 and I2C2 configuration */
21
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
22
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
23
  I2C_InitStructure.I2C_OwnAddress1 = OwnAddress1;
24
  // I2C_InitStructure.I2C_OwnAddress1 = 0x00;
25
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
26
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
27
  I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;
28
  I2C_Init(I2C1, &I2C_InitStructure);
29
30
  I2C_InitStructure.I2C_OwnAddress1 = OwnAddress2;
31
  I2C_InitStructure2 = I2C_InitStructure;
32
  I2C_Init(I2C2, &I2C_InitStructure);
33
34
   // I2C Peripheral Enable
35
       I2C_Cmd(I2C2, ENABLE);
36
  /* enable genarall call detection */I2C2->CR1 |= CR1_ENGC_Set;

hat jemand eine Idee, warum der Cortex als Mater die SCL Leitung auf 
Masse zieht?

von Ralf (Gast)


Lesenswert?

Ich arbeite mich grad in die NxP LPC11xx/13xx/17xx Reihe ein, dort ist 
es so, dass wenn das I2C-Interface für Multimaster konfiguriert ist die 
Clockleitung solange auf Masse zieht wie das SI-Flag 
(I2C-Interrupt-Flag) aktiv ist. Ich würde also mal im Datenblatt zu 
deinem Controller schauen, ob er das sog. Clock-Stretching ebenfalls auf 
diese Weise macht und entsprechend untersuchen, ob er ungewolltes 
Clock-Stretching macht.

Ralf

von Thomas (Gast)


Lesenswert?

Verstehe Dein Problem nicht ganz, denn :
- der I2C Bus des STM hat natürlich Massebezug oder wie schliesst Du 
einen Slave Baustein an ?

Die Intialiserung über die Firmawarecalls scheint in Ordnung zu sein. 
Ich benutze den I2C Bus allerdings im DMA/Interruptbetrieb.

Gruss

von Sylvia H. (sandy)


Lesenswert?

Thomas schrieb:
> - der I2C Bus des STM hat natürlich Massebezug oder wie schliesst Du
> einen Slave Baustein an ?

ich wollt ausdrücken, das meine SCL Leitung kein Kurzschluss auf Masse 
hat.

Ich habe versuchsweise die Pin Initialisierung mal hinter die I2C 
Structure Initialisierung gesetzt, jetzt bleibt SCL auf +3,3 V, dafür 
wird aber nichts mehr gesendet.......

von (prx) A. K. (prx)


Lesenswert?

Sylvia H. schrieb:

> Beim Versuch eine I2C2 Kommunikation mittels eines Cortex Stm32f103 auf
> zu bauen liegen SCL und SDA beide auf +3,3V, innerhalb eines bruchteils
> einer Sekunde (aber für das auge noch schön sichtbar) zieht der Cortex
> die Clockleitung auf Masse.

Nicht grad für das was man ein Sekundenbruchteil nennt, sondern eher im 
Mikrosekundenbereich, aber erlebt habe ich das schon. Nämlich denn, wenn 
zuerst die SCL/SDA-Pins als AF-OD konfiguriert werden und danach die 
I2C-Unit initialisiert wird. Dann sind in der Zwischenzeit die Pins auf 
"low".

Abhilfe: Erst I2C Initialisieren, dann die Pins konfigurieren. Hat bei 
mir funktioniert.

von Sylvia H. (sandy)


Lesenswert?

also die GPIO Init wieder an den Anfang setzen, nun sendet der Master 
wieder.
Aber danach ist der Clock auf 0.
Soll das clock Streching sein? Laut Datenblatt verstehe ich das so, dass 
der Master BEVOR einer Schreibaktion mit SCL auf low auf ein event 
wartet.
Bei mir ist der Clock aber NACH der Schreibaktion auf low, der Master 
wird aber von mir nicht in den receiver mode gesetzt....


SDA/SCL line control
● If clock stretching is enabled:
– Transmitter mode: If TxE=1 and BTF=1: the interface holds the clock 
line low
before transmission to wait for the microcontroller to read SR1 and then 
write the
byte in the Data Register (both buffer and shift register are empty).
– Receiver mode: If RxNE=1 and BTF=1: the interface holds the clock line 
low after
reception to wait for the microcontroller to read SR1 and then read the 
byte in the
Data Register (both buffer and shift register are full).

von Sylvia H. (sandy)


Lesenswert?

A. K. schrieb:
> Abhilfe: Erst I2C Initialisieren, dann die Pins konfigurieren. Hat bei
> mir funktioniert.

upps, zu spät gelesen...
hab ich versucht, aber dann hat der Master gar nichts mehr gesendet 
(siehe oben).....

von Mike R. (thesealion)


Lesenswert?

Sylvia H. schrieb:
> Bei mir ist der Clock aber NACH der Schreibaktion auf low, der Master
> wird aber von mir nicht in den receiver mode gesetzt....

Das passiert ab ehesten, wenn du Kommunikation nicht korrekt abläuft 
(Slave antwortet nicht oder die Programmierung des Masters stimmt 
nicht).

Hast du ein Scope und kannst SDA und SCL mal aufnehmen? Ansonsten wird 
SCL auch auf Masse gezogen wenn du den Bus nur initialisierst und nichts 
sendest?

Mike

von Sylvia H. (sandy)


Lesenswert?

Mike S. schrieb:
> Hast du ein Scope und kannst SDA und SCL mal aufnehmen? Ansonsten wird
> SCL auch auf Masse gezogen wenn du den Bus nur initialisierst und nichts
> sendest?

wenn nur inititalisiert wird bleiben SDA und SCL auf 3,3V
Wenn ich etwas sende, dann erscheinen die Bytes auf auf dem Bus (kann 
ich mit dem Advaark sehen), danach zeigt mir mein OSZI das SDA auf 3,3V 
und SCL auf Masse liegt...

von Sylvia H. (sandy)


Lesenswert?

ich bleibe auch nicht in irgendeiner Methode hängen, weil mein 
partnerbord nicht sein ACK schickt,
das Senden wird abgeschlossen.
Danach ist der Bus tot, weil SCL auf Masse liegt.

von Thomas (Gast)


Lesenswert?

Aus den verfügbaren Informationen ist Dein Phänomen nicht erklärbar. Ich 
rate Dir, wenn Du schnell zu einem Ergebnis kommen willst, den I2c Bus 
Treiber von STM (siehe Application) zu verwenden.
Vorher solltest Du aber sicherstellen, ob nicht Dein Slave 
möglicherweise durch Clockstretching diesen Effekt erzeugt.

von Mike R. (thesealion)


Lesenswert?

Das dein Programm hängen bleibt sagt ja auch keiner, aber ich hab die 
Erfahrung gemacht, das die I2C Hardware von ST gerne mal hängen bleibt 
wenn sie nicht korrekt angesprochen wird. Und das ist zum Teil nicht 
einfach :)

von Sylvia H. (sandy)


Lesenswert?

Thomas schrieb:
> Aus den verfügbaren Informationen ist Dein Phänomen nicht erklärbar. Ich
> rate Dir, wenn Du schnell zu einem Ergebnis kommen willst, den I2c Bus
> Treiber von STM (siehe Application) zu verwenden.

die benutze ich schon..

> Vorher solltest Du aber sicherstellen, ob nicht Dein Slave
> möglicherweise durch Clockstretching diesen Effekt erzeugt.
das habe ich mir auch schon gedacht, das es dem Slave vielleicht zu 
schnell geht. Das Slave Board arbeitet mit einem  ATXMEGA16D4 drauf. 
Daher habe ich mal die Pingeschwindigkeit von GPIO_Speed_50MHz auf 
GPIO_Speed_10MHz geändert, und die I2C geschwindigkeit auf 100 kHz 
eingestellt.
Hat aber leider nichts gebracht :(

von Sylvia H. (sandy)


Lesenswert?

es ist eindeutig der ATXMEGA16 Slave, der die CLK Leitung auf Masse 
zieht.
Ich habe das herausgefunden, indem ich einmal nur den Advaark auf dem 
I2C bus habe mitlauschen lassen, da wurde SCL nach dem Master senden 
nicht auf Masse gezogen.
Gibt es da Erfahrungswerte, hat jemand schon einmal ähnliche Probleme 
bei der I2c Kommunikation zwischen einem ATXMEGA und einem Cortex 
gehabt?

von Sven Wagner (Gast)


Lesenswert?

Sylvia H. schrieb:
> Daher habe ich mal die Pingeschwindigkeit von GPIO_Speed_50MHz auf
> GPIO_Speed_10MHz geändert
Das verändert nur die Stärke der Ausgangstreiber und damit die 
Flankensteilheit. Für I2C sollte das langsamste eingestellt werden.

Grüße
Sven

von (prx) A. K. (prx)


Lesenswert?

Ok, hab noch mal in meinem Code gestöbert. Das bisher war leicht 
verfälscht aus dem Gedächnis. Die bei mir implementierten Reihenfolge 
ist:
-1- I2C Takt einschalten, dies muss vor den Pins kommen.
-2- Pins konfigurieren
-3- I2C konfigurieren.
I2C Reset ist bei mir nur als Software-Reset über CR1 drin.

von Sylvia H. (sandy)


Lesenswert?

die Initialisierungsreihenfolge ist egal, das Problem bleibt jedes Mal 
das gleiche. Da auf dieser Seite keine Antwort mehr kam, habe ich das 
problem auf einer neuen Seite noch mal mit OSZI Bildern geschildert:
Cortex I2C zu kurze Impulsdauer
bitte A.K. schau doch dort mal vorbei, du hast doch immer so gute Ideen 
:)

von Sylvia H. (sandy)


Lesenswert?

irgendwie funktionier der oben genannte Link nicht beim draufklicken, 
aber der Thread heisst "Cortex I2C zu kurze Impulsdauer"

von Thomas (Gast)


Lesenswert?

Wenn Du einen uC als Slave hast, dann kannst Du damit rechnen, dass er 
das Clockstretching bei Uebertragungsraten von 100kHz oder mehr benutzt. 
Setzt Deinen I2C Clock mal spasseshalber auf 1kHz und schau was 
passiert.

von Sylvia H. (sandy)


Lesenswert?

Thomas schrieb:
> Setzt Deinen I2C Clock mal spasseshalber auf 1kHz und schau was
> passiert.

der Cortex macht irgendwie nichts langsameres als 10 khz, auch wenn ich 
ihn 1kHz initialisiere, sendet er mit 10 Khz. seltsam....
Aber am Problem ändert sich auch nichts, der ATXMEGA zieht trotzdem SCL 
auf Masse

von (prx) A. K. (prx)


Lesenswert?

Sämtliche Errata-Sheets schon durchforstet?

von Sylvia H. (sandy)


Lesenswert?

A. K. schrieb:
> Sämtliche Errata-Sheets schon durchforstet?
jop, da findet man nur Erratas bezügl. der Empfangsfunktion und einer 
repeated Start condition, aber nichts, was man machen kann, wenn das 
Partnerboard aus der Kommunikation aussteigt...

von (prx) A. K. (prx)


Lesenswert?

Ich meinte beide Seiten...

von Sylvia H. (sandy)


Lesenswert?

ATXMEGA hat ein kurzes Erratasheet, da steht nur " no known errata" 
drinn.....

von Sylvia H. (sandy)


Angehängte Dateien:

Lesenswert?

Das Problem liegt meiner Meinung nach darin, das der Cortex eine zu 
kurze Startbedingung sendet:
Während der ATXMEGA seine Startbedinugn 6us auf dem Bus stehen hat, 
liefert der Cortex nur 840 ns lang ein Startsignal.
Ausserdem steht zwischen den einzelnen Bytes SDL beim Cortex auch zu 
kurz an. (nur 440 ns, während der ATXMEGA 7,8us SDL auf High hält.
Wie kann ich den Cortex dazu bewegen, die Startbedinung länger zu 
senden, und SDL länger auf High zu halten?
Ich habe es schon mit einem delay nach dem senden der Startbedinung und 
vor dem senden der Slaveadresse versucht, aber das nützt nichts. Da wird 
nur etwas später die Adresse versendet, aber die Startbedingung bleibt 
so kurz.
Hat jemand eine Idee?

von (prx) A. K. (prx)


Lesenswert?

I2C Spec. 2.1 verlangt für SDL=>SCL in der Start Condition bei 400KHz 
für t(HD,STA) mindestens 600ns. Wenn das diese 440ns sind, dann ist das 
offiziell etwas zu wenig. Auf dem Bild ist dies jedoch nicht eindeutig 
erkennbar. Dass der AVRX scheint sich hier an die 4µs des 100KHz Betrieb 
zu halten.

von (prx) A. K. (prx)


Lesenswert?

Im oben gezeigte Code wird der Standard-Mode (<= 100KHz) spezifiziert:
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
Die Screenshots sind aber von 400KHz. Welcher Code passt zu den Bildern?

von Sylvia H. (sandy)


Lesenswert?

es ist auf jeden fall ein 400 kHz Modus erwünscht, die Bilder zeigen 
diesen Mode auch

A. K. schrieb:
> Im oben gezeigte Code wird der Standard-Mode (<= 100KHz) spezifiziert:
> I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

ist das nicht die Einstellung für 400 Khz? Ansonsten gibt es doch nur 
noch die Einstellung  für den SMBus mit seinen 100 kHz....

A. K. schrieb:
> I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

dies sagt, dass das Verhältnis von Impulsdauer/Impulspause des SCK 
Signales 1/2 sei soll, ansosnten gibt es nur noch die Einstellung 9/16, 
aber das bezieht sich doch auch alles auf den 400kHz fast Mode?

von (prx) A. K. (prx)


Lesenswert?

Sylvia H. schrieb:

>> Im oben gezeigte Code wird der Standard-Mode (<= 100KHz) spezifiziert:
>> I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
>
> ist das nicht die Einstellung für 400 Khz? Ansonsten gibt es doch nur
> noch die Einstellung  für den SMBus mit seinen 100 kHz....

Die Lib ist nicht mein Fall, aber ich könnte mir vorstellen, dass sich 
dies in Bit 15 vom CCR übersetzt, das zusammen mit Bit 14 zwischen 
Standard (100Khz) und Fast Mode (400KHz) differenziert.

Bit 15 F/S: I2C master mode selection
0: Standard Mode I2C
1: Fast Mode I2C

I2C jedenfalls kennt diese Modi:
Standard Mode    100 kHz
Fast Mode        400 kHz
Fast Mode Plus   1 MHz
High Speed Mode  3,4 MHz

von Sylvia H. (sandy)


Lesenswert?

A. K. schrieb:
> I2C Spec. 2.1 verlangt für SDL=>SCL in der Start Condition bei 400KHz
> für t(HD,STA) mindestens 600ns.

woher hast du diese Info? Ich finde in der I2C Spec 2.1 von Phillips 
Semiconductors auf den Tabellen S.31ff nur Informationen über die 
minimale Länge einer repeated start condition....

von (prx) A. K. (prx)


Lesenswert?

Sylvia H. schrieb:

> woher hast du diese Info? Ich finde in der I2C Spec 2.1 von Phillips
> Semiconductors auf den Tabellen S.31ff nur Informationen über die
> minimale Länge einer repeated start condition....

Kreative Interpretation. Das "(repeated)" in Klammern habe ich so 
verstanden, dass dieser Wert sowohl für die Start Condition als auch für 
die Repeated Start Condition gilt.

von (prx) A. K. (prx)


Lesenswert?

PS: Ich bin kein Freund der Lib und habe oft keine Doku davon parat. Was 
immer die tut - der Controller interessiert sich einen Dreck für die 
Lib, der kümmert sich nur um seine Steuerregister und nur die sind in 
dessen Doku aufgeführt.

Wenn man solche Problem hat, dann sollte man immer einen Blick auf die 
Register werfen und deren Inhalt mit der Controller-Referenz überprüfen.

von Sylvia H. (sandy)


Lesenswert?

ok, neuer Versuch:
nachdem ich festgestellt habe, das sich der Cortex laut I2C 
Spezifikation normgerecht verhält, und ich der Meinung bin, wenn alles 
normgerecht ist, dann sollte doch auch ein ATXMEGA der Cortex 
verstehen.....
habe ich einen neuen Test gestartet:
Zwei Cortexe bekommen fast das gleiche Programm. Sie werden so 
programmiert, das sie beim Einschalten ein paar byte Infos auf den I2c 
bus werfen, und danach einer alle 2s, un der andere alle 5s ein paar 
bytes auf den General Call bus legen.
Meine Beobachtung:
Ein Board alleine hat keine Probleme seine Daten zu senden. Stecke ich 
das andere Board an den Bus gibt es entweder eine totenstille mit SDA 
und SCL beide auf High, und manchmal eine totenstille mit SDA auf High 
und SCL auf Low. Welche beide Möglichkeiten auftreten ist 
zufallsbedingt.
Ziehe ich dann wieder ein Board ab, sendet das andere Board entweder 
gleich wieder seine Daten, oder muss kurz resetet werden, und wirft dann 
wieder alle gewünschten bytes auf den Bus.
Nun meine Frage:
kann es sein, das der Cortex nicht mit Multimaster zurechtkommt? Laut 
Datenblatt müsste er es eigentlich können....

von Sylvia H. (sandy)


Lesenswert?

ich korrigire:
wenn ein zweites Board an den Bus angeschlossen wird ist totenstille, 
wird es wieder abgezogen, muss das verbleibende Board auf jeden Fall 
resettet werden, damit es wieder annfängt zu senden

von (prx) A. K. (prx)


Lesenswert?

Ich habe das grad nicht genau drauf, aber heisst Multimaster mit general 
call nicht auch, dass jeder Master auch als Slave reagieren muss?

Jedenfalls wäre hier wohl interessant, in welchen Zustand im Falle eines 
Falles nicht nur der Bus ist, sondern insbesondere auch die beteiligten 
I2C-Controller.

von (prx) A. K. (prx)


Lesenswert?

Auf welche Adressen reagiert dein Code denn? Wenn die I2C-Unit einer 
Node sich als Slave angesprochen fühlt, egal ob per GC oder explizit 
adressiert, und ihre Software darauf nicht passend reagiert, dann 
landest du beim STM32 per default im clock stretching und bleibst darin 
hängen, weil die Hardware darauf wartet, dass die Software entsprechend 
reagiert.

Wenn diese Software nicht per Interrupt arbeitet, dann könnte eine 
Kollision zwischen dem Sendeversuch als Master und einer zeitlich 
passend einlaufenden start condition einer anderen Node leicht einen 
deadlock hervorrufen.

Auch hier ist es wichtig, zu erfahren welcher Zustand beiderseits 
vorliegt, in dem Fall auch der Zustand der Software. Allein über die 
beiden Busleitungen wirst du das nicht erfahren.

von Sylvia H. (sandy)


Lesenswert?

A. K. schrieb:
> Ich habe das grad nicht genau drauf, aber heisst Multimaster mit general
> call nicht auch, dass jeder Master auch als Slave reagieren muss?

jop, so ist es

A. K. schrieb:
> Auf welche Adressen reagiert dein Code denn? Wenn die I2C-Unit einer
> Node sich als Slave angesprochen fühlt, egal ob per GC oder explizit
> adressiert, und ihre software state machine darauf nicht reagiert, dann
> landest du beim STM32 per default im clock stretching und bleibst darin
> hängen, weil die Hardware darauf wartet, dass die Software entsprechend
> reagiert.

Meine Boards haben das eine die Adresse 0xa1 und das andere 0xa2. Aber 
die werden nicht angesprochen, die ganze Kommunikation muss über den 
General Call 0x00 laufen.
Was eine software state machine ist kann ich mir im Moment nicht 
vorstellen, hab den ganzen Tag angestrengt nachgedacht und gearbeitet, 
die Luft ist raus.......
Aber morgen früh bin ich wieder voll da!!!!

A. K. schrieb:
> Wenn diese state machine nicht per Interrupt arbeitet, dann könnte eine
> Kollision zwischen dem Sendeversuch als Master und einer zeitlich
> passend einlaufenden start condition einer anderen Node einen deadlock
> hervorrufen.

noch ne NVIC zum programmieren? was anderes als
1
NVIC_SetPriority(I2C1_EV_IRQn, 0x00);
2
  NVIC_EnableIRQ(I2C1_EV_IRQn);
3
4
  NVIC_SetPriority(I2C1_ER_IRQn, 0x01);
5
  NVIC_EnableIRQ(I2C1_ER_IRQn);
6
7
  NVIC_SetPriority(I2C2_EV_IRQn, 0x02);
8
  NVIC_EnableIRQ(I2C2_EV_IRQn);
9
10
  NVIC_SetPriority(I2C2_ER_IRQn, 0x03);
11
  NVIC_EnableIRQ(I2C2_ER_IRQn);

Wahrscheinlich hängen die Problem irgendwie mit diesem General Call 
zusammen.....

von (prx) A. K. (prx)


Lesenswert?

Sylvia H. schrieb:

> Wahrscheinlich hängen die Problem irgendwie mit diesem General Call
> zusammen.....

Nur ist der eigentlich ab Reset abgeschaltet und die Nodes müssten es 
ignorieren, es sei denn du (oder die Lib) schaltet es irgendwo ein.

Den Begriff software state machine hatte ich nicht sehr glücklich 
gewählt und auch korrigiert, weils eher eine hardware state machine mit 
softwareseitiger Reaktion darauf ist.

Jedenfalls gerät es angesichts des homöopathisch dosierten Codes oben 
zum Kaffeesatzlesen. Du solltest jetzt mal die Möglichkeit schaffen, 
heraus zu bekommen, in welchem Zustand sich die I2C-Units und deine 
Software zum Zeitpunkt der Hänger befinden. Sowas ist zentraler Punkt 
beim Debugging.

von Willi (Gast)


Lesenswert?

Sylvia H. schrieb:
> Meine Boards haben das eine die Adresse 0xa1 und das andere 0xa2.

Ich lese nur interessiert mit: sind Deine Adressen richtig gewählt? 0xa1 
ist nicht in Ordnung, da das Bit0 das RW-Signal widerspiegelt.

von (prx) A. K. (prx)


Lesenswert?

Sylvia H. schrieb:

> ATXMEGA hat ein kurzes Erratasheet, da steht nur " no known errata"
> drinn.....

Alles muss man selber machen. Hätte mich auch gewundert - so simpel sind 
die Xmegas denn doch nicht, als dass man das bugfrei zustande bekäme: 
Das Datasheet vom erwähnten ATXMEGA16D4 in der Version 12/10 erwähnt 28, 
und allein 5 davon betreffen das TWI.

von Sylvia H. (sandy)


Angehängte Dateien:

Lesenswert?

A. K. schrieb:
> Das Datasheet vom erwähnten ATXMEGA16D4 in der Version 12/10 erwähnt 28,
> und allein 5 davon betreffen das TWI.

Sorry, ich hatte wohl vergessen zu erwähnen, das es ein ATXMEGA16A4 ist, 
dort steht nichts im Errata....

A. K. schrieb:
> Nur ist der eigentlich ab Reset abgeschaltet und die Nodes müssten es
> ignorieren, es sei denn du (oder die Lib) schaltet es irgendwo ein.

Ich schalte den General Call bei der Initialisierung ein.

A. K. schrieb:
> Jedenfalls gerät es angesichts des homöopathisch dosierten Codes oben
> zum Kaffeesatzlesen.

Ich benutze die Angehängte Lib, der Rest ist ein wüster Code, da ich 
Libs von Kollegen, die den Code für ATXMEGA geschrieben hatten in 
Cortexsprache umsetzen musste....
Ich rufe in meiner main zuerst die Methode TWI_Init() twi_bus.c auf, 
dort befinden sich auch die IRQ Händler.
Danach wird die TWI_Main() Methode aus twi_main.c aufgerufen, dort wird 
ein Timer initialisiert, und eigendlich wird hier auch eine dynamische 
Adressvergabe gestartet, wenns dann endlich mal geht.....

danach wird in der Main mit
1
unsigned char bla[8] = { 0xFF, 0xFF, 0x33, 0x11, 0x22, 0x11, 0x33,
2
      0x44};
3
   TWI_Send(0x00, bla , 8, TWI_MESSAGE_getID);
4
   unsigned char blub[1]={0x08};
5
   TWI_Send(0x00, blub, 1, TWI_MESSAGE_nextID);
nochmal ein paar bytes auf per General Call auf den Bus geschickt
(TWI_Send() steht in twi_bus.c
Das wars, jetzt kommt die endlos while(1){} Schleife, ab hier  wird nur 
noch per Timer Interrupt jede 1,8s etwas an die Adresse 0x00 gesendet.

Ich weis, der Code ist chaotisch und absolut nicht sortiert, geschweige 
denn gekapselt. (deshalb habe ich bisher nur Auszüge gepostet, weil das 
extrem peinlich für mich ist)
Aber das ist nicht mein Werk, so würde ich nie einen Code schreiben. Ich 
muss mit dem Code eines Kollegen zurechtkommen. Wenn alles  ordentlich 
funktioniert, werde ich als aller erstes mal den Code in einen logischen 
Zusammenhang bringen.

A. K. schrieb:
> Du solltest jetzt mal die Möglichkeit schaffen,
> heraus zu bekommen, in welchem Zustand sich die I2C-Units und deine
> Software zum Zeitpunkt der Hänger befinden. Sowas ist zentraler Punkt
> beim Debugging.

Bisher ist das Programm immer mal  wieder beim Senden an der Stelle 
hängen geblieben, wo auf das Event 8_2, also das ACK des Slave auf ein 
Datum gewartet wird.
Meistens aber hängt das Programm dann in der while(1) Schleife, ohne 
irgendwelche Reaktionen zu zeigen. Es geht dann noch nicht einmal mehr 
in den Timer Interupt. Es hängt sich so gesehen einfach alles auf.....

Willi schrieb:
> Ich lese nur interessiert mit: sind Deine Adressen richtig gewählt? 0xa1
> ist nicht in Ordnung, da das Bit0 das RW-Signal widerspiegelt.

Das habe ich noch nicht berücksichtigt, muss das Thema mal nachlesen....

von (prx) A. K. (prx)


Lesenswert?

Sylvia H. schrieb:

> Ich benutze die Angehängte Lib, der Rest ist ein wüster Code, da ich
> Libs von Kollegen, die den Code für ATXMEGA geschrieben hatten in
> Cortexsprache umsetzen musste....

Mein Beileid für jeden, der diesen Code lesen muss.

Aber eines sehe ich trotzdem, nicht zuletzt weil ich das oben ja schon 
ähnlich befürchtet hatte: Der Code geht offenbar davon aus, dass er nur 
als I2C-Master verwendet wird. Wenn aber eine Node zusätzlich als Slave 
genutzt wird, sei es weil sie direkt adressiert wird, sei es weil sie 
auf GCs reagiert, dann muss das in der Software auch vorgesehen werden.

Dieser Code ist in einer Multimaster-Situation also nur einsetzbar, wenn 
grantiert werden kann, dass ein solcher Master nie als Slave 
angesprochen wird.

von (prx) A. K. (prx)


Lesenswert?

Sylvia H. schrieb:

> Bisher ist das Programm immer mal  wieder beim Senden an der Stelle
> hängen geblieben, wo auf das Event 8_2, also das ACK des Slave auf ein
> Datum gewartet wird.

Ich werde es jetzt noch ein einziges Mal versuchen, dann ist Schluss:

In welchem Zustand sind die I2C-Units wenn es hängt? Was du dazu 
benötigst ist zum gegebenen Zeitpunkt ein Register-Dump der I2C-Units. 
Obacht aber bei Registern, die beim Auslesen was auslösen.

Ebenso ist ein Trace der Statusregister der I2C-Units nützlich. Und wenn 
du diese Rohdaten hast, dann dekodierst du sie anhand der Reference und 
dann kannst nachvollziehen, was da abgeht und wo es schlussendlich 
hängt.

Das bedeutet natürlich auch, dass du Information aus dem Int Handler 
benötigst, denn da fällt das ja an. Lass dir was einfallen, wie du da 
rankommst.

von Sylvia H. (sandy)


Lesenswert?

A. K. schrieb:
> Mein Beileid für jeden, der diesen Code lesen muss.

ich weis, ich weis, ist mir auch peinlich genug......

A. K. schrieb:
> Aber eines sehe ich trotzdem, nicht zuletzt weil ich das oben ja schon
> ähnlich befürchtet hatte: Der Code geht offenbar davon aus, dass er nur
> als I2C-Master verwendet wird. Wenn aber eine Node zusätzlich als Slave
> genutzt wird, sei es weil sie direkt adressiert wird, sei es weil sie
> auf GCs reagiert, dann muss das in der Software auch vorgesehen werden.

Beim Cortex ist es so, dass im default Zustand der Slave Mode 
eingeschaltet ist. Möchte man als Master etwas machen, sendet man eine 
START condition, und danach ob man Master-Transmitter oder 
Master-Receiver sein möchte. Nach der Aktion schaltet das Interfache 
automatisch wieder in den Slave Mode.
Das heist, das man den Cortex weder als Master noch als Slave 
initialisiert, wie beim ATXMEGA oder bei all den anderen Controllern so 
üblich, sondern nur die standart Initialisierung braucht (Welcher TWI 
Kanal, welche TWI Geschwindigkeit, welche Adresse als Slave usw)
Der Rest wird von den Interruptroutinen erledigt.
Meine Slave Interruptroutine schreibt z.B. alle Bytes die Empfangen 
werden in den twi_buf[]. Dieser kann dann ausgewertet werden. Somit ist 
gewährleistet, das der Cortex, wenn er im Multi-Master Mode die Slave 
Rolle annimmt, auch mitbekommt, was auf dem Bus los ist.

Aber moment mal:
ist man als Empfänger im Multi-Master Mode eigentlich ein Slave-Receiver 
oder ein Master-Receiver?
Normalerweise müsste man doch dann ein Slave-Receiver sein, da ja der 
andere die Master Rolle übernommen hat, und etwas aktiv auf den Bus 
schickt....

von (prx) A. K. (prx)


Lesenswert?

Sylvia H. schrieb:

> ist man als Empfänger im Multi-Master Mode eigentlich ein Slave-Receiver
> oder ein Master-Receiver?

Wenn von einer anderen Node angesprochen, dann Slave. Ob Receiver oder 
nicht hängt von der Adresse ab, von Bit 0.

In diesem Multimaster müssen also im Handler alle möglichen Zustände 
berücksichtigt werden. Nicht bloss die paar, die ich gesehen habe.

von der A. (the_a)


Lesenswert?

Hallo Leute,

hab mich jett auch mal mit meienm STM32 Discovery hingesetzt und 
versucht i2c Master mit i2c Slae zu verbinden - beides auf der Platine.

Zumindest der Master-Code funktioniert- hab ich mit einem xMEga als 
Slave getestet.
Jetzt hängt aber immer mal meine slave Implementierung. Die Leitungen 
werden ziehmlich lange auf Low gezogen.

Eine Frage hab ich (sicher noch weitere): Im Manual steht bei Slave 
receiver wenn der eine Stop-Condition bekommt: EV4: STOPF=1, cleared by 
reading SR1 register followed by writing to the CR1 register
Aber was soll man denn ins Command register schreiben ohne irgend 
welchen Unsinn zu machen?

Habt ihr eine Master / Slave Bibliothek, die Ihr benutzt?

Die CMSIS Library ist ja wohl mit den Aufrufen standardisiert aber wohl 
nicht z.B in den Event Flags von I2C_GetLastEvent.

Danke schon mal.

Adib.

von Sylvia H. (sandy)


Angehängte Dateien:

Lesenswert?

der Adib schrieb:
> Habt ihr eine Master / Slave Bibliothek, die Ihr benutzt?

Die Angehängten Dateien stammen von STM "optimizedI2CExamples" Projekt, 
diese habe ich benutzt.
Aber ob sie funktionieren steht in den Sternen, bei mir gibts nur 
Probleme....

der Adib schrieb:
> Eine Frage hab ich (sicher noch weitere): Im Manual steht bei Slave
> receiver wenn der eine Stop-Condition bekommt: EV4: STOPF=1, cleared by
> reading SR1 register followed by writing to the CR1 register
> Aber was soll man denn ins Command register schreiben ohne irgend
> welchen Unsinn zu machen?

das steht in der angehängten stm32f10x_it.c in den Interruptroutinen

A. K. schrieb:
> In diesem Multimaster müssen also im Handler alle möglichen Zustände
> berücksichtigt werden. Nicht bloss die paar, die ich gesehen habe.

Meiner Meinung nach wurde in den Interruptroutinen alle Fälle 
berücksichtigt:
Master- und Slave-Receiver schreiben beide die ankommenden Bytes in 
twi_buf[], alle anderen Fälle sind nicht relevant, da ich gepollt auf 
den Bus schreiben

A. K. schrieb:
> Das bedeutet natürlich auch, dass du Information aus dem Int Handler
> benötigst, denn da fällt das ja an. Lass dir was einfallen, wie du da
> rankommst.

mach ich.......

von (prx) A. K. (prx)


Lesenswert?

Sylvia H. schrieb:

> Meiner Meinung nach wurde in den Interruptroutinen alle Fälle
> berücksichtigt:

Kann gut sein, dass ich den falschen Handler erwischt habe. Der gestern 
gepostetete Code ist ja ein ziemliches Durcheinander an auskommentieren 
und teilweise unlesbar formatiertem Code. Da wühl ich mich jetzt nicht 
durch.

> alle anderen Fälle sind nicht relevant, da ich gepollt auf
> den Bus schreiben

Und genau das kann zum Problem werden, weil Polling eine bestimmte 
Abfolge von Ereignissen voraussetzt, die die in einer 
Multimaster-Umgebung u.U. nicht gegeben ist.

von Sylvia H. (sandy)


Angehängte Dateien:

Lesenswert?

Ich möchte mit Eqlipse gerne die Register des Cortex auslesen. Dazu gehe 
ich in den Debugmodus und sehe die Register r0-r9 wie im Anhang zu 
sehen.
Nun weis ich, das die Register Boundary Adress für I2C2 laut Datenblatt 
0x4000 5800 - 0x4000 5BFF beträgt.
Die Passenden I2C2 Register liegen dann auf entsprechenden Offsetts 
höher.
Doch wie kann ich nun über diese Adressen herausfinden, was Eqlipse mir 
mit r0-r9 anzeigt? Nirgendwo finde ich eine Option heraus zu finden, auf 
welchen Adressen die Register r0-r9 anfangen.
Weis jemand, wie man die Adressen den Registern zuorden kann?

Ansonsten kann ich nur sehen, das mein cortex wie schon vorher erwähnt, 
bei der Abfrage nach Event 8_2 hängen bleibt...

von Sylvia H. (sandy)


Lesenswert?

hab was rausgefunden, falls es irgend jemand interessiert:

- In Eqlipse Debug Configurations  anklicken
- Im Reiter Debugger das Kästchen Verbose console mode aktivieren
- eine Text Datei erstellen, in der folgendes geschrieben wird:

set $I2C_CR1=(char *)0x40005800
display $I2C_CR1
- Auf diese Datei als GDB command file verweisen


danach erscheint beim Debuggen im Konsolenfenster folgender ausdruck:

~"1: $I2C_CR1 = 0x40005800 \"A\\004\""
1: $I2C_CR1 = 0x40005800 "A\004"~"\n"

So und nun fängt mein Problem an:
wenn ich den Wert "A\004"~"\n" aus dem ASCII Code in Hex Code umwandele, 
kommen ziemlich bescheuerte Daten für das Register raus....
Weis jemand, wie man die Zeile

1: $I2C_CR1 = 0x40005800 "A\004"~"\n"
Interpretiert?

von der A. (the_a)


Angehängte Dateien:

Lesenswert?

Also ich habe zZ eine Atollic Pro Testversion am Start. damit kann man 
alle Peripherie register ganz gut sehen.
Es sollte aber auch mit dem Eclipse Plugin: embsysregview funktionieren.

Was für eine Eclipse Version / Plugins verwendest du?
Das ARM-plugin funktioniert ja nicht mit dem neuen 3.7.

Adib.

von Sylvia H. (sandy)


Lesenswert?

der Adib schrieb:
> Was für eine Eclipse Version / Plugins verwendest du?

Version 3.6

von Sylvia H. (sandy)


Angehängte Dateien:

Lesenswert?

für die interessieten Mitleser :)
mit der angehängten Textdate als GDB Comand File kann man sich im 
Debugmode die Werte seiner Register anzeigen lassen.
Es steht ein dann in der Console der Registerwert in Dezimalform da.

von Sylvia H. (sandy)


Lesenswert?

soweit so gut,
nun habe ich alle Registerwerte, die ich im Falle des Aufhängens mir 
anschauen konnte.
Noch mal kurz zur Problemstellung:
Mein einzelner Master (A)  sendet lustig alle 2s 3 Bytes auf den Bus: F1 
30 29
gehen als General Call an die Adresse 0x00 auf die Reise.
Sobald ein anderer Master(B)  an den Bus angeschlossen wird,  springt 
(meistens) SCL auf low und erholt sich nicht mehr. Das „meistens“ 
bezieht sich darauf, dass wenn der Master B sofort etwas sendet SCL auf 
low geht, und wenn nicht, SCL auf High bleibt, aber dann trotzdem tote 
Hose auf dem Bus ist
hier nun die Registerwerte meines armen Sende-Masters A:

CR1: 0441 => Periphal enable =1, General Call enable = 1,ACK enable = 1
     Alles klar

CR2: 0124 => Interrupt enable = 1, Periphal Frequenz = 36 Mhz
     Da im 400 kHz Mode die Periphal Frequenz auf mindestens 4MHz 
gestellt  werden soll => Alles klar

OAR1: 4030 => Adressmode = 0 (=7 Bit Adresse), Adrese = 30 (hab mich mal 
in das Thema Adressen eingelesen, A1 ist Quatsch…..)
  Alles klar

OAR2:0, Alles Klar
Nun tauchen 2 Unterschiedliche Hängermöglichkeiten auf:
1.  SCL wird nicht auf Low gezogen, aber trotzdem bleibt der Cortex 
Hängen
Registeranzeigen:

DR:  41 => Das zweite  Byte wurde versucht ins  Datenregister  zu laden, 
danach blieb der Cortex hängen
SR2: 2=> Sr2 sagt, der Bus ist Busy
SR1 bleibt immer 0 das heißt dass TxE auf 0 immer sagt, das Data 
Register ist nicht leer, was auch wahr ist.
Wenn ich nun mit dem Debugger weitersteppe lande in meiner Timer 
Interruptroutine, aus der ich nicht wieder herauskomme.


2.  SCL wird auf Low gezogen
Registeranzeigen:
DR: 255 => Wo kommt auf einmal 0xff her,  die Zahl hab ich nie 
gesendet????
SR2:18 =>  General Call received = 1, OK, aber das reservierte Bit 3 
sollte eigentlich von der Hardware auf 0 gesetzt sein, ist es aber nicht
Auch hier lande ich beim weitersteppen in der Timer Interruptroutine und 
komme nicht wieder heraus

Soweit die Registerwerte…..
Ich stolpere über SR2 im 2. Fall. Warum zieht die Hardware nicht das Bit 
3 auf 0?
Könnte das der Grund für die Abstürze sein?
Aber im 1.Fall zeigt SR2 ja nur Busy an, da zieht die Hardware das Bit 3 
ja auch auf 0……
Seltsam,seltsam……

von Sylvia H. (sandy)


Lesenswert?

noch etwas:
nach dem Register CR2 ist nur das Error Interrupt enable Bit aktiviert.
Ich habe den Master ein Nachricht per Polling schicken lassen, dabei ist 
er ja hängengeblieben.
nach dem Verlust einer Arbitration schaltet die Hardware den CORTEX ja 
automatisch in den Slave-modus um. Müsste dann aber nicht auch das Event 
Interrupt Bit gesetzt sein?

ich dacht immer, wenn ich die NVIC so schreibe:
1
   NVIC_SetPriority(I2C2_EV_IRQn, 0x02);
2
  NVIC_EnableIRQ(I2C2_EV_IRQn);
3
4
  NVIC_SetPriority(I2C2_ER_IRQn, 0x03);
5
  NVIC_EnableIRQ(I2C2_ER_IRQn);
dann sind die Interrupts automatisch aktiv?

von Sylvia H. (sandy)


Lesenswert?

Hi Leute,
nachdem ich tagelange Tests durchgeführt, ungefähr 1000000 mal alle 
Register des Cortex kontrolliert, die I2C Spezifikation und das Cortex 
Datasheet (sammt Errata) auswendig kann ;=) ....
Hier die Lösung des Problemes:
Die Von STM bereitgestellte Library für "Optimized I2C Exmples" (an2824) 
weist folgende ausschlaggebende Fehler auf:

I2C2_ER_IRQHandler :
-  Es fehlte die Behandlung folgender Error-Flags: 
PECERR,TIMEOUT,SMBALERT
-  ARLO: Das Flag wurde zum Zurücksetzen mit einer falschen Maske 
verundet
-  BERR: obwohl im Errata steht, es müsste nur in einer „noisy 
environment“ folgendes programmiert werden, hat es sich herausgestellt, 
dass man dies auch in einer ganz normalen Umgebung machen muss: 
(übrigens, das Errata hat hier auch einen Fehler, man bräuchte wohl auch 
noch ein Errata zum Errata…..)
Wenn ein BERR auftritt, und das START Bit ist gesetzt, muss I2C resettet 
werden indem man in CR1 das SWRST Bit setzt. Aber Achtung, nicht 
vergessen I2C2 danach wieder zu Initialisieren! Sonst läuft I2C2 weiter, 
hat aber alle Register auf den Wert 0 gesetzt!!!!
Danach noch E2C Event Interrupts einschalten, und alles ist wieder ok:
1
/* If BERR = 1 */
2
  if ((SR1Register & 0x0100) == 0x0100) {
3
4
    I2C2->SR1 &= 0xFEFF;
5
6
    if((I2C2->CR1 & 0x0100)== 0x0100){ //is START bit set? 
7
       /* Peripheral under reset */
8
      I2C2->CR1 |= CR1_SWRST_Set;   //Errata S. 25
9
      I2C_LowLevelInit(I2C2);
10
       /* Enable the selected I2C interrupts */
11
       I2C2->CR2 |= I2C_IT_EVT;
12
    }
13
14
    SR1Register = 0;
15
  }

I2C_Master_BufferWrite:
Wenn der Master etwas auf den Bus schreiben möchte und die 
Startbedingung gesetzt hat, dann wartet er auf Event 5.
Sollte in dieser Wartezeit ein BERR auftreten, wartet er endlos, deshalb 
muss ein Timeout gesetzt werden. Kommt er in den Timeout, muss man hier 
auch wieder I2C2 reseten, neu Initialisieren und den Event Interrupt 
einschalten, genauso wie oben in der BERR = 1 Routine.

Dies sind die Fehler, die ich in der Firmaware gefunden habe. Was lerne 
wir daraus? Mann kann echt auf nichts mehr verlassen, noch nicht mal auf 
den Hersteller.....

Des Weiteren ist ein 10 kOhm pullup Widerstand wesentlich zu hoch.

Nun läufts auf dem I2C2 Bus !

Grüße von
Sylvia

von mha (Gast)


Lesenswert?

Hi.

Wäre cool, wenn du deine korrigierte Version hier online stellen 
könntest!

Vielen Dank!

von Sylvia H. (sandy)


Angehängte Dateien:

Lesenswert?

mach ich doch gerne,

Gruß
Sylvia

von leo (Gast)


Lesenswert?

Hallo Sylvia,

wie sieht Deine Applikation aus?
Wieso ARM mit ATXMEGA?

Vielen Dank und Gruß

von Sylvia H. (sandy)


Lesenswert?

Ich habe zwei Boards die miteiander über I2C Kommunizieren müssen:
Ein Board hat einen ATXMEGA16D4 drauf, an dem kann ich nichts ändern.
Das Andere läuft mit einem Cortex Stm32f103, den habe ich mit den 
geposteten Libs programmiert.

von leo (Gast)


Lesenswert?

Hallo Sylvia,

was für ein ATXMEGA-Boad ist das?

Vielen Dank und Gruß
Leo

von Sylvia H. (sandy)


Lesenswert?

Das ist kein Evaluation-Board, sondern ein selbst gebautes Board, mit 
einem ATXMEGA16 .

von leo (Gast)


Lesenswert?

Hallo Sylvia,

wie sieht die Aufgabenteilung zwischen ARM und XMEGA aus?

Vielen Dank und Gruß

von Sylvia H. (sandy)


Lesenswert?

Hallo leo,
Beide sind Master. Der ATXMEGA sendet all 10 sekunden ein 16 Byte 
grosses Datenpaket auf den Bus, welches der CORTEX per Interrupt 
empfangen, auswerten und weiterverarbeitet muss. Gleichzeitig soll es 
aber auch möglich sein, das der CORTEX dem ATXMEGA von sich aus ein 
Datenpaket zuschickt. Daher das Multimaster-System.

von leo (Gast)


Lesenswert?

Hallo Sylvia,

warum die XMEGA-Applikation separat?
Warum nicht die XMEGA-Applikation auch auf einem ARM?
Oder umgekehrt: Warum nicht die ARM-Applikation auf auch auf einem 
ATXMEGA?

Vielen Dank und Gruß
Leo

von Sylvia H. (sandy)


Lesenswert?

Hallo leo,

Das ist meine Bachelorarbeit:
Ein Rauchmeldermodul sendet alle 10 sekunden Daten auf den I2C Bus. 
Dieses Rauchmeldermodul ist bereits entwickelt und schon fest 
vorgegeben.
Ein von mir zu entwickelndes Modul soll diese Daten aufnehmen, und über 
Ethernet an einen Rechner zur weiteren Auswertung schicken.

Der Cortex arbeitet auf meinem Ethernet-Modul. Dieses Modul soll auch in 
der Lage sein, SPI und CAN Nachrichten ins Ethernet zu pusten. Des 
Weiteren braucht der Steuerungscontroller 2 x I2C Schnittstellen 
(Firmeninterne Gründe).
Daher der große Cortex für die Ansteuerung eines kleinen 
Ethernet-Controller.

Beide Module müssen in ein 19 Zoll Gehäuse eingpasst werden, und auch 
unabhängig voneinander arbeiten können. Daher müssen beide Aplikationen 
auf getrennten Boards laufen.

Gruß
Sylvia

von leo (Gast)


Lesenswert?

Hallo Sylvia,

was für ein ARM-Board setzt Du ein?

Vielen Dank und Gruß
Leo

von Sylvia H. (sandy)


Lesenswert?

Hallo Leo,
da gibt es kein ARM-Board, das ist alles selbstgebastelt.

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.