Hallo, ich möchte gerne mit AVR Studio 4.08 ein mit WinAVR erzeugtes Programm simulieren. Dazu erstelle ich mit "make extcoff" das cof-File und lade es in AVR Studio. Nur bei der Simulation springt er ziemlich wahlos in den Sourcen umher. Es werden Zeilen übersprungen, oder er springt in Leerzeilen. Zusammengefasst funktioniert die Siumulation nicht. Kann mir jemand sagen, was ich falsch mache ? Vielen Dank. Mfg Thorsten
mglw. garnichts, ueberspringen von Zeilen kann daran liegen, dass es aufgrund der Compiler-Optimierung keine Debug-Symbole fuer die entsprechende Quellcode-Zeile gibt. Vielleicht auch mal mit dem neuen elf-Parser ausprobieren (neustes WinAVR, neustes AVRStudio) naeheres dazu im wiki (avr-gcc-tutorial).
Danke, das Stichwort Optimierung war das richtige. Ich hatte folgendes programmiert: void DisplayTime(U32 * time) { U08 hours, min, sec, Buffer[9] = "00:00:00\0"; hours = *time / 3600; min = (*time % 3600) / 60; sec = *time % 3600 % 60; Buffer[0] += (hours / 10); Buffer[1] += (hours % 10); Buffer[3] += (min / 10) ; Buffer[4] += (min % 10); Buffer[6] += (sec / 10) ; Buffer[7] += (sec % 10); /* #ifdef LCD4LINES LCD_SetCursorPos(LINE3+6); #else LCD_SetCursorPos(LINE2+6); #endif LCD_PutString(Buffer); */ } Entscheidend ist der auskommentierte Teil. Die drei Zeilen darüber (Buffer[0]...) hat der Compiler wohl komplett wegoptimiert, weil offensichtilich mit Buffer später nichts mehr angestellt wurde. Daran hat sich trotz Abschaltung der Optimierung im Makefile nichts geändert. Erst nachdem die Auskommentierung aufgehoben wurde, funktionierte alles. Das finde ich jetzt mal extrem schräg. Mit der Deklarierung U08 volatile Buffer[9]=... funktionierts übrigens auch. Danke nochmals.
Warum ist das schräg? Folgender Fall: x = 1; x = x + 1; Das wird warscheinlich auch in ein simples "x = 2" übersetzt...
Wird es interssanterweise nicht. Bei der Deklaration "volatile unsigned char x" ensteht folgendes: ;x=1 LDI R24,0x01 STD Y+1,R24 ;x=x+1 LDD R24,Y+1 SUBI R24,0xFF STD Y+1,R24 Ohne volatile wird mal wieder überhaupt kein Code erzeugt.
Klar, weil mit x ja "nichts passiert" und "nicht benötigt" wird. Kurzes Beispiel: #include <avr/io.h> #include <inttypes.h> int main(void) { uint8_t x = 0; DDRB = 0xFF; PORTB = x; while(1) { x++; PORTB = x; } /* NEVEREACHED */ return 0; } [..] 29 .LM2: 30 0008 90E0 ldi r25,lo8(0) 31 .LM3: 32 000a 8FEF ldi r24,lo8(-1) 33 000c 87BB out 55-0x20,r24 34 .L4: 35 .LM4: 36 000e 98BB out 56-0x20,r25 37 .LM5: 38 0010 9F5F subi r25,lo8(-(1)) 39 0012 FDCF rjmp .L4 [..] Hier erkennt der Compiler, daß x zur Laufzeit dem PORTB zugewiesen wird. Als nächstes dann der Beweis zu meiner These "x = 2": #include <inttypes.h> int main(void) { uint8_t x = 1; DDRB = 0xFF; PORTB = 0; x = x + 1; PORTB = x; while(1) { } /* NEVEREACHED */ return 0; } [..] 29 .LM2: 30 0008 8FEF ldi r24,lo8(-1) 31 000a 87BB out 55-0x20,r24 32 .LM3: 33 000c 18BA out 56-0x20,__zero_reg__ 34 .LM4: 35 000e 82E0 ldi r24,lo8(2) 36 0010 88BB out 56-0x20,r24 37 .L2: 38 .LM5: 39 0012 FFCF rjmp .L2 [..] Speziell Zeile 35 verdeutlicht das!
Nachtrag: 1. Da ist mir beim zweiten Beispiel ne Zeile verloren gegangen: #include <avr/io.h> 2. Kompiliert für einen ATMega8 mit Optimierungslevel "s". 3. MFile zum Erzeugen des Makefiles benutzt.
Alles klar, ich muß mich wohl an volatile gewöhnen, wenn alles so ausgeführt werden soll, wie auch programmiert. Noch ne Frage, die mit diesem Thema nichts zu tun hat: kann man bei Programmers Notepad 2 die Funktion "Make All" auch über ein Tastaturkürzel erreichen ? Ich habe nirgends eine Beschreibung gefunden und ständig mit der Maus ins Menu gehen nervt mich schon etwas. Denn eigentlich finde ich es sehr angenehm mit dem PN2 zu arbeiten. Vielen Dank. MfG Thorsten
Tools -> Options -> Tools -> [WinAVR] Make all -> Edit -> Shortcut
Ich hab mir, obwohl ich PN nur gelegentlich nutze, noch "[WinAVR] Rebuild" angelegt. Command: make.exe Folder: %d Parameters: clean all Shortcut: F7 (bin ich so gewohnt) Save: All Files
Wann empfiehlt es sich eigentlich, ein "make clean all" zu machen ?
Wenn man ALLE resourcen neu Kompilieren und die dependencies neu erzeugen möchte.
> Alles klar, ich muß mich wohl an volatile gewöhnen, ...
Nein, um Himmels Willen!
Gewöhn' Dich bitte lieber an die Optimierungen und schreibe keinen
Code, der am Ende nicht benutzt wird, von dem Du aber erwartest, daß
der Compiler ihn umsetzt...
Wenn Du die Optimierung ganz oder teilweise (volatile) abschaltest,
erzeugst Du nicht nur größeren und/oder langsameren Code, sondern Du
debuggst eine völlig andere Applikation als die, die es künftig mal
werden soll. Das ist schade um die Arbeit.
ich habe jetzt aber wirklich ein Problem. Ich möchte eine Funtkion testen (Laufzeit), die gleiche übrigens aus meinem dritten Posting. Dazu habe ich jetzt im Hauptprogramm folgendes gemacht: #define U32 unsigned long; int main(void) { volatile U32 test; test = 215999; // DisplayTime(&test); ... } Er macht es einfach nicht, weder setzt er test auf den geforderten Wert, noch erzeugt er Code für DisplayTime(). Was soll ich denn jetzt machen ?
Seltsmerweise bekomme ich außerdem folgende Warnung: "passing arg 1 of `DisplayTime' discards qualifiers from pointer target type". Damit kann ich nichts anfangen, zumal alles mal funktioniert hat.
Warum er für Deine Funktion keinen Code erzeugt hat, ist mir so erstmal nicht ersichtlich. Wenn die Funktion DisplayTime sehr simpel ist, könnte er sie inline erweitert haben (also ohne RCALL). Die Warnung besagt, daß Deine Variable mit dem volatile qualifier deklariert worden ist (übrigens völlig unsinnig an dieser Stelle, da für die Übergabe einer Adresse zwangsläufig Speicher eingeräumt werden muß), die Funktion aber ohne volatile ... * deklariert ist, d. h. die Funktion weiß nicht mehr, daß sie das übergebene Objekt als volatile behandeln soll.
Ich bin jetzt kein AVR-GCC Profi, aber aufpassen beim Zuweisen von literals (konstanten Zahlenwerten) normalerweise werden die als integer (16bit-> max. 65535) behandelt, vor die Zuweisung der Zahl 215999 sollte ein cast auf long erfolgen, sonst fehlen in der variable test nach der Zuweisung die oberen 16 bits...
Ein Compiler, der das (zumindest bei einer simplen Zuweisung) tut, wäre nicht Standard konform. Der Standard verlangt, dass die Konstante den Datentyp bekommt, der für die komplette Darstellung notwendig ist. Anyway, es ist eine sinnvolle und gute Gewohnheit, im Falle einer Bereichsüberschreitung von `int' auch in der Tat die Konstante (42) als long (42L) oder unsigned long (42UL) zu deklarieren.
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.