Forum: Mikrocontroller und Digitale Elektronik STM32 i2c error recovery Problem


von Michael A. (mukululul)


Angehängte Dateien:

Lesenswert?

Hallo,
ich versuche gerade meine i2c lese routine fehler tolerant zu machen. 
Genauer, nachdem ein Fehler passiert ist muss ein weiter Versuch möglich 
sein.

Also im prinzip ein read von i2c, da passiert ein Fehler, zB timeout 
Overrun/Underrun. Dann putzen der Fehler/Register, zur not ReInit der 
HW.

Im moment ist es so das ich auf einen Bus ohne Device aber mit pullups 
ein start schicke, das geht ok. Dann schicke ich die 7bit HW Adresse 
0xE0 mit Read, also 0xE1.
Danach warte ich bis die Adresse anliegt.
deviceAdress=0xE0;
/* Send START condition */
i2c_send_start_and_wait_for_rdy();
/* Send slave address */
i2c_send_7bit_address(I2C2, deviceAdress, I2C_READ);
/* Waiting for address is transferred. */
WAIT_EVENT_TO(!(I2C_SR1(I2C2) & I2C_SR1_ADDR));

Dies timed natürlich aus da kein Device angeschlossen ist.

Soweit so gut.

Jetzt wird die oben gezeigte Routine nochmal gerufen und diesmal gibts 
einen Hardfault.

Was auf SCL und SDA passiert sieht man in der angehängten Graphik.

Ich vermute mal das man nach so einem Fehler die HW irgendwie 
zurücksetzen.

Hat hierzu jemand einen Rat oder selbst schon Erfahrungen gemacht?

Gruss
Michael

von Michael A. (mukululul)


Angehängte Dateien:

Lesenswert?

Hier noch der Code den ich verwende. Im Prinzip ist es das 
OptimizedI2C/examples/src/I2CRoutines.c aber nur der Pollingmode.
Mit der Readroutine kann ich einen SE95D/LM75 ohne Probleme back2back 
lesen.

Kommentare, Anregungen sind Willkommen.

Gruss
Michael

von holger (Gast)


Lesenswert?

>Ich vermute mal das man nach so einem Fehler die HW irgendwie
>zurücksetzen.
>
>Hat hierzu jemand einen Rat oder selbst schon Erfahrungen gemacht?

Wenn du kein ACK vom Chip bekommst dann versuch erst mal
sauber mit einem I2C Stop raus zu gehen.

von Rangi J. (rangi)


Lesenswert?

Da gibts nen Interrupt "I2C-Error-Int". Dort kannst du das "AF"-Flag 
(AdressFault) in SR1 abfragen.
Ich habe darauf hin SR1=0; und CR1 |= CR1_STOP; gemacht. Danach kann ich 
wieder normal mit de Bus reden. Ebenso verfahre ich mit BERR und ARLO.

von Michael A. (mukululul)


Lesenswert?

Hallo,
also jetzt hab ich das setzen von SR1=0 und STOP probiert, immernoch ein 
Hardfault beim 2ten versuch.
MSG:SR1 = 0x400  SR2 = 0x3
SR1 steht nach dem ersten versuch auf AF und und im SR2 BUSY und MSL.

Hat vielleicht nochjemand eine Idee?

Gruss
Michael

von Michael A. (mukululul)


Lesenswert?

Hallo,
sieht so als ob das Problem mit FreeRTOS zusammen hängt.
Evt so was wie nested IRQ?
Ich werd mal weiter suchen...

Wie kann man den im hardfault Falle sehen warum es einen Hardfault gab?

Gruss
Michael

von Michael A. (mukululul)


Angehängte Dateien:

Lesenswert?

Nun hab ich den Grund für den Hardfault gefunden.

Stack war zu klein ;-)

Um das Problem zu finden hab ich etwas gegoogled und code für einen hard 
fault handler gefunden den ich hier in etwas abgeänderter Form poste.
Hab den Assembler code in inline assembler umgeschrieben....

termf ist meine printf routine aufs terminal.
Damit läst sich das jetzt prima debuggen. Bit 10 im CFSR war bei mir 
gesetzt was auf einen dangeling pointer hinweist.

comipliert mit FreeRTOS, für den STM32 stack muss man das include und 
register access ändern.

Gruss
Michael

von Michael A. (mukululul)


Lesenswert?

Hier noch ein snippet von dem Hardfault print out:
[Hard fault handler - all numbers in hex]
R0 = 1
R1 = 74
R2 = 74
R3 = 1
R12 = a5a5a5a5
LR [R14] = 8002b25  subroutine call return address
PC [R15] = 8002160  program counter
PSR = 21000000
BFAR = e000ed38
CFSR = 400
HFSR = 40000000
DFSR = 0
AFSR = 0
SCB_SHCSR = 0

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.