Hallo,
habe inzwischen ein relativ großes Programm für den Atmega8 geschrieben
(in C). Und ich bin an der Grenze des Flash Speichers angekommen. Jetzt
versuche ich den Code zu komprimieren... Gibt es da allgemeine Tricks
und Tipps... in der Richtung "statt Switch Case eine For Schleife
verwenden" oder so?
Ich möchte in meinem Programm u.a. Int in Strings konvertieren und
Strings nach float. Dazu verwende ich itoa und atof... Wenn ich atof
einsetze belegt mein Programm aber 1kB mehr Speicher! Kann das sein?
Das Problem ist, ich habe eine Zahl in einem String die ich mit einer
anderen Zahl multiplizieren muss und anschliessend auf einem LCD
ausgebe.
Gäbe es da noch andere Wege außer atof und dann zurück in einen String?
Johnny
Johnny66 schrieb:> float
Wenn du die float-Rechnungen durch Festkommaarithmetik ersetzen kannst
gewinnst du viel Ressourcen. Die Float-Funktionen brauchen recht viel
Speicher.
:-)
Johnny66 schrieb:> Ich möchte in meinem Programm u.a. Int in Strings konvertieren und> Strings nach float. Dazu verwende ich itoa und atof...
Hä ???
Wie wärs einfach mit:
@Floh: ja, das ist eine Idee, danke!
@Peter: da habe ich mich nicht gut ausgedrückt, sorry. Das ist nicht
eine Zahl, da gehts um zwei "Baustellen"... einmal will ich eine Int in
einen String konvertieren und an einer anderen Stell möcht ich eine
float aus einem String lesen.
Achja... wenn ich das richtig gesehen habe, dann ist der Atmega168
identisch wie der Atmega8 aufgebaut... nur mit doppelt so großen Flash
Speicher. D.h. ich brauche in meiner Schaltung und in meinem Programm
nichts ändern und kann den µC einfach ersetzen?
Wenn ich das Programm nicht komprimiert bekomme werde ich das
wahrscheinlich machen müssen...
Trotzdem interessiert es mich, wie man so programmiert dass man wenig
Speicher belegt.
Johnny66 schrieb:> Achja... wenn ich das richtig gesehen habe, dann ist der Atmega168> identisch wie der Atmega8 aufgebaut... nur mit doppelt so großen Flash> Speicher. D.h. ich brauche in meiner Schaltung und in meinem Programm> nichts ändern und kann den µC einfach ersetzen?
So einfach ist es leider nicht. Der Atmega8 und der Atmega168 sind nur
pinkompatibel. Das heißt du kannst deine Schaltung schonmal behalten.
Allerdings sind sie nicht binärkompatibel. Das heißt du wirst Codeteile
portieren müssen. Welche das sind, siehst du in der Appnote AVR094 [1].
Das ist zwar die Portierung von Mega8 auf Mega88, aber der Mega168 ist
zum Mega88 binärkompatibel. Praktisch heißt das Portieren zum Schluss
meist nicht mehr als ein paar Registernamen/Bitnamen und
Interruptvektoren im Quelltext anpassen.
[1] http://www.atmel.com/dyn/resources/prod_documents/doc2553.pdf
Gruß Skriptkiddy
> Trotzdem interessiert es mich, wie man so programmiert dass man wenig> Speicher belegt.
Schlaumeierantwort: In dem man aufgeblasenen Code durch schlankeren Code
ersetzt.
S.o. Floatingpoint statt Fixkomma.
Weniger oder kürzere Textmeldungen benutzen. Texte splitten und
Recyclen.
Funktionen zu inlinen statt statisch definieren, wenn Funktionen
vorhanden sind, die sich dafür eignen. Aufruftiefe eher flach halten.
Schlankere Datentypen verwenden. Lokale Variablen bevorzugen.
Externe Libraries unter die Lupe nehmen und granularer machen, damit der
Linker unbenutzte Funktionen weglassen kann.
Wertetabellen durch Näherungsfunktionen ersetzen. Oder Funktionen durch
Tabellen ersetzen. Geforderte Genauigkeit überdenken und
Tabellen/Formeln anpassen.
Softwarefunktionen durch Hardwarefunktionen ersetzen.
PAP überarbeiten und verschlanken. Features weglassen.
Danke!
@Seltsam: wenn ich externe Dateien mit Funktionen einbinde, dann werden
doch nur die Funktionen eingebunden, die ich wirklich brauche oder?
Und die Variablem werden doch im RAM abgelegt oder? Bringt das was für
den Flash, wenn ich z.B. statt long int, short int verwende?
WinAVR-Toolchain:
Der Linker arbeitet auf der Ebene der Objektdateien. Wenn du in einer
Objektdatei die Funktionen foo() und bar() hast, aber nur foo() benutzt,
kann bar() als toter Code in deinem Programm landen. Und Libraries (*.a)
Dateien sind Archive von Objektdateien. Diese Situation kannst du mit
dem MAP und dem LSS File einfach feststellen.
Die Initialwerte von globalen und statischen Variablen müssen auch im
Flash vorhanden sein. Der Startupcode initialisiert die Variablen mit
den Werten aus dem Flash. Ob das beim Defaultwert (0) ebenso ist, weiss
ich nicht aus dem Stegreif. Ich vermute, dass nur die Werte ungleich
Defaultwert iM Flash gespeichert sind und es für den Defaultwert eine
Ausnullschleife im Startup gibt.
Abhängig von deinem Programm solltest du wo möglich short int statt long
int benutzen. Noch besser wäre es, wenn du auf 8-Bit gehen kannst wo
möglich. Du sparst Platz bei den Initialwerten und beim Code. Um
16-Bit zu verarbeiten sind deutlich mehr Register (=> PUSH/POP) und
Verarbeitungscode erforderlich als für 8-Bit Werte. Aufpassen: Bei der
Umstellung Programm peinlich genau aut Integerüberläufe prüfen!
Die Zeit, die du damit verbringst, Deinen Code zu "komprimieren", kostet
Dich viel mehr, als den µC mit größerem Flash zu kaufen.
Es sei denn, Du willst den µC verkaufen und musst die Software da
irgendwie reinquetschen.
Andersrum geht beim "Komprimieren" häufig die Uberschaubarkeit und
Struktur des Codes soweit kaputt, dass man den Code danach sowieso nicht
mehr warten kann.
Daher meine Empfehlung: Sauber Programmieren und wenn's nicht reicht,
den nächstgrößeren µC einsetzen.
uitrg789 schrieb:> Andersrum geht beim "Komprimieren" häufig die Uberschaubarkeit und> Struktur des Codes soweit kaputt, dass man den Code danach sowieso nicht> mehr warten kann.
Na ja, auf der anderen Seite führt so aufräumen manchmal dazu daß der
Code entrümpelt und "gewachsene" Geflechte besser strukturiert neu
gemacht werden. Dann erreicht man damit gerade eine bessere
Überschaubarkeit.
Ich bin davon ausgegangen, dass der Code vor dem "Komprimieren" noch
sauber war. Inklusive Überschaubarkeit und Struktur.
Und nicht ein schrottiger Happy-Coding-Code.
uitrg789 schrieb:> Ich bin davon ausgegangen, dass der Code vor dem "Komprimieren" noch> sauber war. Inklusive Überschaubarkeit und Struktur.>> Und nicht ein schrottiger Happy-Coding-Code.
In den meisten Fällen ist er aber genau letzteres :-)
uitrg789 schrieb:> Die Zeit, die du damit verbringst, Deinen Code zu "komprimieren", kostet> Dich viel mehr, als den µC mit größerem Flash zu kaufen.>> Es sei denn, Du willst den µC verkaufen und musst die Software da> irgendwie reinquetschen.>> Andersrum geht beim "Komprimieren" häufig die Uberschaubarkeit und> Struktur des Codes soweit kaputt, dass man den Code danach sowieso nicht> mehr warten kann.>> Daher meine Empfehlung: Sauber Programmieren und wenn's nicht reicht,> den nächstgrößeren µC einsetzen.
Unsinn. Wenn man jedes mal doppelt so viel Flash braucht spart man mehr
als wenn man effizient programmieren kann.
Danke Leute für die Tips!
Habe vorhin auch noch das Tutorial zur AVR-GCC-Codeoptimierung
entdeckt... das Tool avr-nm ist ja auch recht hilfreich um festzustellen
welche Funktion besonders viel Speicher belegt.