Hallo Es wäre mir ja nicht aufgefallen, hätte ich nicht das Oszilloskop laufen lassen. folgende C-Code Zeile: loop_until_bit_is_set(CONTROL_IN, DATA_STROBE); wird so übersetzt: +0000020B: B380 IN R24,0x10 In from I/O location +0000020C: 9580 COM R24 One's complement +0000020D: FD80 SBRC R24,0 Skip if bit in register cleared +0000020E: CFFC RJMP -0x0004 Relative jump das sind 4 ops. es geht auch mit 2en. asm volatile ( "sbis 0x10,4" "\n\t" "rjmp -0x0002" "\n\t" :: ); und so sieht auch das Makro in iomacros.h aus. Ich vermute dass er Codeoptimierer da irgendwie reinfuscht. Kann mir jemand etwas genaueres darüber sagen? Wie kann ich im asm block die obengenannten Konstanten einbinden. (trotz avr-asm cookbook bekomme ich es nicht hin) Wäre wirklich dankbar für Ratschläge und Hinweise. Bye
Das ist schon recht seltsam, da der Assemblercode dieses Makros, wie du ja selbst festgestellt hast, in iomacros.h definiert ist. Und das Schlüsselwort volatile steht auch dabei, daher dürfte der Optimierer dort nichts herumdrehen. Und du bist sicher, dass du dich nicht vertan hast? Schau dir mal die Stelle im AVR-Studio an, da kann man ja zwischen Assembler- und Sourcecode-Ansicht umschalten.
Ja, das ist aus dem AVR-Studio entnommen. Hier nochmal das Original. 516: loop_until_bit_is_set(EPP_CONTROL_IN, EPP_DATA_STROBE); +00000208: B380 IN R24,0x10 In from I/O location +00000209: 9580 COM R24 One's complement +0000020A: FD80 SBRC R24,0 Skip if bit in register cleared +0000020B: CFFC RJMP -0x0004 Relative jump Hier auch mal die Optionen vom Makefile: #Hier definieren wir Einstellungen (Flags) für den Assembler, ASFLAGS = -Wa, -gstabs #den Compiler CPFLAGS = -g -Os -Wall -Wstrict-prototypes -Wa,-ahlms=$(<:.c=.lst) #und den Linker LDFLAGS = -Wl,-Map=$(TRG).map,--cref Es würde mich mal interessieren, ob andere auch diesen Code von loop_until_bit_is_set() erhalten.
Misst eigentlich wollte ich den oberen Beitrag nur einmal haben. Naja. Es kommt aber noch besser, mit Optimieroption -O0 kommt folgendes raus... 169: loop_until_bit_is_set(EPP_CONTROL_IN, EPP_DATA_STROBE); +000000DD: 91800030 LDS R24,0x0030 Load direct from data space +000000DF: 2799 CLR R25 Exclusive OR +000000E0: 9580 COM R24 One's complement +000000E1: 9590 COM R25 One's complement +000000E2: 7081 ANDI R24,0x01 Logical AND with immediate +000000E3: 7090 ANDI R25,0x00 Logical AND with immediate +000000E4: 9700 SBIW R24,0x00 Subtract immediate from word +000000E5: F7B9 BRNE +0x77 Branch if status flag cleared das ist ja Wahnsinn.
Vielleicht sollte ich noch dazu sagen, daß es für einen Atmega128 (MCU = atmega128) kompiliert wurde.
Ich arbeite nun schon seit einiger Zeit mit dem avrgcc und bin von der Qualität des erzeugten Codes sehr überzeugt (im Gegensatz zu anderen handelsüblichen Compilern!). Daher habe ich diese Sache selbst mal überprüft, indem ich mit dem AVR-Studio mal Code unter die Lupe genommen habe, wo dieser Makro verwendet wurde. Also ich kann das, was du hier schreibst absolut nicht nachvollziehen, bei mir stehen immer die Assemblerbefehle drin, die auch dort stehen sollen, nämlich die, die in iomacros.h definiert sind und sonst nichts! Wo soll auch der andere Code herkommen, der Compiler saugt sich sowas doch nicht aus den Fingern und bei Assemblercode, der mit dem Schlüsselwort "volatile" gekennzeichnet ist, dort mengt auch der Optimierer nichts herum, das kann man in jedem Lehrbuch nachlesen. Getestet habe ich dies mit avrgcc Version 3.02. Sag mal, woher stammen denn die Beschreibungstexte hinter dem Assemblercode? Ist das neu im AVR-Studio Version 4? In Version 3 sieht das aber etwas anders aus. Ich habe in anderen Foren schon einiges erlebt, wo Leute versucht haben, über die Qualität des avrgcc herzuziehen. Solche Leute entpuppten sich dann aber stets als Mitarbeiter von Handelsfirmen, die kommerzielle Konkurrenzprodukte verkaufen oder es waren Leute, die scheinbar sonst irgendwie gesponsort wurden um solche Aussagen zu machen. Und deren Aussagen entpuppten sich bei genauerer Betrachtung stets recht schnell als heisse Luft. Ich habe erst kürzlich die Testversion des ICCtiny von Imagecraft bei mir installiert, weil ich neugierig war, was so ein 200$-Produkt zu leisten vermag. Schon am ersten Tag hatte ich 2 heftige Compiler-Fehler, die bei einem ausgereiften Produkt niemals hätten vorkommen dürfen. Daraufhin hatte ich die Fehlerbeschreibung mit einem Beispielcode an Imagecraft gesendet, weil ich auf deren Antwort gespannt war. Das einzige, das ich bis heute zurückbekam war eine knappe Bestätigung über den Erhalt meiner Mail und das ist nun schon fast einen Monat her. Auf weitere Rückfragen erhielt ich keine Antwort! Dies will ich hier nun nicht mehr weiter kommentieren, solche Sachen die sprechen halt für sich. Soweit meine 0.02$ zu diesem Thema. Notker
Also es scheint am avr-gcc 3.2 (ja 3.2!!!) zu liegen. (2002-06-25_FREAKS.exe) #include <io.h> int main (void) { loop_until_bit_is_set(PINA, 0); } mit 3.2 (eben FALSCH): 5: int main (void) 6: { +00000052: EFCF SER R28 Load immediate +00000053: E0DF LDI R29,0x0F Load immediate +00000054: BFDE OUT 0x3E,R29 Out to I/O location +00000055: BFCD OUT 0x3D,R28 Out to I/O location 7: loop_until_bit_is_set(PINA, 0); +00000056: B389 IN R24,0x19 In from I/O location +00000057: 9580 COM R24 One's complement +00000058: FD80 SBRC R24,0 Skip if bit in register cleared +00000059: CFFC RJMP -0x0004 Relative jump 9: } mit 3.02 (RICHTIG) (avrgcc20011121a.exe) 5: int main (void) 6: { +00000053: EFCF SER R28 Load immediate +00000054: E0DF LDI R29,0x0F Load immediate +00000055: BFDE OUT 0x3E,R29 Out to I/O location +00000056: BFCD OUT 0x3D,R28 Out to I/O location 7: loop_until_bit_is_set(PINA, 0); +00000057: 9BC8 SBIS 0x19,0 Skip if bit in I/O register set +00000058: CFFE RJMP -0x0002 Relative jump 9: } +00000059: CFFF RJMP -0x0001 Relative jump Aber die 3.02 Version unterstützt keinen ATmega128!! Was soll ich machen? Kann mir jemand helfen? Jochen
Die Version 3.20 ist deutlich als Experimentalversion (=Alpha Stadium) gekennzeichnet! Aber dass hier so gravierende Mängel drin sind, hätte ich nicht gedacht. Meiner Meinung nach müsste es aber auch möglich sein, die Version 3.02 für diese neuen Mega-Typen zumindest bedingt nutzbar zu machen. Wenn man sich selbst eine Header-Datei bastelt, müsste es auch möglich sein, Code für einen anderen Typen für den Mega128 lauffähig zu bekommen. Allerdings werden wohl nicht alle Features des Mega128 nutzbar sein. Kommt halt drauf an, was du machen willst. Notker
Ist ja im Prinzip kein Fehler, sondern nur nicht ganz optimaler Code. Das Problem sind ja der MEGA128 und der und alle anderen MEGA AVR mit I/O-Registern im Bereich > 60h. Dieses war ja ursprünglich garnicht so vorgesehen. Dieser ist auch nur mit entsprechenden Memory orientierten Befehlen erreichbar. Ebenso so wurden ja etliche Register aus dem SBIC/SBIS Bereich heraus verschoben. Man braucht sich nur mal die Header-Datei sfr_defs.h anzuschauen. Hier optimalen Code zu erzeugen, erfordert doch aufwendige Behandlung von Sonderfällen. Ganz nebenbei wird ja hier ATMEL der normalen AVR Architektur etwas untreu. Hier sollte man nicht auf die Arbeit anderer Leute schimpfen, sondern selber vielleicht Lösungen für diese Sonderfälle entwickeln, die zu optimalerem Code führen.
> Das Problem sind ja der MEGA128 und der und alle anderen MEGA AVR mit I/O-Registern im Bereich > 60h. Die Adresse im Beispiel ist aber 0x10. > Dieses war ja ursprünglich garnicht so vorgesehen. Dieser ist auch nur mit entsprechenden Memory orientierten Befehlen erreichbar. Das trifft aber auf das obige Beispiel nicht zu. > Hier sollte man nicht auf die Arbeit anderer Leute schimpfen, sondern selber vielleicht Lösungen für diese Sonderfälle entwickeln, die zu optimalerem Code führen. Wie ich schon sagte, meine Meinung über den avrgcc ist eigentlich recht positiv. Aber diese Sache ist eindeutig ein Mangel, der korrigiert werden muss, da gibt es keine Diskussion. Wie schon gesagt, die Version 3.20 ist ja auch eindeutig als Experimentalversion gekennzeichnet.
@Notker Woher soll der Compiler denn ohne Ausnahmebhandlung denn wissen, dass der I/O Port PINx den im Bit-Testbereich liegt. Bei der Standardarchitektur war und ist dies ja der Fall. Ich muss dir allerdings zustimmen das der AVRGCC für alle "Standard" AVRs recht vernünftigen und stabilen Code erzeugt.
Erstmal Danke für die rege Teilnahme an diesem Problem. Da die avrgcc 3.2 ja nicht nur die Codeerzeugung für den ATmega8 und ATmega128 betrifft, sondern auch wohl andere wie zB. Atmega103 denke ich dass es sinnvoll ist, eine Lösung zu finden, die diese Grenze berücksichtigt. (wenn es daran liegt) Werde mich mal daran versuchen, denke aber nicht dass ich es hinbekomme, da mein Wissen über den gcc nicht besonders ist. Hatte auch noch ein anderes Problem, nämlich dass der Compiler Code erzeugt hatte der mehr RAM verbraucht hatte als der Atmega128 her gab. (lag aber an meiner Fehleinschätzung) Ist mir nicht aufgefallen, da der Compiler sich nicht gemeldet hatte. text data bss dec hex filename 1234 82 4527 5843 16d3 Prell.elf data (82bytes) + bss (4527bytes) > 4096Bytes RAM Naja jetzt läuft es mit nem kleineren array. Wäre echt gut wenn man zu dem anderen Problem eine Lösung findet. Außerdem finde es noch komisch dass er erst dass Complement bildet und dann auf bit_clear testet anstatt direkt auf bit_set.
Hi, ich habe bis vor etwa einem Monat mit dem ICC programmiert, und bin derzeit auf avr-gcc. Die neueste Winavr version ist ausgezeichnet. Ich habe das exakt gleiche (relative einfache) Programm von icc nach gcc geportet. Dabei sind etwa 1kb asm source und der rest in c. Aufgefallen ist mir (das war das avrfreaks release, also die vorherige version 3.2) dass der code von anfang an schneller lief. Wo ICC erst ab 500$ einen (in dem programm völlig ineffektiven) optimizer anbietet funktioniert der von avr umsonst und wirklich effizient. der erzeugte code war um 30% kleiner als der vom ICC. Die einzigen Nachteile des AVR die mir sind: Größerer Programmieraufwand da der ICC mehr libraries etc hat. Das debuggen des gcc codes im avrstudio geht nicht so gut wie das des ICC codes, zb kann man beim icc externe asm files wie ne weitere .c file singlesteppen, beim gcc wird das sehr unübersichtlich. Man muss sich erst in die makefiles etc einarbeiten, das soll zwar glaube ich alles vereinfacht werden, also dass avrgcc sogar mit gui etc kommt, aber ich schätze es wird noch einige Zeit dauern bis der gcc auch so komfortabel wie ein kommerzieller Compiler wird, generell das größte Program das unixprogramme so an sich haben (denke ich). Mein Fazit: Er ist umsonst, er arbeitet effektiver und die neueste Version ist gleich angenehm zu programmieren wie der ICC. Und Support findet man beim weiter verbreiteten gcc auch einfacher als beim ICC oder einem anderen kommerziellen crosscompiler.
Eine "GUI" für den GCC gibt es doch mehr oder weniger schon. Schau Dir mal AVREdit an. Das ist die GCC Version von AVRfreaks mit einem Editor. Leider noch nicht ganz Bugfree
Beim Umstieg von avrgcc 3.02 zu avrgcc 3.3 (WinAVR) bin ich ueber genau dieses loop_until_bit_is_set macro gestolpert. Beim avrgcc 3.02 ist es in iomacro.h als asm-macro so definiert: #define loop_until_bit_is_set(port, bit) \ _asm__ __volatile_ ( \ "L_%=: " "sbis %0,%1" "\n\t" \ "rjmp L_%=" \ : /* no outputs */ \ : "I" ((uint8_t)(port-__SFR_OFFSET)), \ "I" ((uint8_t)(bit)) \ ) Beim avrgcc 3.3 hingegen so: #define bit_is_clear(sfr, bit) (~inb(sfr) & _BV(bit)) #define loop_until_bit_is_set(sfr, bit) do { } while (bit_is_clear(sfr, bit)) Das Problem liegt in dem bitweise Komplement in von inb(sfr) in dem bit_is_clear() Macro. Der Compiler denkt wohl, er muss erst alle Bits einlesen, um dann das Kompelement zu bilden und danach ein Bit zu maskieren. Als Lösung habe ich ein eigenes _loop_until_bit_is_set geschrieben, welche das bitweise invertieren vermeidet: #define _loop_until_bit_is_set(port, bit) { while (!bit_is_set((port), (bit))); } Bei dieser Version verwendet der gcc den "skip on bit" Befehl (Compileraufruf natuerlich mit der Optimierungsoption -Os). Ansonsten scheint der avrgcc 3.3 uebrigens besser zu optimieren als der avrgcc 3.02 Ich habe allerdings bisher nur Code fuer den AT2313 und AT2343/23 produziert. Kann sein, dass der Optimizer fuer den MEGA128 anders agiert... MfG, - Michael Bergmann
Ich kenne AVREdit, hab es kurz ausprobiert war für etwa 5 Sekunden begeistert dann bereits enttäuscht. Ich kann die störenden Punkte und Bugs zwar nicht näher benennen aber es gab davon reichlich. Ich verwende derzeit Ultraedit mit 3 kurzbefehlen, compile,clean,upload. Damit kann man sehr angenehm arbeiten da Ultraedit an sich ein sehr ausgearbeiteter Editor ist (man kann blöcke markieren und mit tab gemeinsam ausrücken, er kann c++ und asm code farblich hervorheben wie ein normales gui, und die Handhabenung mit Dateien in einem Projekt etc. ist sehr angenehm, dazu kanne r auch in die Errorzeile Springen und die compilerwarnungen und errors in nem dockingfenster anzeigen) Es ist leider Shareware, also entweder crack oder kaufen wenn mans damit machen will. Meiner Meinung nach ist die GUI des MS VC++ die Beste, sehr angenehm handhabbar, exakt auf den Zweck angepasst, und ich finde es angenehm wenn man zb strcpy( schreibt das prorgamm klein einblendet welche Befehle es gibt) oder man auf die selbe art irgendeinestrcutvariable. schreibt (und alle members gelistet werden). Der größte Nachteil von AVRgcc ist wie schon gesagt die Handhabung, wenn zb ein Entwickler zum ersten mal auf einem atmel entwickeln möchte und er vor der Compilerwahl steht ist es unwarscheinlich dass avrgcc genommen wird. Ich gehe davon aus dass er unter windows entwickeln möchte, dann steht er vor dem Problem dass er nicht ienmal ein von Anfang an funktionsfähiges Release bekommt, bzw die veraltete .2 Version downloaden muss (und auch da muss man readmes etc lesen usw.) Man nehme ICC und hat alles sofort lauffähig, einen click auf setup.exe und das Ding hat eine brauchbare gui und alles weitere integriert, compilersettings sieht man erklärt und checkboxes, F1 bringt eine Hilfe zum Compiler und kennt den Syntax. inline asm ist weitaus angenehmer als der von gcc. und makefiles gibts gar keine mehr, man muss keine Abhängigkeiten etc definieren. Ist natürlich fraglich ob es sowas jemals für den avrgcc geben wird da das Tool für Unix entwickelt wird.
eine richtige ide wirds wohl eher nicht geben...aber eric weddington arbeitet gerade am januar release für winavr3.4..dort soll ein eigenständiger editor mit dabei sein der einige sachen vereinfachen soll...
Die Geschichte mit dem bit_is_clear() war eindeutig ein Denkfehler von Marek. Der C-Standard verlangt halt, daß die Argumente für den Tilde-Operator erst zu promoten sind (zu "int" in diesem Falle), bevor der Operator angewandt wird. Mittlerweile hat jemand einen offiziellen Bugreport geschrieben und dort eine effektivere Version angeboten: !bit_is_set() tut's nämlich ohne diesen Seiteneffekt. Das wird in der nächsten WinAVR dabei sein, da es schon im CVS ist, Eric aber den Sourcecode für die neue Version noch nicht gezogen hat. scanf() wird übrigens auch dabei sein...
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.