Hallo, welche Möglichkeiten gibt es um zu erkennen, welche Routinen richtig Platz einnehmen? Ich möchte meinen Bootloader gerne optimieren, weil ich noch ca. 500 Byte benötige aber nur noch 92 frei habe. Es sind mehrere Dateien "included", ich habe nun Angst das der Compiler nicht nur das eingefügt hat was wirklich benötigt wird, sondern auch Sachen die vlt. gar nicht benötigt werden. Wenn ihr noch Tips habt worauf man noch achten sollte um Programmspeicher zu sparen, wäre ich sehr dankbar. Programmiert wird mit "Atmel Studio 7". Grüße AVRli...
:
Bearbeitet durch User
Upps! Sehe ich zum ersten mal... :-( Vielen Dank für den Hinweis, das ist ne Menge Stoff, Sehr schön! :-D Grüße AVRli...
AVRli .. schrieb: > sondern auch > Sachen die vlt. gar nicht benötigt werden. Normalerweise gibt es ein MAP-File, in dem Routinen und ihre Adressen aufgelistet sind, allerdings muss man dem Compiler/Linker/IDE i.A. sagen, dass man das haben möchte. Da findet man dann auch indirekt aufgerufene Routinen, z.B. mathematische Funktionen. Ich habe das z.B. benutzt um zu klären, ob etwa Multiplikation und Division dazugelinkt sind, obwohl ich nur die Multiplikation brauche, usw. usw. Wie man die Division dann los wird ist wieder eine andere Frage. Georg
Danke nochmal für Eure Antworten, es folgt ein kleines Feedback... Habe mich mit dem Thema befasst und mir in erster Linie das MAP File angesehen. Das ist ja wirklich erstaunlich was da so zusammen kommt. ;-) Mir sind Funktionen aufgefallen, die aus Bequemlichkeit mehr Platz einnehmen, als direkte Zugriffe. Als Beispiel das setzen der Baudrate für den UART. Da habe ich eine Funktion für übernommen, welche die Werte für das UBRR aus der übergebenen Baudrate berechnet. Was zwar total bequem ist aber der Wert ändert sich ja bei meinem Projekt nicht also weise ich das Register nun mit konstanten Werten zu. Das MAP File war für mich der Schlüssel und die nun abschließende "-Os Optimierung" bescheren mir 1003 Byte mehr Platz, den ich wirklich sehr gut gebrauchen kann! Schöne Grüße, AVRli...
Morgen, So etwas wie die Berechnung des Baudraten Registers, kann man gut als preprozessor Makro machen. Dann kostet es keinen Speicher und du kannst den Wert trotzdem einfach anpassen. Vielleicht gibt es noch mehr Stellen, am den du so optomieren kannst.
Harald schrieb: > https://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung Wer einen gcc benutzt, der nicht aus dem tiefsten Mittelalter stammt, kann auch noch
1 | -flto |
benutzen.
AVRli .. schrieb: > Als Beispiel das setzen der Baudrate für den UART. Denk dran: Optimieren lohnt sich nur bei großen Teilen. Wenn Du eine Funktion, die direkt und indirekt weniger als 5 % Speicherplatz benötigt, um 50 % optimierst, hast Du weniger davon, als wenn Du eine Funktion, die 20 % belegt, um 15 % optimierst.
(s)printf() ist auch ein Speicherfresser. Man kann aber gut drauf verzichten. Es ist erst mal sehr universell und die Programmiererei geht schnell damit. Es gibt Leute, die verwenden das prinzipiell gar nicht. Ich benutze es und weiss: im Fall der Fälle ist dort noch 0,5kB zu holen. Ab und zu kommt das vor.
AVRli .. schrieb: > Danke nochmal für Eure Antworten, es folgt ein kleines Feedback... > > Habe mich mit dem Thema befasst und mir in erster Linie das MAP File > angesehen. Das ist ja wirklich erstaunlich was da so zusammen kommt. ;-) > > Mir sind Funktionen aufgefallen, die aus Bequemlichkeit mehr Platz > einnehmen, als direkte Zugriffe. > > Als Beispiel das setzen der Baudrate für den UART. Da habe ich eine > Funktion für übernommen, welche die Werte für das UBRR aus der > übergebenen Baudrate berechnet. Was zwar total bequem ist aber der Wert > ändert sich ja bei meinem Projekt nicht also weise ich das Register nun > mit konstanten Werten zu. Sowas macht man in C++ mit constexpr-Funktionen, also einer Berechnung zur Compilezeit. Zur Laufzeit ist davon nichts(!) mehr übrig ausser dem Wert.
Danke für Eure ganzen weiterenHinweise, so langsam wird es! H.Joachim S. schrieb: > (s)printf() ist auch ein Speicherfresser. Da weiß ich wieder nicht, wie man das bedient. Alles was dazu hängen geblieben ist, es lieber nicht zu benutzen. Also ich kenne nur den Weg Zeichenketten und Zahlen und was man so hat, über einen eigenen Buffer über den UART oder sonst was auszugeben. Einmal hatte ich mal, bei einem anderen Projekt, auf Float gesetzt, das vermeide ich nun auch und rechne immer mit ganzen Zahlen. Ich bin aktuell mit dem Ergebnis der Codegröße zufrieden, was nicht heißen soll das es perfekt ist. Aber erst durch die Aktion ahbe ich gelernt, wie es im Programmspeicher dann letztendlich aufgebaut ist und das wir den Entwicklern der Compiler doch einiges zu danken haben! Grüße, AVRli...
Wilhelm M. schrieb: > Sowas macht man in C++ mit constexpr-Funktionen, also einer Berechnung > zur Compilezeit. Zur Laufzeit ist davon nichts(!) mehr übrig ausser dem > Wert. Das kann man in C auch haben, wenn der Compiler nicht zu blöde ist.
S. R. schrieb: > Wilhelm M. schrieb: >> Sowas macht man in C++ mit constexpr-Funktionen, also einer Berechnung >> zur Compilezeit. Zur Laufzeit ist davon nichts(!) mehr übrig ausser dem >> Wert. > > Das kann man in C auch haben, wenn der Compiler nicht zu blöde ist. Suchen und Sortieren zur definitiv Compilezeit in C? no way ...
Wilhelm M. schrieb: >> Das kann man in C auch haben, wenn der Compiler nicht zu blöde ist. > Suchen und Sortieren zur definitiv Compilezeit in C? no way ... Die UBRR-Register aus Compiletimekonstanten ausrechnen lassen? Sicher doch, macht mein Code schon immer. Ich hab nie behauptet, dass ein C-Compiler die Mächtigkeit von C++ erreicht. Aber in diesem Fall reicht auch das weniger scharfe Schwert.
AVRli .. schrieb: > Als Beispiel das setzen der Baudrate für den UART. Da habe ich eine > Funktion für übernommen, welche die Werte für das UBRR aus der > übergebenen Baudrate berechnet. Wilhelm M. schrieb: > Suchen und Sortieren zur definitiv Compilezeit in C? no way ... Wie kommst du von "UBRR aus Baudrate berechnen" auf "Suchen und Sortieren"? Der Zusammenhang erschließt sich mir nicht wirklich.
Falles du es nicht eh schon machst. Den Compiler auf Codegröße optimieren lassen (gcc -Os) Details: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
S. R. schrieb: > Wilhelm M. schrieb: >>> Das kann man in C auch haben, wenn der Compiler nicht zu blöde ist. >> Suchen und Sortieren zur definitiv Compilezeit in C? no way ... > > Die UBRR-Register aus Compiletimekonstanten ausrechnen lassen? Sicher > doch, macht mein Code schon immer. Für derart einfache Funktionen kann der Compiler oft eine const -> const Transformation macht, das stimmt. Mir geht es aber darum, dass er es machen muss(!), wenn ich das will, bzw. ich einen Compilezeitfehler bekommen, wenn es nicht möglich ist. Und das schaffe ich nur bei C++ mit constexpr-Funktionen in einem constexpr-Kontext.
Wolfgang schrieb: > AVRli .. schrieb: >> Als Beispiel das setzen der Baudrate für den UART. Da habe ich eine >> Funktion für übernommen, welche die Werte für das UBRR aus der >> übergebenen Baudrate berechnet. > > Wilhelm M. schrieb: >> Suchen und Sortieren zur definitiv Compilezeit in C? no way ... > > Wie kommst du von "UBRR aus Baudrate berechnen" auf "Suchen und > Sortieren"? Der Zusammenhang erschließt sich mir nicht wirklich. Geschrieben war: > Wilhelm M. schrieb: >> Sowas macht man in C++ mit constexpr-Funktionen, also einer Berechnung >> zur Compilezeit. Zur Laufzeit ist davon nichts(!) mehr übrig ausser dem >> Wert. > Das kann man in C auch haben, wenn der Compiler nicht zu blöde ist. Und genau das kann der C-Compiler nicht, weil er keine constexpr-Funktionen kennt. Als Gegenbeispiel habe ich dann Suchen und Sortieren gebracht.
Wilhelm M. schrieb: > Als Gegenbeispiel habe ich dann Suchen und > Sortieren gebracht. Warum sollte ich per constexpr Suchen und Sortieren wollen? Wenn ich was sortieren möchte, schreib' ich's doch besser gleich sortiert hin, dann ist das deutlich übersichtlicher. Und wenn ich etwas suchen will, das sich bereits zur Compilezeit finden lässt, dann kann ich das Suchergebnis doch auch gleich hinschreiben? Nicht falsch verstehen: ich bin von constexpr und template metaprogramming durchaus beeindruckt, nur von deinen Beispielen nicht ;).
Markus F. schrieb: > Wilhelm M. schrieb: >> Als Gegenbeispiel habe ich dann Suchen und >> Sortieren gebracht. > > Warum sollte ich per constexpr Suchen und Sortieren wollen? > > Wenn ich was sortieren möchte, schreib' ich's doch besser gleich > sortiert hin, dann ist das deutlich übersichtlicher. > > Und wenn ich etwas suchen will, das sich bereits zur Compilezeit finden > lässt, dann kann ich das Suchergebnis doch auch gleich hinschreiben? > > Nicht falsch verstehen: ich bin von constexpr und template > metaprogramming durchaus beeindruckt, nur von deinen Beispielen nicht > ;). Och, das brauchst Du auch nicht. Kommt häufiger vor als Du denkst: Du modellierst bspw. einen Timer, dafür hast Du sicher auch irgendwie eine Tabelle der möglichen Prescaler. In der einen Anwendung möchtest bspw. das Prescaler/Grenzregisterpärchen haben mit dem kleinsten möglichen Precaler, in einer anderen mit dem größten oder irgendwelche anderen Randbedingungen. Schon hast Du ein derartiges Problem.
:
Bearbeitet durch User
Du verallgemeinerst ein ziemlich kleines Problem, was in C problemlos zur compilezeit lösbar ist (UBRR-Registerwerte anhand von Baudrate und CPU-Frequenz ausrechnen), auf etwas, was in C definitiv nicht möglich ist (suchen und sortieren). Das ist der erste Fehler. Der zweite Fehler ist - meiner Meinung nach - eine massive Übermodellierung von Kleinkram, der nur durch enormen Einsatz von Compilerfähigkeiten handhabbar ist. Es ist schon ziemlich beeindruckend, wenn aus 20 kLOC vollgenerischem Quelltext ein nur wenige zig Bytes großes Binary rausfällt... aber irgendwie habe ich dabei dann immer das Gefühl, dass eigentlich das falsche Problem gelöst wurde.
Auch schön zur Visualisierung von Codegrößen in einem fertigen elf ist das Script elfsize aus diesem Projekt https://github.com/ARMmbed/mbed-os-linker-report Matthias
S. R. schrieb: > Du verallgemeinerst ein ziemlich kleines Problem, was in C problemlos > zur compilezeit lösbar ist (UBRR-Registerwerte anhand von Baudrate und > CPU-Frequenz ausrechnen), auf etwas, was in C definitiv nicht möglich > ist (suchen und sortieren). Nochmal: in C darf der Compiler das zur Compilezeit machen (as-if-rule), in C++ kann ich ihn mit einer constexpr-function in einem constexpr-Kontext dazu zwingen. Und ich brauche dafür keine untyped/unscoped-Präprozessormakros. Das mit Suchen/Sortieren sollte nur nochmal diesen Unterschied deutlicher machen. Gewissermaßen um nochmal dem Einwand vorzubeugen: ja aber bei mir hat er doch die Funktion für die Baud-Rate mit einem Literal-Argument auch zur Compilezeit ausgewertet. Bei einer komplizierteren Funktion (Suchen/Sortieren) würde der C-Compiler das nicht mehr einfach so machen. Mit constexpr kann ich ihn aber dazu zwingen sofern überhaupt möglich. Und gerade dieses Feature (constexpr) ist etwas, was auch jeder C-Programmierer nutzen kann, wenn er denn ein C++-Compiler verwendet. > Das ist der erste Fehler. Sehe ich nicht so. Siehe oben. > Der zweite Fehler ist - meiner Meinung nach - eine massive > Übermodellierung von Kleinkram, der nur durch enormen Einsatz von > Compilerfähigkeiten handhabbar ist. Das die Qualifizierung einer Funktion oder eines lvalue mit constexpr findest Du einen "massiven Einsatz con Compilerfähigkeiten"? Gerade das ist doch ein wunderschönes Beispiel, was völlig unspektakulär daherkommt. > Es ist schon ziemlich beeindruckend, wenn aus 20 kLOC vollgenerischem > Quelltext ein nur wenige zig Bytes großes Binary rausfällt... aber > irgendwie habe ich dabei dann immer das Gefühl, dass eigentlich das > falsche Problem gelöst wurde. Wo hatten wir gerade die 20kLOC? Und ich habe bei machen Problemen, das Gefühl, das man sie mit C nur auf dem falschen Wege lösen kann ...
:
Bearbeitet durch User
> Nochmal: in C darf der Compiler das [Baudraten berechnen] > zur Compilezeit machen (as-if-rule), Das tut er für solche Sachen auch. > in C++ kann ich ihn mit einer constexpr-function in einem > constexpr-Kontext dazu zwingen. Das ist aber schön. > Und ich brauche dafür keine > untyped/unscoped-Präprozessormakros. Stimmt. Ist nur am Thema vorbei. > Das mit Suchen/Sortieren sollte nur nochmal diesen Unterschied > deutlicher machen. Wie lieb von dir, leider ging es darum nicht. > Gewissermaßen um nochmal dem Einwand vorzubeugen: ja > aber bei mir hat er doch die Funktion für die Baud-Rate mit einem > Literal-Argument auch zur Compilezeit ausgewertet. Hat er ja auch, erstaunlich gut sogar. :-) > Bei einer komplizierteren Funktion (Suchen/Sortieren) würde der > C-Compiler das nicht mehr einfach so machen. Nur muss ich für die fixe UBRR-Berechnung, um die es hier ging, weder suchen noch sortieren. > Mit constexpr kann ich ihn aber dazu > zwingen sofern überhaupt möglich. Stimmt. Im Normalfall wendet man Such- und Sortieralgorithmen aber auf Eingangsdaten an, und die sind zur Compilezeit eher selten bekannt. > Und gerade dieses Feature (constexpr) ist etwas, was auch jeder > C-Programmierer nutzen kann, wenn er denn ein C++-Compiler verwendet. Allerdings programmiert der C-Programmierer dann kein C mehr, sondern C++. Und da gibt es durchaus subtile Unterschiede, die man kennen sollte, wenn man mindestens eine der beiden Sprachen gut kann. >> Der zweite Fehler ist - meiner Meinung nach - eine massive >> Übermodellierung von Kleinkram, der nur durch enormen Einsatz von >> Compilerfähigkeiten handhabbar ist. > > Das die Qualifizierung einer Funktion oder eines lvalue mit constexpr > findest Du einen "massiven Einsatz con Compilerfähigkeiten"? Gerade das > ist doch ein wunderschönes Beispiel, was völlig unspektakulär > daherkommt. Nö, ich bezog mich eigentlich auf eine Codebase, mit der ich öfter zu tun habe, sowie deine gelegentlichen Beispiele. >> Es ist schon ziemlich beeindruckend, wenn aus 20 kLOC vollgenerischem >> Quelltext ein nur wenige zig Bytes großes Binary rausfällt... aber >> irgendwie habe ich dabei dann immer das Gefühl, dass eigentlich das >> falsche Problem gelöst wurde. > > Wo hatten wir gerade die 20kLOC? Ich wollte damit nur illustrieren, dass mir constexpr und auch ein paar andere C++-Fähigkeiten durchaus bekannt sind. > Und ich habe bei machen Problemen, das Gefühl, das man sie mit C nur auf > dem falschen Wege lösen kann ... Das ist richtig, denn C ist nicht die perfekte Sprache für alle Probleme. Das ist C++ aber auch nicht.
:
Bearbeitet durch User
Wilhelm M. schrieb: > Kommt häufiger vor als Du denkst: Du modellierst bspw. einen Timer, > dafür hast Du sicher auch irgendwie eine Tabelle der möglichen > Prescaler. In der einen Anwendung möchtest bspw. das > Prescaler/Grenzregisterpärchen haben mit dem kleinsten möglichen > Precaler, in einer anderen mit dem größten oder irgendwelche anderen > Randbedingungen. Schon hast Du ein derartiges Problem. Das geht ja selbst in Assembler ziemlich problemlos. Übrigens natürlich mit Fehlermeldung zu Compile- (also: eigentlich Assemble-) Zeit, wenn's keine Lösung gibt. Und natürlich geht es auch in C, "von aussen" gesehen als "Funktions-Makros" sogar eleganter, das ist in der Implementierung der Makros selber allerdings deutlich schreibaufwendiger als im Asm-Stil. Aber auch in C geht der Asm-Stil. Umgekehrt kann man zumindest in einigen Assemblern auch "Funktions-Makros" im C-Stil schreiben. Zusammenfassung: Es geht in Asm und es geht in C. In beiden Sprchen geht es auf zwei Arten. Also kein Problem. Ganz sicher jedenfalls keins, zu dessen Lösung man zwingend C++ benötigen würde...
S. R. schrieb: >> Nochmal: in C darf der Compiler das [Baudraten berechnen] >> zur Compilezeit machen (as-if-rule), > > Das tut er für solche Sachen auch. Auch bei -O0 ? Bei jedem Compiler? >> in C++ kann ich ihn mit einer constexpr-function in einem >> constexpr-Kontext dazu zwingen. > > Das ist aber schön. Genau: s.o. >> Und ich brauche dafür keine >> untyped/unscoped-Präprozessormakros. > > Stimmt. Ist nur am Thema vorbei. Auf keinen Fall: denn an dieser Stelle der Diskussion kommt dann der Einwand, man könnte dasselbe auch in C mit dem Präprozessor machen. Was sehr begrenzt stimmt, jedoch eben auch die genannten anderen Nachteile mit sich bringt. >> Mit constexpr kann ich ihn aber dazu >> zwingen sofern überhaupt möglich. > > Stimmt. Im Normalfall wendet man Such- und Sortieralgorithmen aber auf > Eingangsdaten an, und die sind zur Compilezeit eher selten bekannt. Nö. An dieser Stelle der Diskussion kommt dann der Einwand, dass man solche Berechnungen dann mit weiten Tools oder Skripte im build-Prozess machen könnte. Kann man, jedoch erzeugt man m.E. dadurch wesentlich mehr Komplexität, als es auf direktem Wege zu machen. >> Und gerade dieses Feature (constexpr) ist etwas, was auch jeder >> C-Programmierer nutzen kann, wenn er denn ein C++-Compiler verwendet. > > Allerdings programmiert der C-Programmierer dann kein C mehr, sondern > C++. Und da gibt es durchaus subtile Unterschiede, die man kennen > sollte, wenn man mindestens eine der beiden Sprachen gut kann. Ja, das prominenteste ist type-punning via unions, was dann in C++ UB und in C ein implementation-defined behaviour liefert, und das wiederum ist recht vielen nicht bewusst, wie viele Diskussionen hier zeigen. >>> Der zweite Fehler ist - meiner Meinung nach - eine massive >>> Übermodellierung von Kleinkram, der nur durch enormen Einsatz von >>> Compilerfähigkeiten handhabbar ist. >> >> Das die Qualifizierung einer Funktion oder eines lvalue mit constexpr >> findest Du einen "massiven Einsatz con Compilerfähigkeiten"? Gerade das >> ist doch ein wunderschönes Beispiel, was völlig unspektakulär >> daherkommt. > > Nö, ich bezog mich eigentlich auf eine Codebase, mit der ich öfter zu > tun habe, sowie deine gelegentlichen Beispiele. Nur ging es weder um Deine Codebase, die keiner kennt, noch um irgendwelche anderen Beispiele meinerseits, sondern um ein Konzept namens constexpr. >>> Es ist schon ziemlich beeindruckend, wenn aus 20 kLOC vollgenerischem >>> Quelltext ein nur wenige zig Bytes großes Binary rausfällt... aber >>> irgendwie habe ich dabei dann immer das Gefühl, dass eigentlich das >>> falsche Problem gelöst wurde. >> >> Wo hatten wir gerade die 20kLOC? > > Ich wollte damit nur illustrieren, dass mir constexpr und auch ein paar > andere C++-Fähigkeiten durchaus bekannt sind. Und dazu brauchst Du 20kLOC? >> Und ich habe bei machen Problemen, das Gefühl, das man sie mit C nur auf >> dem falschen Wege lösen kann ... > > Das ist richtig, denn C ist nicht die perfekte Sprache für alle > Probleme. Das ist C++ aber auch nicht. Vor allem nicht für jeden Einsatzzweck. Doch für system- und/oder hardware-nahe SW ist für mich C++ nah dran (und wird m.E. immer besser).
Wilhelm M. schrieb: > Ja, das prominenteste ist type-punning via unions, was dann in C++ UB > und in C ein implementation-defined behaviour liefert, und das wiederum > ist recht vielen nicht bewusst, wie viele Diskussionen hier zeigen. Ja, sonst funktioniert der Garbage-Collector nicht mehr richtig...
Nach meiner Beobachtung sind in den letzten Jahren in den C++ Standard auch Neuerungen dazugekommen, die gerade für Hardware mit limitierten Resourcen gut sind. z.B. constexpr, move Operationen, static_assert, unique_ptr Hier wird ja um die Sinnhaftigkeit von Sortieren zur Compilezeit gestritten. Ich möchte noch zwei Beispiele hinzufügen, die Entwickler mit C Erfahrung wahrscheinlich naheliegender sind. Es werden Fixkommazahlen für ein Filter verwendet, weil die HW keine FPU hat. Es wäre aber trotzdem schön, wenn man die Filterkoeffizienten direkt aus einem Tool als float angeben kann. Hier kann man mit constexpr diese garantiert zur Compilezeit umrechnen und damit sicherstellen, dass keine float Bibliothek im Binary gelinkt wird. Constexpr zusammen mit static_assert erlaubt es bei Parametern zur Compilezeit Bedinungen zu prüfen. Beispiel ist eine Bibliothek, wo ein Teiler als Konstante angegeben werden kann, dieser aber ein Vielfaches von 4 sein muss (oder auch komplexere Bedingungen). Mit static_assert würde der Entwickler dann eine Fehlermeldung bekommen, wenn diese Vorgaben nicht erfüllt sind.
Beitrag #5400332 wurde vom Autor gelöscht.
Wilhelm M. schrieb: > S. R. schrieb: >>> Nochmal: in C darf der Compiler das [Baudraten berechnen] >>> zur Compilezeit machen (as-if-rule), >> >> Das tut er für solche Sachen auch. > > Auch bei -O0 ? Bei jedem Compiler? Aus welchem Popo ziehst du denn jetzt die Annahme?
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.