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
Vielleicht weiß VMLAB ja nicht, wie es diese Variable anzeigen soll, keine Ahnung. Existieren muss sie ja, wenn du da was abspeicherst.
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.
Danke für den Tipp. <Das wird wohl ein kleines Problem/Defizit des Debuggers sein.> Verwende ich AVR Studio statt VMLBab, ändert sich nichts!? Im map-file finde ich: 63:switches.c **** uint8_t dg_flag = 0, t_flag = 0, temp; 131 .LM1-rot_decode 132 .LM1: 133 0018 1B82 std Y+3,__zero_reg__ 134 001a 1A82 std Y+2,__zero_reg__ 64:switches.c **** static uint8_t val_dyn; //enthält Wert der 1. Abfrage 65:switches.c **** 66:switches.c **** #define DG1_cw 0x81; 67:switches.c **** #define DG1_ccw 0x82; 68:switches.c **** #define DG2_cw 0x84; 69:switches.c **** #define DG2_ccw 0x88; 70:switches.c **** 71:switches.c **** GICR &= ~(_BV(INT1)); Wenn ich das richtig interpretiere, existiert val_dyn nicht!! Hier nochmals der Code (soweit relevant): void rot_decode (uint8_t dg_stat[]) { uint8_t dg_flag = 0, t_flag = 0, temp; static uint8_t val_dyn; //enthält Wert der 1. Abfrage #define DG1_cw 0x81; #define DG1_ccw 0x82; #define DG2_cw 0x84; #define DG2_ccw 0x88; GICR &= ~(_BV(INT1)); .... .... 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 (dyn.) i2c_stop(); (die letzten 6 Zeilen nur zum Verständnis)
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.
Guck besser in die Symboltabelle (Ausgabe von avr-nm, wird bei neueren WinAVR-Makefiles automatisch erzeugt).
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.
Leider ist das wohl nicht der Grund: Atmega32, Flash 7700 words, also ca. 50% voll.
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
Sieht aber so aus, als würde dein VMLAB nichts davon wissen. Diese Ausschrift sieht nicht nach Compiler oder Linker aus.
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.
vieleicht hilft es, die variable mit einem vernünftigen Wert zu initialisieren.:
1 | void rot_decode (uint8_t) |
2 | { uint8_t t_flag = 0; |
3 | static uint8_t val_dyn = 0; |
usw. keine angst, per C-Standard wird diese Initialisiereung genau einmal ausgeführt und nicht für jeden Aufruf. HTH -krono
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)
1 | Script started on Sat Sep 22 17:19:30 2007 |
2 | tppb:/tmp tobias$ cat static.c |
1 | #include <stdio.h> |
2 | |
3 | void foo(void) |
4 | {
|
5 | static int var = 42; |
6 | printf("%d\n", var++); |
7 | }
|
8 | |
9 | |
10 | int main(void) |
11 | {
|
12 | foo(); |
13 | foo(); |
14 | foo(); |
15 | foo(); |
16 | return 0; |
17 | }
|
1 | tppb:/tmp tobias$ c89 -o static static.c |
2 | tppb:/tmp tobias$ ./static |
3 | 42 |
4 | 43 |
5 | 44 |
6 | 45 |
7 | tppb:/tmp tobias$ exit |
8 | |
9 | Script done on Sat Sep 22 17:20:08 2007 |
hth, -krono
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.
> genau ein mal. beim "betreten" von main.
Nein, das wird erledigt, bevor main aufgerufen wird - häufig schon vom
Linker...
nagut.. dann halt so ^^. mein punkt war halt das einmalige intialisieren dieser variablen, die ja (für ungeübte) nach lokaler variable aussieht.
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.
Noch so einer, der immer das letzte Wort haben muß, auch wenn er nichts zu sagen hat...
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.