Forum: Mikrocontroller und Digitale Elektronik STM32F205 cached Register obwohl er keine Caches hat


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Mw E. (Firma: fritzler-avr.de) (fritzler)


Bewertung
0 lesenswert
nicht lesenswert
Ein interessantes Problem ist mir gestern aufgefallen.

Ab und zu bleibt der I2C hängen bei der while Schleife hier:
1
uint8_t i2c_rep_start(unsigned int i2c_base, uint8_t addr){
2
3
  volatile struct i2c * const i2c = (volatile struct i2c *)i2c_base;
4
  
5
  while(i2c->SR1 & SR1_BTF);
6
  return starting(i2c_base, addr);
7
}

Mit dem volatile stimmt eigentlich alles und es ist mit -O0 compiliert 
zum debuggen.

Im Debugger sehe ich, dass der CPU Kern SR1 als 0x84 ausließt und im 
Register vorhält.
0x80 für TX not empty und eben 0x04 für BTF.
Jetzt dacht ich, dass dann eben der I2C Bus klemmt, kann ja mal 
vorkommen.

ABER!

Wenn ich jetzt im Debugger den Registerwatch öffne, dann steht da 0x80 
beim SR1.
Jetzt kommts noch besser: wenn ich jetzt nochmal durchsteppe, dann ließt 
er auch 0x80 aus und macht weiter aufm I2C Bus.

Hat da jemand ne Idee?
In den Erratas stehen zwar andere gruselige Dinge, aber nicht dieses 
Problem.

Ich brauch nen Exorzisten!

von Gerd E. (robberknight)


Bewertung
0 lesenswert
nicht lesenswert
Mw E. schrieb:
> Wenn ich jetzt im Debugger den Registerwatch öffne, dann steht da 0x80
> beim SR1.

Ich würde dem Debugger an der Stelle nicht unbedingt vertrauen. Wenn der 
Debugger Register auslesen will, kann es zu einigen lustigen Effekten 
kommen die Fehler vorspiegeln wo gar keine sind.

Lies die Register in Deinem Code aus und speichere sie in einem Puffer 
im RAM. Dann lass den Code mit normaler Geschwindigkeit ohne 
Unterbrechung durch den Debugger laufen. Setze Deinen Breakpoint auf 
eine spätere Stelle im Code und schau Dir dann den Inhalt von Deinem 
Puffer an.

von Jim M. (turboj)


Bewertung
0 lesenswert
nicht lesenswert
Mw E. schrieb:
> Mit dem volatile stimmt eigentlich alles und es ist mit -O0 compiliert
> zum debuggen.

Zeig mir wie "struct i2c" definiert ist  und ich zeige Dir (vermutlich) 
Deinen Fehler.

Die metrische Tonne Casts bringt hier nix IMHO.

von (prx) A. K. (prx)


Bewertung
0 lesenswert
nicht lesenswert
Der Asm-Code dieses Codes?

Was soll es eigentlich bringen, die Adresse als uint zu übergeben und 
überall zu casten? Statt den Parameter gleich richtig zu definieren. 
Ganz allgemein würde ich empfehlen, Casts möglichst sparsam einzusetzen.

: Bearbeitet durch User
von foobar (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Sicher, dass der Test (warten auf 0) richtig rum ist?

von M. H. (bambel2)


Bewertung
0 lesenswert
nicht lesenswert
Kann auch ein Glitch in der Hardware sein. Hatte sowas beim SDIO Modul 
schon. Habe das Status Register in einer Dauerschleife gepollt.
Mit -O0 lief alles. Sobald man den Code auf -O3 gestellt hat, hat er 
immer nen CRC Fehler angezeigt, obwohl die Kommunikation aufm 
Logicanalyzer korrekt aussah...

Ich musste zuerst darauf warten, bis das Kommando fertig war, und dann 
die Status Flags lesen. Die Flags flackern wohl während des Sendens ab 
und zu hin und her. Das war eine Sucherei.

: Bearbeitet durch User
von Mw E. (Firma: fritzler-avr.de) (fritzler)


Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die Antworten, leider komme ich erst jetzt zum 
Antworten.

foobar schrieb:
> Sicher, dass der Test (warten auf 0) richtig rum ist?
Genau das wars, BTF soll ja nicht gesetzt sein.
Man sollt eben nicht 1 Uhr morgens noch Coden.

Gerd E. schrieb:
> Mw E. schrieb:
>> Wenn ich jetzt im Debugger den Registerwatch öffne, dann steht da 0x80
>> beim SR1.
>
> Ich würde dem Debugger an der Stelle nicht unbedingt vertrauen. Wenn der
> Debugger Register auslesen will, kann es zu einigen lustigen Effekten
> kommen die Fehler vorspiegeln wo gar keine sind.

Registerlesen beim I2C kann ja durchaus an der Statemachine rumspielen 
(zB SR2 lesen resetet das ADDR Bit).
An der Stelle ist da zwar nichts im DaBla Dokumentiert, aber wer weis 
was ST da ins Silizium gegossen hat.
Jedenfalls wird das auslesen der Register an der Statemachine gespielt 
haben zB durch das DataRegister lesen und schon hats das BTF geflippt.
Wieso hat der PeripheralBus eigentlich keine Leitung für "das ist jetzt 
eine Registerwatch Debugauslesung, bitte behalte die internen States der 
Statemachine bei" ?! Wär doch mal ne gute Neuerung.

Jim M. schrieb:
> Die metrische Tonne Casts bringt hier nix IMHO.
Verzweiflungstat ;)
Ein volatile cast würde reichen.

Jim M. schrieb:
> Zeig mir wie "struct i2c" definiert ist  und ich zeige Dir (vermutlich)
> Deinen Fehler.
Bittesehr:
1
struct i2c {
2
  unsigned int CR1;
3
  unsigned int CR2;
4
  unsigned int OAR1;
5
  unsigned int OAR2;
6
  unsigned int DR;
7
  unsigned int SR1;
8
  unsigned int SR2;
9
  unsigned int CCR;
10
  unsigned int TRISE;
11
};
es bringt übrigens nichts dort volatile vor das struct zu schreiben, 
dann meckert der Compiler zurecht mit:
"periph/i2c_regdefs.h:14:1: warning: useless type qualifier in empty 
declaration"
Erst durch das Casten wird das volatile, ist das struct volatile, so 
auch seine Inhalte.

A. K. schrieb:
> Was soll es eigentlich bringen, die Adresse als uint zu übergeben und
> überall zu casten? Statt den Parameter gleich richtig zu definieren.
> Ganz allgemein würde ich empfehlen, Casts möglichst sparsam einzusetzen.

Es gibt ja nicht nur den einen I2C, also übergeb ich die Basisadresse 
des I2C und lege dann das struct über die Register.
Da könnt man jetzt nochn enum nehmen.
Direkt nen Pointer aufn struct übergeben könnt man auch, aber dann muss 
ich eben beim anlegen auch schon rumcasten.
Oder wie würdest du das machen?

Jedenfalls tut das jetzt, ab und zu gibts maln NACK nachm write, aber 
das kann ja immermal vorkommen beim I2C wenn der Slave grade kein Bock 
hat zu Antworten.

von Jim M. (turboj)


Bewertung
0 lesenswert
nicht lesenswert
Mw E. schrieb:
> Erst durch das Casten wird das volatile, ist das struct volatile, so
> auch seine Inhalte.

Zuviele Casts. Kann man weglassen, wenn man das volatile in das Struct 
packt:
1
struct i2c {
2
  volatile unsigned int CR1;
3
  volatile unsigned int CR2;
4
  volatile unsigned int OAR1;
5
  volatile unsigned int OAR2;
6
  volatile unsigned int DR;
7
  volatile unsigned int SR1;
8
  volatile unsigned int SR2;
9
  volatile unsigned int CCR;
10
  volatile unsigned int TRISE;
11
};

Erst dann macht der Compiler bei "normalen" Zugriffen alles richtig. So 
machen das alle OEM Header die ich hier finde.

Ich würde die "unsigned int" dann noch durch uint32_t ersetzen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.