Forum: Compiler & IDEs lokale Variable + volatile funkt nicht


von GasmixMan (Gast)


Angehängte Dateien:

Lesenswert?

Servus!

AVR Studio : Version 4.12, Service Pack 4, Build 498
WinAVR     : 2006-04-21
HW         : ATMega16, LCD mit HD44780, 3x4 Tastenfeld
Download   : AVRISP

Problem: Die Tastenabfrage (siehe Datei "keypad_ctrl.c", Methode 
"readKeypadKEY") funktioniert mit Optimierung 's' in Makefile nicht, 
hingegen ohne Optimierung '0' sehr wohl.

Zu Testzwecken gebe ich mir den binären Wert des PIN Registers der 
verwendeten Schnittstelle D BUT_PIN (siehe define Konstante in 
"global_defs.h") auf die LCD Zeile 2 aus und den in der lokalen Variable 
sample_1 gespeicherten Wert von BUT_PIN auf Zeile 3 aus. Alles in der 
Methode "readKeypadKEY".

Falls die entsprechende Taste gedrückt wird ändert sich der Wert von 
BUT_PIN aber sample_1 ändert sich mit Optimierung nie, obwohl volatile.

Ein weiterer Versuch die Schnittstelle D als formalen Parameter zu 
übergeben (siehe die Parameter port und pin welche in der jetzigen 
Version nicht verwendet werden) funktioniert auch mit Optimierung auch 
wen die lokalen Variablen sample_1 und sample_2 nicht mit volatile 
qualifiziert werden. -> aber für mich unbefriedigende Lösung

Ich wollte euch fragen, wieso in der jetzigen Version der Wert von 
sample_1 nie erneuert wird, obwohl mit volatile qualifiziert.

Brauche wirklich Hilfe da ich bereits zwei volle Tage in dieses Problem 
investiert habe und keinen mm weiterkomme.

Die main befindet sich übrigens in "gasmixer.c".

Schönen Dank erstmal.

von GasmixMan (Gast)


Lesenswert?

Servus!

Das Problem hat (anscheinend) nichts mit "volatile" zu tun sondern eher 
mit der Dauer für die Einsynchronisierung der Pins.

Vergleicht man das Inline-Assembler File so sieht man:

ohne Optimierung:

122:          sample_1 = BUT_PIN;
+00000B10:   91800030    LDS     R24,0x0030       Load direct from data 
space
+00000B12:   878D        STD     Y+13,R24         Store indirect with 
displacement

mit Optimierung:

122:          sample_1 = BUT_PIN;
+000003C1:   B380        IN      R24,0x10         In from I/O location
+000003C2:   8389        STD     Y+1,R24          Store indirect with 
displacement

das der Unterschied im Ladebefehl des Ports liegt, wobei IN in einem 
Zyklus und LDS in zwei Zyklen abgearbeitet wird. Der Verdacht bestätigt 
sich, denn wenn man nach setzen des Ports eine "NOP" Operation einfügt 
funktioniert der Code auch mit Optimierung. D.h. zwischen setzen des 
Ports und Einlesen muss gewartet werden. Bei der Variante ohne 
Optimierung hat es funktioniert, weil eben der LDS Befehl zwei Zyklen 
benötigt.

Jedoch habe ich noch eine Frage. Sieht man sich den Schaltplan im 
Datenblatt des ATMega16 für eine Schnittstelle an, so sieht man das die 
Einsynchronisierung über ein Latch und ein D-FF geschieht, welche aber 
anscheinend immer aktiv sind (keine enable-Leitungen). Dann müsste aber, 
wenn ich die Taste drücke und eine Zeile des Tastenfelds fix auf 0 
liegt, der neue Wert einmal in das PINxn Register übernommen werden. -> 
somit bräuchte ich theoretisch kein "NOP".

Kann mir das bitte einer erklären.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> D.h. zwischen setzen des
> Ports und Einlesen muss gewartet werden.

Das ist ein alter Hut.  Bin ich auch schon drüber gestolpert. ;-)
Beispielsweise im Datenblatt vom ATmega640 & Co., Seite 86 Mitte:

``When reading back a software assigned pin value, a nop instruction
must be inserted as indicated in Figure 35. The out instruction sets
the "SYNC LATCH" signal at the positive edge of the clock. In this
case, the delay tpd through the synchronizer is 1 system clock
period.''

von A.K. (Gast)


Lesenswert?

"welche aber anscheinend immer aktiv sind (keine enable-Leitungen)"

Brille putzen. Seite 51.

von Peter D. (peda)


Lesenswert?

GasmixMan wrote:


> funktioniert der Code auch mit Optimierung. D.h. zwischen setzen des
> Ports und Einlesen muss gewartet werden. Bei der Variante ohne

Das ist ein generelles Problem aller 1-Zyklus-MCs, auch bei den neuen 
8051-ern (z.B. AT89LP4052) ists auch so.

Man muß mehrere Sachen machen, hat aber nur einen Taktzyklus. Also macht 
man mehreres parallel, d.h. der eine Befehl wird komplettiert, während 
der nächste schon beginnt.


Bei den PICs gibt es sogar noch etwas ganz verrücktes. Wenn man 2 
Read-Modify-Write Befehle hintereinander schreibt, wird nur der letzte 
wirklich ausgeführt. Der letzte liest das Portregister bevor der erste 
die Änderung zurückgeschrieben hat und damit ist die Änderung verloren.

Die AVRs und 8051 machen es aber korrekt.


Peter

von A.K. (Gast)


Lesenswert?

@Peter: Bei welchen PICs gibt's das? Das heisst nämlich, dass der 
Compiler auf solche Spässe Rücksicht nehmen muss. Die normale 18er 
jedenfalls sind laut Doku 4-Takter ohne solches Problem.

von GasmixMan (Gast)


Lesenswert?

Servus!

Also die Synchronisierschaltung ist immer aktiv siehe S. 51 -> von wegen 
Brille putzen.

Das Problem liegt in der Zeile "setPortHighKEY()", dort werden innerhalb 
der Schleife alle Zeilen auf '1' gelegt und dann erst die entsprechende 
Zeile auf '0'. Somit brauche ich das "NOP" wirklich.

``When reading back a software assigned pin value, a nop instruction
must be inserted as indicated in Figure 35. The out instruction sets
the "SYNC LATCH" signal at the positive edge of the clock. In this
case, the delay tpd through the synchronizer is 1 system clock
period.''

Hatte ich gelesen und verstanden. Dennoch machte ich den Denkfehler bzw. 
"Betriebsblindheit", dass die Leitung konstant auf '0' gelegt wird. Dann 
bräuchte ich das "NOP" nicht, da der PIN Wert durch eine externe Quelle 
(der Benutzer) verändert wird und durch den dauernd aktiven Synchronizer 
würde mal ein veränderter Wert eingelesen. Habs im Code einfach 
übersehen.

Danke.

von A.K. (Gast)


Lesenswert?

Sorry für das "Brille putzen", war ein Missverständnis. Bei Latches hat 
der Begriff "Enable" eine besondere Bedeutung.

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.