Hallo, gestern wollte ich ein kleines Programmchen für einen 2313 (2kB Flash, 128B RAM) mit AVR-GCC schreiben. Obwohl mein Programmchen wirklich klein war (nur ein Modul, ~500 Zeilen mit defines und Kommentaren), kam die Fehlermeldung, daß sowohl Flash als auch RAM voll sind. Ist das normal?? Kann man dem Compiler vielleicht irgendwie sagen, er soll auf "Speicherplatz" optimieren?? Danke, Sebastian
Ich habe ähnliches vor: Um die Eignung der AVR für meine Anwendungen im industriellen Umfeld zu testen, will ich einen AT89C2051 durch einen AT90S2313 ersetzen, d.h. ohne eine neue Platine machen zu müssen. Das 2051-Programm ist in C geschrieben und belegt etwa 1,6kB des Flash. Es sind nur wenige Zeilen, aber es benutzt float Variablen. Meine Frage: Hat schon mal jemand float auf nem 2313 verwendet oder ist das illusorisch ? Peter
@Sebastian: Welche Features benutzt Du denn alles so? Ich habe mal ein kleines meiner Projekte herausgewühlt, das vom Codeumfang vergleichbar ist. Das kommt für 2 x je ca. 400 Zeilen Quellcode auf 1 KB Flash-Nutzung. Allerdings hängt das von den benutzten Bibliotheksfunktionen etc. pp. mit ab. Wenn Du printf() benutzt, genügt schon eine einzige Zeile Programmcode, daß alles nicht mehr in einen AT90S2313 hineinpaßt. ;-) Die RAM-Nutzung hast Du natürlich komplett mit Deinen Variablen selbst in der Hand. Denk dran, daß Du auch RAM für den Stack brauchst. @Peter: float auf dem 2313 wird sicher knapp. Solange Du nur addieren und subtrahieren willst, geht es vielleicht gerade noch so, Multiplikation oder gar Division ziehen aber vermutlich schon so viel mit rein, daß das nicht mehr praktikabel ist. Und Ein-/Ausgaben wirst Du ja vielleicht auch noch machen wollen... Ich habe Gleitkomma erfolgreich auf einem AT90S8535 benutzt, allerdings wäre für printf() kein Platz mehr gewesen (hatte ich damals sowieso noch nicht), und zusammen mit bißchen Debug-Code und sowas habe ich am Ende den Flash dieses Teils auch vollbekommen (fast jedenfalls). Vielleicht wäre ja scaled integer eher was für Dich?
@Peter: Vielleicht hast Du schon mein Frequenzmeßgerät gesehen www.mino-elektronik.de/fmeter/fmeterx.htm. Hier wird float auf Basis eines IAR-Compilers ICCA90 (V1.x) verwendet. Die Codegröße für fadd, fsub, fmul, fdiv, die Konvertierungen float2long, long2float, ... und die Rundungen beträgt unter 900Byte. Verglichen mit ImageCraft-AVR, GCCAVR und Codevision-AVR ist das sehr kompakt. Printf ist allerdings bei keinem der Compiler anzuraten, da auch viele Routinen gelinkt werden, die nicht gebraucht werden. Ohne Geld auszugeben, kann man eine Demo von IAR bekommen, eine c-Quelle mit float schreiben und 'debuggen'; so bekommt man den versteckten Code der Libs zu sehen und könnte ihn auch abtippen. Zur weiteren Anwendung gibt es einen kostenlosen AA90 Assembler (www.atmel.com). Bei mir (s.o.) gibt es auch ein Beispielprogramm 'fm.c', welches auch float benötigt und trotz reiner C-Quelle in den 2313 paßt. Ich hatte seinerzeit meine ersten Versuche mit dem 2313 gemacht, der genau wie bei Dir den 2051 ersetzen sollte. Der Code für einen Tastatudekoder + LCD-Treiber + ser.Multiprozessorschnittstelle auf dem 2051 war mit 2k gerade passend, für den 2313 wollte der C-Compiler zunächst 3k erzeugen. Durch Optimierung und teilweise Codierung in Assembler (wie auch schon beim 2051) passte der Code dann auch in den 2313. So macht man seine Erfahrungen. Die Vorteile waren für mich das interne EEPROM und die Programmierung verschiedener Versionen auf der Leiterplatte. Die serielle Ausgabe (über 4094) aufs LC-Display wurde so schnell, daß bei 62,5kBd keine Warteschleifen mehr eingefügt werden mussten. Ich will hier keine Werbung machen, aber der aktuelle IAR ICCAVR erzeugt sehr guten Code und nutzt bei den ATmega auch die neuen Befehle; das Teil kostet aber auch richtig Knete! Ich rufe die Compiler aus der Kommandozeile auf, was für mich sehr wichtig ist. Ich kann Dir anbieten, Deine Quelle 'mal durch den Compiler zu nudeln und Dir den Output schicken. Michael
Mein Programmchen benutzt gar keine C-Library. Auch keine floats oder solche Sachen. Allerdings eine größere Schachtelungstiefe von if/switch/for etc. Die Variablen, die ich benutze, machen zusammen 20 bis 30 Bytes. Ich habe den GCC in Verdacht, ziemlich resourcenhungrigen Code zu erzeugen?! Grüße, Sebastian
@Michael, 900 Byte klingt gut, beim 2051 sinds 979 Byte. Vielleicht hat doch noch jemand dazu Vergleichszahlen für den AVRGCC ? printf() nehme ich nicht, da ich ja 7-Segment-Kode brauche und kein ASCII. Dein Frequenzmesser sieht interessant aus, ähnelt vom Meßprinzip her meinem mit dem 2051 aufgebautem. Eine Frage, ist das Programm dazu nun in C (wegen float) oder in Assembler ? Das mit den 0,0025 Hz ist aber ein Druckfehler, das wären ja 7 Minuten Meßzeit. Meiner geht von 0,5Hz ... 125MHz, die Auflösung ist 4 Digits bzw. 0,001Hz, die Meßzeit beträgt 0,5s ab >2Hz und erhöht sich bis auf 2s bei 0,5Hz. Als Vorverstärker bzw. Trigger nehme ich den AD8009 und den LT1720. Bei Interesse kann ich mehr dazu auf meine Webseite stellen. Peter
@Peter: 'fm.c' ist reine C-Quelle; Du kannst Dir den .hex-Code ja 'mal auf einen 2313 programmieren. Bei fmeter.htm sind 0,0025Hz kein Druckfehler. Bei 1Hz Eingangsfrequenz bekommt man 7-stellige Ergebnisse: jede Sekunde ein neues! Ich gleiche damit z.B. PCF8583 Uhren ab. Der Vorteiler für 50MHz wird automatisch selektiert. Hier habe ich die Steuerung und Auswertung in C, die Interruptroutinen und Optimierungen (interne Registerverwendung) in Assembler gemacht. Ebenso ist der startup abgemagert - einige Konstanten liegen im EEPROM. Michael
> Ich will hier keine Werbung machen, aber der aktuelle IAR ICCAVR erzeugt sehr guten Code ... Ich will ja hier keine Werbung machen, aber da schmeisst mal wieder jemand Äpfel und Tomaten durcheinander! Was hat denn die Firma IAR Systems mit der Firma Imagecraft zu tun?? ICCAVR stammt von der Firma Imagecraft und nicht von IAR, wie man am Namen schon unschwer erkennen kann (Imagecraft C-Compiler). Und zwischen den Produkten von Imagecraft und denen von IAR Systems liegen Welten. Vielleicht entscheidest du dich erst mal, wofür du hier (Schleich-)werbung machen willst. > Ich habe den GCC in Verdacht, ziemlich resourcenhungrigen Code zu erzeugen?! Auch mal wieder so eine Fehlannahme! Ich würde erst mal schauen welches Flieskommaformat bzw. welche Präzision die Routinen haben, bevor ich anfange die erzeugte Codegrösse zu vergleichen. Wenn ich die Präzision und den Zahlenbereich einer Fliesskommavariablen entsprechend reduziere, bekomme ich naturgemäss auch kompaktere Routinen und damit kompakteren Code (siehe z.B. CodeVision & Konsorten). Wenn man allerdings volle IEEE 754-Präzision haben möchte (float = 4 Byte, double = 8 Byte und long double = 10 Byte), so kostet das natürlich entsprechenden Platz. Leider schreibt der ANSI-Standard hier nichts vor, so dass Hersteller kommerzielle Compiler mit verkrüppelten Fliesskommaroutinen trotzdem noch dieses Schildchen auf den Karton pappen dürfen, was mir persönlich sehr missfällt. Notker
Der avr-gcc unterstützt ohnehin nur 4-Byte floats, double ist identisch zu diesem. Viel mehr erscheint mir persönlich auch kaum sinnvoll; zwei 4-Byte floats als Argumente einer Funktion belegen bereits den kompletten Satz an scratch registers, die definiert sind, also ab 3 Parametern müßte man schon auf den Stack. Anyway, wichtig beim avr-gcc ist, welche Optimierungsoptionen benutzt werden. Wer gedankenlos -O3 schreibt (oder gar sinnloserweise noch größere Zahlen, weil er das Manual nicht gelesen hat und nicht weiß, daß es gar nichts höheres gibt ;-), der wird bestraft. -O3 wird ja vielleicht noch ein bissel schneller als die kleineren Zahlen, aber kleiner wird es absolut nicht, sondern vielmehr recht aufgebläht. Am kleinsten fallen -Os (wie der Name sagt ;-) und -O1 aus, und sie sind bestenfalls nur geringfügig langsamer als die Optimierungsstufen mit der größeren Zahl (d. h. weniger als 10 % selbst bei rechenkritischen Operationen).
Vielleicht ist meine Frage ja ganz dumm ...: Sind im Makefile die linker flags richtig ? #linker flags LDFLAGS = -Wl,-Map=$(TRG).map,--cref -lm Das Fehlen des -lm switches erzeugt Fehlermeldungen über volles flash.
@notker: 'iccavr.exe' ist auch von IAR. Wie man am Namen unschwer erkennen kann kommt ICC von Iar-C-Compiler. Die Version davor hieß 'icca90.exe'. Vielleicht liest Du die Sätze 'mal komplett, ohne gleich loszuwettern. Ich habe noch einmal nachgesehen: float-basisroutinen bei IAR brauchen 638 Byte (gleicher Wert bei zwei verschiedenen Projekten). Internes Format 4 Byte, wie nicht anders zu erwarten.
ftp://ftp.imagecraft.com/pub/pub/iccavrdem.exe Also der ist doch wohl zweifelsohne von Imagecraft, oder? (das "dem" steht übrigens dafür, dass es die Demoversion ist, die Vollversion heisst iccavr.exe. Ich habe den Satz schon richtig gelesen, danke für den Hinweis! Notker
> Der avr-gcc unterstützt ohnehin nur 4-Byte floats, double ist identisch zu diesem. Das halte ich aber für ein Gerücht! Aber ein kurzes Debugging mit dem AVR-Studio an einem Beispielprogramm wird dies schnell klären. > Wer gedankenlos -O3 schreibt (oder gar sinnloserweise noch größere Zahlen, weil er das Manual nicht gelesen hat und nicht weiß, daß es gar nichts höheres gibt ;-), der wird bestraft. Womit denn? Mit Freiheitsstrafe nicht unter 2 Jahren? ;-) Naja, beim "normalen!" gcc gibt es hier schon höhere Zahlen. Notker
> Das halte ich aber für ein Gerücht! Kannst Du gern. Um wieviel möchtest Du wetten? RTFDoc hilft hier übrigens auch, es ist sehr eindeutig beschrieben, daß er nur 32-bit floats kennt. Aber ich gebe zu, wetten wäre unfair, ich habe Heimvorteil. > Naja, beim "normalen!" gcc gibt es hier schon höhere > Zahlen. Woher hast Du denn diese Weisheit? Aus dem Manual oder dem Sourcecode des gcc bestimmt nicht. Vielleicht aus abergläubischen Linux-Makefiles, die von Unwissenden geschrieben worden sind, die sich einbilden, das bloße Aufschreiben von -O99 würde die gcc-Geister beschwören, besseren Code zu produzieren... gcc selbst ignoriert es geflissentlich und nimmt einfach stattdessen mal -O3 an, bis die Leute ja dann vielleicht doch noch RTFM'ed haben...
>Woher hast Du denn diese Weisheit? Aus dem Manual oder >dem Sourcecode des gcc bestimmt nicht. Vielleicht aus >abergläubischen Linux-Makefiles, die von Unwissenden >geschrieben worden sind, die sich einbilden, das bloße >Aufschreiben von -O99 würde die gcc-Geister beschwören, >besseren Code zu produzieren... Sag mal, du trägst hier aber ganz schön dick auf! Also das, was hier drin steht ist also falsch? http://www.fokus.gmd.de/linux/HOWTO/pdf/Assembly-HOWTO.pdf Ich könnte ja jetzt noch in den Sourcen des gcc solange rumsuchen, bis ich etwas gefunden habe, aber ehrlich gesagt, ich finde es langsam etwas müssig, jede fragwürdige Behauptung, die hier gemacht wird, genauer zu untersuchen. Wer es also genau wissen will, soll selbst nachsehen. Notker
Wasichnochsagenwollte: Mit WinAVR hab ich jetzt mein Programmchen problemlos in den A2313 bekommen. Scheint wirklich ein Fortschritt gegenüber V3.0.2 zu sein!! Grüße, Sebastian
man gcc, da steht's weiß auf Schwarz: -O, -O0, -O1, -O2 und -O3. Das Assembler-HOWTO ist also offensichtlich falsch.
@Notker: > Sag mal, du trägst hier aber ganz schön dick auf! Zumindest habe ich die Doku gelesen. ;-) Diese nennt eindeutig nur -O0 (ist identisch zum Weglassen von -O), -O alias -O1, -O2 und -O3. > Also das, was hier drin steht ist also falsch? Ja, zumindest für einen unverpfuschten gcc. Allerdings ist innerhalb des gcc die Variable "optimize" global, und diese bekommt in der Tat die Zahl nach -O zugewiesen, so daß ein einzelner Codegenerator von anderen Levels Gebrauch machen könnte. Der ungepatchte gcc benutzt aber als höchsten Vergleich "optimize >= 2", und genau so ist es auch dokumentiert. UTSL.
> Zumindest habe ich die Doku gelesen. ;-) Diese nennt > eindeutig nur -O0 (ist identisch zum Weglassen von -O), > -O alias -O1, -O2 und -O3. Sorry, -Os habe ich unterschlagen.
Also hier mal ein Codeauszug aus der Source des gcc 3.2: ------------------schnipp-------------------------------- else if (argv[i][0] == '-' && argv[i][1] == 'O') { /* Handle -Os, -O2, -O3, -O69, ... */ <--------!!!! char *p = &argv[i][2]; if ((p[0] == 's') && (p[1] == 0)) { optimize_size = 1; /* Optimizing for size forces optimize to be 2. */ optimize = 2; } ------------------schnapp----------------------------------- Also irgendwie scheinen dort ja doch Levels höher als 3 erkannt und ausgewertet zu werden, oder habe ich heute abend etwas an den Augen??? Level -O6 habe ich im Unix-Bereich schon des öfteren in Sourcen namhafter und renommierter GPL-Software gesehen. Notker
Wenn Du bis dorthin vorgedrungen bist, dann untersuche einfach noch, an welchen Stellen die Variable "optimzize" auch wirklich benutzt wird. Du wirst zu Deinem Erstaunen feststellen, dass der hoechste Vergleich, der irgendwo auftritt, optimize >= 2 ist -- was exakt der Manpage entspricht. Was anderes habe ich auch nicht geschrieben: die Zahl nach -O wird zwar noch geparst, aber alles ab -O3 wird identisch behandelt. Ob mehr oder weniger namhafte ,,Experten'' im Glauben an den Gott der Optimierung dann -O6 schreiben, ist mir egal. Sie werden jedenfalls damit nicht mehr als mit -O3 erreichen, und um auf den Anfang zurueckzukommen, fuer die meisten AVR-Applikationen kann -O3 zu einer massiven Platzverschwendung bei bestenfalls marginaler Verbesserung der Laufzeit fuehren. Siehe Doku, meine Mini-Benchmark-Ergebnisse habe ich dokumentiert.
> Du wirst zu Deinem Erstaunen feststellen, dass der hoechste > Vergleich, der irgendwo auftritt, optimize >= 2 > ist -- was exakt der Manpage entspricht. Nun, dann schauen wir doch mal etwas weiter unten (toplev.c) ... ------------------------schnipp------------------------------- flag_delete_null_pointer_checks = 1; flag_reorder_blocks = 1; } if (optimize >= 3) <---------------!!! { flag_inline_functions = 1; flag_rename_registers = 1; -----------------------schnapp------------------------------- Nun, ich denke, dass DU besser mal einen Blick vorher hier hineingeworfen hättest. Mein lieber Jörg Wunsch, so langsam wird die Sache langweilig. Ich glaube, du suchst dir besser ein anderes Forum mit leichtgläubigerem Publikum aus, wo du dein "Expertenwissen" zum Besten geben kannst. Die Behauptung hier ist wohl auch mal wieder heisse Luft. Notker
Na gut, dann halt >=3, was Jörg wahrscheinlich auch gemeint hat ("...was exakt der Manpage entspricht"), aber größere Werte als 3 machen beim GCC definitiv keinen Unterschied. BTW: Er ist auf dem Gebiet wohl der letzte, in dessen Zusammenhang es angebracht ist "Expertenwissen" in Anführungszeichen zu schreiben...
> BTW: Er ist auf dem Gebiet wohl der letzte, in dessen Zusammenhang es
angebracht ist "Expertenwissen" in Anführungszeichen zu schreiben...
Mag ja alles sein, allerdings finde ich seine Art wenig souverän. Als
tatsächlicher Experte sollte man schon seine Hausaufgaben gemacht haben
und ein etwas diplomatischerer Umgang mit anderen Menschen wäre kein
Luxus.
Notker
Nun, die Hausaufgaben habe ich gemacht. Siehe Andreas' Hinweis, das war ein simpler Schreibfehler -- der Effekt ist exakt der, den ich beschrieben habe: -O3 ist der höchste ,,aus der Dose raus'' unterstützte Level. Daß man dafür natürlich entweder >= 3 oder > 2 schreiben muß, ja klar. Ich hatte meine Hausaufgabe schon vor einer Woche gemacht und daher aus dem Gedächtnis zitiert. Ich wehre mich vor allem gegen diese ,,weil es im HOWTO xyz steht, muß es richtig sein'' Mentalität. Alles spricht dagegen, daß es -O levels > 3 wirklich gibt (die Manpages, der Sourcecode), aber der Glaube an den Gott der Optimierung wirkt stärker... Dabei ist in der Doku zum gcc wirklich recht detailliert beschrieben, welche Stufe welche Optimierungen einschließt. Im Gegensatz zu irgendeinem Howto stammt diese aber von den Autoren/Maintainern.
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.