Ich plane, ein Arduino programmierbares Brett zu verwenden. Diese haben ziemlich begrenzte Flash-Speicher im Bereich zwischen 16 und 128 kB, um kompilierten C- oder C ++ - Code zu speichern.
Gibt es Möglichkeiten, zu schätzen, wie viel (Standard) Code es darstellt?
Ich nehme an, das ist sehr vage, aber ich suche nur nach einer Größenordnung.
Die Ausgabe des Befehls size
ist ein guter Ausgangspunkt, aber Sie erhalten nicht alle Informationen, die Sie benötigen.
Die Größe Ihres Bildes ist normalerweise ein wenig mehr als die Summe des Textes und der Datenabschnitte. Der BSS-Abschnitt ist im Wesentlichen komprimiert, da es sich um Nullen handelt. Es kann andere Abschnitte geben, die relevant sind, die nicht nach Größe aufgeführt sind.
Wenn Ihr Build-System so eingerichtet ist, wie es zuvor für AVR-Mikrocontroller verwendet wurde, erhalten Sie eine * .elf-Datei sowie eine * .bin-Datei und möglicherweise eine * .hex-Datei. Die * .bin-Datei ist das eigentliche Bild, das im Programm-Flash des Prozessors gespeichert wird. Sie können also anhand seiner Größe feststellen, wie Ihr Programm wächst, wenn Sie Änderungen daran vornehmen. Die * .bin-Datei wird mit dem Befehl objdump aus der * .elf-Datei und einigen Flags extrahiert, an die ich mich momentan nicht erinnern kann.
Wenn Sie wissen wollen, wie Sie Ihren C- oder C ++ - Code beim Kompilieren erraten können, ist das viel schwieriger. Ich habe einen 10x-Blowup in einer Funktion beobachtet, als ich versuchte, ein uint64_t statt eines uint32_t zu verwenden, als alles, was ich tat, es inkrementierte (das war ungefähr 5 mal mehr Code, als ich dachte). Dies war hauptsächlich damit zu tun, dass die avr-Optimierungen von gcc nicht die besten sind, aber kleinere Änderungen in der Code-Größe können aus scheinbar harmlosem Code entstehen.
Dies wird wahrscheinlich mit der Verwendung von C ++ verstärkt werden, was dazu neigt, mehr Dinge zu verbergen, die in Code umgewandelt werden als C. Die wichtigsten Dinge, die C ++ versteckt, sind Destruktoraufrufe und viele Zeigerdereferenzierungen, die mit dem this
-Zeiger in Objekten zu tun haben, sowie ein geheimer Zeiger, den viele Objekte auf ihre virtuelle Funktionstabelle und ihre statischen Klassenvariablen haben.
Bei AVR ist es wahrscheinlich, dass sich all diese Pointer-Stuffs wirklich addieren, weil Pointer doppelt so groß wie Register sind und mehrere Befehle zum Laden benötigen. Auch AVR hat nur ein paar Registerpaare, die als Zeiger verwendet werden können, was dazu führt, dass viele Dinge in diese Register hinein und aus ihnen heraus bewegt werden.
Einige Tipps für kleine Programme auf AVR:
Verwenden Sie uint8_t
und int8_t
anstelle von int
, wann immer Sie können. Sie können auch uint_fast8_t
und int_fast8_t
verwenden, wenn Sie möchten, dass Ihr Code portabel ist. Dies kann dazu führen, dass viele Operationen nur halb so viel Code belegen, weil int
zwei Bytes ist.
Seien Sie sich über Dinge wie String- und Struct-Konstanten und Literale und wie / wo sie gespeichert sind sehr bewusst.
Wenn Sie keine Angst davor haben, lesen Sie die AVR Montageanleitung. Sie können sich eine Vorstellung von den Arten von Anweisungen machen und daraus den Typ von C-Code, der diesen Anweisungen leicht zugeordnet werden kann. Verwenden Sie diese Art von C-Code.
Das kannst du nicht wirklich sagen. Die Länge des nicht kompilierten Codes hat wenig mit der Länge des kompilierten Codes zu tun. Zum Beispiel:
%Vor%vs
%Vor%Beide sind genau die gleiche Anzahl von Zeilen und erzeugen die gleiche Ausgabe, aber das erste Beispiel beinhaltet eine Instanziierung von std :: sort, die wahrscheinlich eine Größenordnung mehr Code als der Rest des Codes hier ist. p>
Wenn Sie die Anzahl der im Programm verwendeten Bytes unbedingt zählen müssen, verwenden Sie Assembler.
Laden Sie die arduino IDE herunter und verifizieren Sie Ihren vorhandenen Code oder sehen Sie sich die Beispielskizzen an. Es wird Ihnen sagen, wie viele Bytes dieser Code enthält, was Ihnen eine Vorstellung davon gibt, wie viel mehr Sie in ein bestimmtes Gerät passen können. Wenn Sie ein paar Beispiele zufällig auswählen, ist das Beispiel Webserver 5816 Byte und das LCD Hallo Welt ist 2616. Beide verwenden externe Bibliotheken.
Versuchen Sie, eine vereinfachte Version Ihrer App zu erstellen, indem Sie sich zuerst auf das wertvollste Feature konzentrieren und dann das "nette (und coole) Zeug hinzufügen". Behalten Sie die Byte-Verwendung in der Arduino IDE im Auge, wenn Sie Ihren Code verifizieren.
Als grober Hinweis benötigt meine erste App (LED-Flasher, die von einem Push-Buttun gesteuert wird) 1092 Bytes. Das ist ungefähr 1K von 32k. Ziemlich kleiner Fußabdruck für C ++ - Code!
Was mich am meisten beunruhigt, ist die begrenzte Menge an RAM (1 Kb). Wenn der CPU-Stack etwas davon mitnimmt, bleibt nicht viel übrig, um irgendwelche Datenstrukturen zu erzeugen.
Ich hatte erst seit 48 Stunden meinen Arduino, also gibt es noch eine Menge, um ihn effektiv zu benutzen ;-) Aber es macht sehr viel Spaß, ihn zu benutzen:).
Es ist ziemlich viel für eine ziemlich komplexe Software, aber Sie werden anfangen, an das Limit zu stoßen, wenn Sie wollen, dass es viele verschiedene Funktionen hat. Wenn Sie eine große Menge statischer Zeichenketten und Daten speichern möchten, kann dies sehr schnell passieren. Aber 32 KB ist eine anständige Menge für eingebettete Anwendungen. Es ist eher RAM, mit dem du zuerst Probleme hast!
Außerdem sind die C ++ - Compiler für eingebettete Systeme oft sehr viel schlechter als die C-Compiler. Das heißt, sie sind nirgends so gut wie C ++ - Compiler für die gängigen Desktop-Betriebssysteme (was die Erstellung eines effizienten Maschinencodes für die Zielplattform betrifft).
In einem Linux-System können Sie einige Experimente mit statischen kompilierten Beispielprogrammen durchführen. ZB
%Vor%Die Größen sind in Bytes angegeben. Diese Ausgabe ist unabhängig vom ausführbaren Dateiformat, da die Größe der verschiedenen Abschnitte innerhalb des Dateiformats liegt. Der Textbereich enthält den Maschinencode und den Befehl stufff. Der Datenbereich enthält Daten zur statischen Initialisierung von Variablen. Die Größe von bss ist die Größe nicht initialisierter Daten - natürlich müssen nicht initialisierte Daten nicht in der ausführbaren Datei gespeichert werden.)
Nun, busybox enthält eine Menge Funktionalität (wie alle gängigen Shell-Befehle, eine Shell etc.).
Wenn Sie eigene Beispiele mit gcc -static verknüpfen, denken Sie daran, dass Ihre verwendete libc die Programmgröße drastisch erhöhen kann und dass die Verwendung einer eingebetteten libc viel platzsparender ist.
>Um zu testen, dass Sie die Diät-libc oder uclibc und verlinken dagegen. Tatsächlich wird busybox normalerweise mit uclibc verbunden.
Beachten Sie, dass die Größen, die Sie auf diese Weise erhalten, nur eine Größenordnung ergeben . Zum Beispiel verwendet Ihre Workstation wahrscheinlich eine andere CPU-Architektur als die Arduino-Platine, und der Maschinencode unterschiedlicher Architektur kann sich mehr oder weniger in seiner Größe unterscheiden (aufgrund von Operandengrößen, verfügbaren Befehlen, Opcode-Codierung und so) >
Um mit grobe Größenordnung Argumentation fortzufahren, enthält busybox grob 309 Tools (einschließlich ftp-Daemon und solche Sachen), dh die durchschnittliche Code-Größe eines Busybox-Tools beträgt ungefähr 5k.