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:
1 | float superkomplizierte_wandlung_int_nach_float( int zahl ) |
2 | {
|
3 | return zahl; |
4 | }
|
Peter
@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.
>und an einer anderen Stell möcht ich eine >float aus einem String lesen. Pffffh, auch da lässt sich was mit Festkomma machen.
Gesetz von Moore praktisch anwenden: Atmega168 nehmen. Der hat doppelt so viel Flash.
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.
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.