Hallo zusammen,
ich deklariere innerhalb einer Funktion die Variable val_dyn als static:
void rot_decode (uint8_t)
{ uint8_t t_flag = 0;
static uint8_t val_dyn;
usw.
Diese Funktion wird von einer ISR aufgerufen, verändert aber keine
Variable;
Optimierung im Makefile = 0 (sicherheitshalber (?)).
Benutzt werden WINAVR und avr-libc 1.4.3 sowie VMLAB zur Simulation.
Was passiert?
Übersetzung ok. ohne Fehlermeldungen und Warnungen; die Funktion
arbeitet
einwandfrei, allerdings: val_dyn existiert nicht.
Beim Debuggen im 'single step' wird die Deklaration einfach
übersprungen.
Kann mir jemand auf die Sprünge helfen? Was mache ich falsch?
(Hoffentlich habe ich die Situation ausreichend klar beschrieben).
Wolf
Eine Definition erzeugt ja auch keinen ausführbaren Code, folglich
kann man da nicht im single step hinein.
Wenn du die Variable innerhalb der Funktion nirgends benutzt, wird
der Optimierer sie glücklich ignorieren -- sie kann ja nie geändert
oder gelesen werden.
Hallo Jörg,
ich hätte schreiben sollen "deklariert und definiert ...".
Natürlich wird die Variable innerhalb dieser Funktion benutzt, ich
wollte nicht den Code der ganzen Funktion posten.
Also: val_dyn speichert einen über I2C-Bus gelesenen Wert bis zu einem
erneuten Aufruf der Funktion.
Gruss
Wolf
Jede andere Variable lässt sich in VMLAB anzeigen.
AVR Studio verhält sich übrigens genau so wie in meinem ersten Beitrag
beschrieben.
Was vermutest Du als Ursache?
Das wird wohl ein kleines Problem/Defizit des Debuggers sein. Statische
Variable liegen ja nicht auf dem Stack, sondern im Datensegment.
Eventuell kannst du sie sehen, wenn der Debugger eine Möglichkeit
bietet, globale Variablen anzusehen. Der Name könnte dann aber entweder
kryptisch oder sonstwie eindeutig gemacht sein, denn es können ja viele
Funktionen existieren, die dieselbe statische Deklaration enthalten -
die muß jeweils mit einer anderen Speicheradresse verknüpft sein.
Die lokale Gültigkeit von lokalen statischen Variablen wird einzig durch
den Compiler erzwungen. Wenn man die Adresse so einer Variablen kennt,
kann man sie jederzeit zugreifen - auch wenn sie lexikalisch gerade
nicht gültig ist.
Bei dynamischen Variablen ist das ausgeschlossen, da dynamische
Variablen nur existieren, wenn ein Stackframe der Funktion existiert, in
der sie definiert sind - ist die Funktion rekursiv, dann können sogar
mehrere Frames vorhanden sein, für jede Inkarnation eins.
Sieh dir mal das map-Listing des Linkers an. Dort müßten die Namen und
Adressen aufgeführt sein.
Da val_dyn in den ASM-Fragmenten, die du gepostet hast, nicht
zugegriffen wird, sieht man nichts davon. Die Deklaration bewirkt nur,
daß der Compiler irdendwo im Datensegment den Platz dafür reserviert.
Dafür wird zur Laufzeit kein Code ausgeführt.
Such mal im ASM-Output des Compilers nach einer Stelle, an der val_dyn
gelesen, oder geschrieben wird. Dann kennst du den Namen, den der
Compiler dafür generiert hat. Damit kannst du dann evtl. auch im
Debugger darauf zugreifen.
> Im map-file finde ich:
Das ist nicht der map-File, sondern das ASM-Listing des Compilers.
Unter dem map-Listing versteht man eine Liste der Zuordnungen von
Symbolnamen zu Speicheradressen. Es wird nicht vom Compiler erzeugt,
sondern vom Linker.
Finde nach 'Build' die Warnung
static variable adress beyond RAM limit:val_dyn ->.0x800331
Auch für statische Variable in anderen Funktionen erscheinen
entsprechende Warnungen. Hatte ich bisher nicht beachtet ( :( ).
Was kann die Ursache hierfür sein und wie könnte eine Abhilfe aussehen?
Im map-File erscheint val_dyn mit Adresse 0x0080032e.
Wolf
Wolf wrote:
> Finde nach 'Build' die Warnung> static variable adress beyond RAM limit:val_dyn ->.0x800331
Das klingt aber sehr danach, dass dein Speicher voll ist.
Wolf wrote:
> Leider ist das wohl nicht der Grund: Atmega32, Flash 7700 words, also> ca. 50% voll.
Der Flash ist nicht das Problem.
Oder willst du deine Variablen nur auslesen?
Der SRAM ist das Problem.
> Leider ist das wohl nicht der Grund: Atmega32, Flash 7700 words,> also ca. 50% voll.
Das ist nicht der Speicher, in dem statische Variablen abgelegt werden.
Die landen im RAM, und davon hat der Mega32 deutlich weniger ...
kbuchegg wrote:
>Der Flash ist nicht das Problem.>Oder willst du deine Variablen nur auslesen?
Sollte mir eigentlich klar sein, sonst brauchte man ja wohl keine
Variablen.
Speicherverbrauch lt. AVR Studio
Data: 791 bytes (38.6% full)
(.data + .bss +.noinit)
uhu wrote:
>Gibst du den richtigen Prozessortyp an?
ja, Atmega32
Jörg wrote:
>Sieht aber so aus, als würde dein VMLAB nichts davon wissen.
Mag sein, die 'Ignoranz' bezüglich der staischen Variablen zeigt auch
AVR Studio.
Welche Gründe dafür könnte es geben? Speicherbelegung für Daten und
Programm scheiden m.E aus.
>Diese Ausschrift sieht nicht nach Compiler oder Linker aus.
Was meinst Du damit?
Wolf wrote:
>>Diese Ausschrift sieht nicht nach Compiler oder Linker aus.>> Was meinst Du damit?
Das hier:
static variable adress beyond RAM limit:val_dyn ->.0x800331
Das sieht mir eher wie eine Meldung von VMLAB aus.
Wenn der Code vollständig war (oben) und Deine statische Variable nur
beschrieben und sonst nicht weiter verwendet wird, dann wird diese ggf.
- zu Recht - wegoptimiert.
Jörg wrote:
>static variable adress beyond RAM limit:val_dyn ->.0x800331>Das sieht mir eher wie eine Meldung von VMLAB aus.
Stimmt; allerdings verwendet VMLAB den GNU C compiler genau so wie AVR
Studio auch.
Da sich bisher für mich keine Alternativen zeigen: Gibt es die
Möglichkeit, der statischen Variablen 'zwangsweise' eine Adresse im RAM
zuzuweisen (ich möchte sie möglichst nicht global deklarieren)?
Florian wrote:
>Wenn der Code vollständig war (oben) und Deine statische Variable nur>beschrieben und sonst nicht weiter verwendet wird, dann wird diese ggf.>- zu Recht - wegoptimiert.
Würde ich ja verstehen, aber sie wird geschrieben und gelesen (s.u.):
i2c_start(ENC_ADR + I2C_WRITE); //IO-Expander abfragen
temp = i2c_readNak(); //enthält Wert nach 1. Abfrage
PAUSE_p(5); //Prellzeit abwarten
i2c_start(ENC_ADR + I2C_WRITE); //IO-Expander erneut abfragen
>> val_dyn = i2c_readNak(); //enthält gültigen Wert
i2c_stop();
Im weiteren Verlauf wird sie auch gelesen, z.B.
if (val_dyn & 0x020)
BTW: Danke für die bisherige Hilfe.
Wolf
Wolf wrote:
>>Das sieht mir eher wie eine Meldung von VMLAB aus.> Stimmt; allerdings verwendet VMLAB den GNU C compiler genau so wie> AVR Studio auch.
Trotzdem ist die Meldung von VMLAB, nicht vom Compiler oder Linker.
VMLAB hat in der Analyse der Objektdatei festgestellt, dass die
Variable auf deinem Zielprozessor gar nicht im RAM untergebracht
worden ist.
> Da sich bisher für mich keine Alternativen zeigen: Gibt es die> Möglichkeit, der statischen Variablen 'zwangsweise' eine Adresse im> RAM zuzuweisen (ich möchte sie möglichst nicht global deklarieren)?
Das hilft doch nichts. Du hast einfach keinen RAM mehr, zumindest
laut Meinung von VMLAB. Offenbar geht hier VMLAB von einem anderen
Controller aus als der Compiler, oder es hat einen Bug und ist der
Meinung, der benutzte Controller hätte weniger RAM als er wirklich
hat.
krono wrote:
> keine angst, per C-Standard wird diese Initialisiereung genau einmal> ausgeführt und nicht> für jeden Aufruf.
Quatsch. Die Initialisierung einer lokalen Variablen wird bei
jedem Aufruf vorgenommen, und statische Variablen werden per C-Standard
ohnehin mit 0 initialisiert, wenn nichts anderes angegeben ist.
Jörg Wunsch wrote:
>> keine angst, per C-Standard wird diese Initialisiereung genau einmal>> ausgeführt und nicht>> für jeden Aufruf.>> Quatsch. Die Initialisierung einer lokalen Variablen wird bei> jedem Aufruf vorgenommen, und statische Variablen werden per C-Standard> ohnehin mit 0 initialisiert, wenn nichts anderes angegeben ist.
einer lokalen variable ja.
aber nicht bei einer statischen lokalen variable.
ansonsten wuerde dass hier nicht funktionieren.
(btw: c89 heisst, das ganze wird mit einem ANSI-C Compiler gebaut)
krono wrote:
> einer lokalen variable ja.> aber nicht bei einer statischen lokalen variable.> ansonsten wuerde dass hier nicht funktionieren.
Eine lokale statische C-Variable wird nur einmal bei Programmstart
initialisiert. (C++ initialisiert sie, wenn sie zum ersten mal sichtbar
wird.)
Die Eigenschaft 'lokal' wird bei statischen Variablen nur vom
Scopemechanismus des Compilers erzwungen. Die Variable selbst lebt von
Programmstart bis zum Ende, ist aber nur in dem Block sichtbar, in dem
sie definiert ist.
Uhu Uhuhu wrote:
> Eine lokale statische C-Variable wird nur einmal bei Programmstart> initialisiert. (C++ initialisiert sie, wenn sie zum ersten mal sichtbar> wird.)>> Die Eigenschaft 'lokal' wird bei statischen Variablen nur vom> Scopemechanismus des Compilers erzwungen. Die Variable selbst lebt von> Programmstart bis zum Ende, ist aber nur in dem Block sichtbar, in dem> sie definiert ist.
hab ich nicht bezweifelt.
(selfquote)
keine angst, per C-Standard wird diese Initialisiereung genau einmal
ausgeführt und nicht
für jeden Aufruf.
(/selfquote)
genau ein mal. beim "betreten" von main.
krono wrote:
> mein punkt war halt das einmalige intialisieren dieser variablen,> die ja (für ungeübte) nach lokaler variable aussieht.
Und mein Punkt war, dass du deine Aussage ,,wird nur einmal erledigt''
unter ein Stück Code mit zwei verschiedenen Initialisierungen
gesetzt hast, von denen eine wirklich nur einmal erfolgt, die andere
aber (automatische Variable) bei jedem Funktionseintritt. Zudem war
die Initialisierung, auf die sich der Kommentar bezog (nämlich die
der statischen Variablen) völlig überflüssig, da sie der ohnehin
vom Compiler/Laufzeitsystem bereits vorgenommenen Initialisierung
aller statischer Objekte auf 0 entspricht.
Damit ist auch klar, dass dein Vorschlag, die Variable ,,mit einem
vernünftigen Wert zu initialisieren'', dem OP keinerlei Änderung
des Verhaltens bringen wird. Der damit generierte Objektcode ist
nämlich letztendlich identisch. (GCC erkennt mittlerweile, dass
eine Initialisierung eines statischen Objekts mit 0 bzw. NULL der
default-Initialisierung entspricht, und schiebt dadurch die Variable
nicht mehr aus dem .bss ins .data, wie er das früher noch gemacht
hat.)
das mit den 2 deklarationen kam daher, dass ich nur den "vorgegebenen"
code geaendert habe.
und die initialisierung statischer variablen auf 0 war mir bis dato
nicht bekannt.
ist ja auch eigentlich fuers problem irrelevant.
ich wurde mich fragen, ob dass ueberhaupt hülfe.
krono wrote:
> und die initialisierung statischer variablen auf 0 war mir bis dato> nicht bekannt.
Hmm, und das, wo du doch selbst mit dem C-Standard herumgewedelt
hast. ;-) Tjaja, das steht auch alles im Standard... (wenn du's
nicht glaubst, popele ich dir auch gern noch die Kapitelnummer
dafür raus).
krono wrote:
> vieleicht hilft es, die Variable mit einem vernünftigen Wert zu> initialisieren.:
Habe ich ich schon früher versucht, erwartungsgemäss ohne Erfolg.
Nach wie vor bleibt für mich die zentrale Frage, wie ich AVR Studio
(WINAVR) dazu bewege, meinen Code mit (lokalen) statischen Variablen zu
compilieren und zu linken, um ihn mit STK500 zu testen.
Eine globale Deklaration möchte ich vermeiden; jedes bessere C-Handbuch
weist darauf hin.
Moment mal, mit dem STK500 sollte bitteschön alles funktionieren, sonst
hast du noch ein ganz anderes Problem. Bislang hattest du lediglich
geschildert, dass es in der Simulation von VMLAB nicht funktioniert
hat, selbst von AVR Studio war keine Rede.
inzwischen hat sich zu diesem Thema vielerlei angesammelt, vielleicht
hast Du es übersehen - meine Beiträge v. 29.8.07 und 1.9.07.
STK500 ist für mich eine komfortable Hw-Plattform mit einiger Peripherie
wie LEDs, Schalter, UART und hat m.E. nichts mit den geschilderten
Schwierigkeiten zu tun.
Fang einfach nochmal von vorn an, das ist alles zu verwirrend.
Was geht, was geht nicht, welche Fehlermeldungen, an welcher Stelle
tauchen die Fehlermeldungen auf?
Das da oben passt alles nicht mehr wirklich zusammen.
Da ich meinen Code inzwischen verändert/erweitert habe, muss ich
versuchen, den damaligen Stand zu restaurieren, werde mich aber auf
WinAVR, AVRStudio (und STK500) beschränken und VMLAB zunächst ausser
acht lassen.
Bis dahin Dank für bisherige Hilfe.
Wolf
wegen anderer Prioritäten habe ich erst jetzt das Problem wieder
aufgreifen können.
Ergebnis: Mit AVRStudio und STK500 als Target wird eine Variable als
static ohne Probleme akzeptiert und so behandelt wie erwartet.
VMLAB verarbeitet tatsächlich <static> nicht richtig.
Danke nochmals.
Wolf
Das ist schade. Da Enrique VMLAB auch nicht mehr weiter entwickeln
will (weil es kommerziell einfach nie wirklich gelaufen ist), wird
sich das wohl auch nicht mehr ändern lassen.
>VMLAB verarbeitet tatsächlich <static> nicht richtig.
Lokale static-variablen lassen sich im watch-Fenster schon ansehen,
allerdings nicht im scope der zugehörigen Funktion, sondern im scope von
main.
Oliver