Hallo, ich habe in einer header-Datei ein Define für die Korrektur der Encoderschritte. Ich habe 2 versch. Encoder, von denen die eine Sorte 2 Pulse pro Raste liefert, die andere 4 Pulse pro Raste. Bei der Bearbeitung des Menüs wird der Zähler jeweils um den Betrag verschoben (also einmal >> 1 und das andere Mal >> 2). Das ganze ist mir nur aufgefallen, weil ich gerade bei +- 100% Auslastung einer Tina bin und mit jedem Byte geizen muss. Ändere ich den Wert von 2 auf 1 steigt die Programmgröße um 10-12 Byte und ist plötzlich über 100% (mit Optimierung -Os). Ändere ich den Wert wieder zurück auf 2 sinkt die Programmgröße um obige Anzahl Bytes. Wieso ändert sich die Codegröße in Abhängigkeit des shift-Faktors? Kann ich den Code umformulieren, sodass diese Effekte nicht mehr auftreten?
das liegt am Optimierer...vereinfacht gesagt, wenn z.B. ein Register schon mit z.B. 2 vorgeladen ist, und die nächste Operation dort 2 benötigt - wird kein Platz verbraucht, ist es mit 5 belegt, gehen ein paar Byte für die Umbelegung drauf.. Besonders deutlich ist das auch, wenn man Variable mal mit 0 und mal mit was anderem belegt.
Santiago wrote:
> Wieso ändert sich die Codegröße in Abhängigkeit des shift-Faktors?
Weil deine Tina offenbar ein Prozessor ist, der keine N Bits in
einem Befehl schieben kann, sondern nur jeweils um 1 Bit.
Jörg Wunsch wrote: > Weil deine Tina offenbar ein Prozessor ist, der keine N Bits in > einem Befehl schieben kann, sondern nur jeweils um 1 Bit. Aber die Größenänderung ist "verkehrt herum". ;-)
> Weil deine Tina offenbar ein Prozessor ist, der keine N Bits in > einem Befehl schieben kann, sondern nur jeweils um 1 Bit. Hm - nach der Logik würde ich aber bei dem größeren Schiebewert den größeren Code erwarten. Es ist aber genau anders herum. Da klingt die Variante von "egberto" plausibler. Das ist aber bitter, wenn die Codegröße vom Zufall, bzw. von der initialen Registerbelegung abhängt.
Ohne den konkreten Code testen zu können ist das alles nur Kaffeesatzleserei. Wenn es wirklich wichtig ist, die Länge(!) des Code unabhängig von der Shift-Count zu machen, musst du nur dafür sorgen, dass dieser Wert vom Compiler nicht als konstant angesehen wird. Dann wird eine Schleife draus. Für die Laufzeit ist das natürlich ein Schuss in den Ofen, und die ist dann statt der Länge davon abhängig. Wenn du sowohl Laufzeit wie Länge konstant und kurz halten willst, musst du von AVR Abschied nehmen.
Santiago wrote: > Kann ich den Code umformulieren, sodass diese Effekte nicht mehr > auftreten? Ja. Es gibt keinen Code, der sich nicht noch weiter optimieren ließe. Um mehr zu sagen, müßtest Du den Code mal zeigen. Peter
Hallo, danke für Eure Aufmerksamkeit. > Ohne den konkreten Code testen zu können ist das alles nur > Kaffeesatzleserei. Ist leider eine Auftragsarbeit - kann ich nicht so einfach posten. @Peter Jetzt bin ich genau an dem Punkt, den ich befürchtet hatte. Die Umrechnerei der Encoder Pulse bricht mir das Genick. Leider bekam ich keine Antwort auf meine Frage nach einem Encoder, der nur einen Puls pro Raste erzeugt. Nur aus Spaß habe ich den ganzen Umrechnungscode mal gekapselt und die Auswirkungen liegen bei ca. 100 Byte Codegröße. Das halte ich für eine Tina recht üppig und nimmer vernachlässigbar. > Es gibt keinen Code, der sich nicht noch weiter optimieren ließe. Yep - aber in 2 Tagen habe ich kein Assembler gelernt :( Wird also schweren Herzens ein mega und damit ne neue Platine werden müssen.
Auch wenns eine Auftragsarbeit ist, lässt sich doch bestimmt daraus ein kürzeres Testprogramm stricken, das den Effekt zeigt, und das du hier zeigen kannst. Wenn nicht, must du halt alleine weiter basteln. Oliver
Santiago wrote: > Nur aus Spaß habe ich den ganzen Umrechnungscode mal gekapselt und die > Auswirkungen liegen bei ca. 100 Byte Codegröße. Das halte ich für eine > Tina recht üppig und nimmer vernachlässigbar. Was ist eine Tina? Die ATtiny haben ja alle außer dem ATtiny2313 bis zu 8kB Flash, da sind 100 Byte pillepalle. > Yep - aber in 2 Tagen habe ich kein Assembler gelernt :( Wer hat was von Assembler gesagt? Es geht erstmal um die Optimierung des C-Codes. Natürlich wäre es schön, wenn man dazu das Listing des Compilers versteht. Aber Bytes zählen kann man auch ohne Assemblerkenntnisse. Peter
Wenn du bis jetzt "normal ordentlich" programmiert hast, d.h. kein besonderes Augenmerk auf die Codegröße gelegt hast, sind mit der hier verfügbaren Anleitung zur Codeoptimierung in C bestimmt noch 100 Byte zu holen. Ein weiterer "Geheimtip": nimm einen etwas älteren GCC (von 2006/2007). Viel Erfolg
Also ein wenig Inline Assembler könnte da Wunder wirken. Wenn man allerdings erstmal richtig Assembler Programmieren lernen muss, dann siehts da düster aus. Ich hatte mal eine Erfahrung mit nem Tiny 2313. Mit C-Code 100% bzw. zu groß für den Flash für die gewünschte Funktion. Hab mich dann dazu entschlossen, anhand des C-Codes alles in Assembler selber zu schreiben (C-Code allerdings als Blaupause"). Und siehe da alles passt rein: Optimierung um 50% -> Also Controller Flash zu 50% voll. Man muss allerdings sehr viel mehr Hirnschmalz investieren, da die üblichen Komfortfunktionen des Compilers wegfallen. Und größere Arrays mit ihrer Indizierung schnell schief gehen können!
@Oliver
1 | #define FAKTOR 1
|
2 | |
3 | a = b >> FAKTOR; |
So sieht der code aus - natürlich in 2 verschiedenen Dateien. Von den Zählerzuweisungen gibt es einige (glaube 5). Wenn ich FAKTOR auf 2 setze ist der Code kleiner als wenn ich ihn auf 1 setze. Aber ok - wir können es dabei belassen. Dank Euch für Eure Zeit und Aufmerksamkeit. @Peter > Die ATtiny haben ja alle außer dem ATtiny2313 bis zu 8kB Flash, da sind > 100 Byte pillepalle. Nun es war genau die ATtiny2313. Aber wie heißt es so schön: aus Schaden wird man kluch ;) @egberto > Wenn du bis jetzt "normal ordentlich" programmiert hast, d.h. kein > besonderes Augenmerk auf die Codegröße gelegt hast, sind mit der hier > verfügbaren Anleitung zur Codeoptimierung in C bestimmt noch 100 Byte zu > holen. Nun ich bin neu in der mC-Programmierung. Allerdings habe ich schon auf Speicherbedarf geschaut. Wie gut ich dabei war, kann ich jetzt nicht beurteilen. Ich werd's mir nochmal anschauen. Danke für das "Mut-machen". Wahrscheinlich wird es doch auf einen anderen Chip rauslaufen.
@Matthias Wir sind uns einig, dass mit Assembler noch einiges rauszuholen wäre. Nur habe ich im Moment nicht die Zeit, mich da auch noch einzuarbeiten. Ich bin mir ziemlich sicher, dass der Aufwand alle Erwartungen sprengt. Ein ander Mal vielleicht.
Santiago wrote: > Nun es war genau die ATtiny2313. > > Aber wie heißt es so schön: aus Schaden wird man kluch ;) Ja, ich habe mich auch schon mächtig geärgert, daß Atmel alle ATtiny auf 8kB/512B gepimmt hat, aber bloß den ATtiny2313 nicht. 2kB ist wirklich so die kritische Grenze für den AVR-GCC, man ist ruckzuck drüber. Ich versuche daher neue Projekte auf den ATtiny461/861 umzuschwenken. Der hat zwar 2 IOs weniger, aber mit Bootloader kann man alle 16 benutzen. Peter
Peter Dannegger wrote:
> 8kB/512B gepimmt hat, aber bloß den ATtiny2313 nicht.
Wahrscheinlich streiten sie nun schon sein Jahren über den dafür zu
vergebenden Namen. Passt halt nicht ins Schema. ;-)
>Von den Zählerzuweisungen gibt es einige (glaube 5).
Solange da nicht auch 5 Drehgeber an der Tina hängen, könnte man
schonmal fragen, warum gerade 5, und nicht nur genau eine pro Drehgeber?
Oliver
Santiago wrote: > @Oliver >
1 | > #define FAKTOR 1 |
2 | >
|
3 | > a = b >> FAKTOR; |
4 | >
|
> So sieht der code aus - natürlich in 2 verschiedenen Dateien. > Von den Zählerzuweisungen gibt es einige (glaube 5). > Wenn ich FAKTOR auf 2 setze ist der Code kleiner als wenn ich ihn auf 1 > setze. > Möglicherweite merkt sich der Compiler Zwischenwerte und braucht mehr Register, was dann einen Frame erfordert. Ohne asm-Listing/C-Quelle/Compiler-Version/Schalter ist's aber Rumgestochere. Möglich auch, daß GCC erkennt, daß b eine Konstante ist und dadurch Optimierungen machen kann für >> 2, die er für >> 1 nicht machen könnte, zB wenn dadurch ein if(a == ...) Block wegfällt da toter Code. Einige "Optimierungen" kann man abwürgen, indem man vor/hinter C-Befehle schreibt asm volatile (""::); oder indem man GCC explizite Kenntnis über Registerinhalte nimmt: asm volatile ("" : "+r" (a)); Beide Templates gehen für alle GCC-Varianten, also nicht nur für AVR. Sie erzeugen keinen Code, haben aber Einfluss aufs Compilat. Nochwas zu "C-Quelle" Bei einem aggressiv optimierenden Compiler ist immer auch der Gesamtkontext einer Codezeile wichtig. Eine losgelöste Zeile kann komplett anderen Code erzeugen als im Kontext. Auch wenn nur eine kleine, unscheinbare Codeänderung in der C-Quelle gemacht wird, kann das dennoch Auswirkungen darauf haben, wie C-Code 100 Zeilen davor(!) oder dahinter compilert wird!
> Ich versuche daher neue Projekte auf den ATtiny461/861 umzuschwenken. > Der hat zwar 2 IOs weniger, aber mit Bootloader kann man alle 16 > benutzen. Hm - habe mir die Steinchen mal angeschaut, die MLF-Varianten scheinen gleich groß mit dem mega8 zu sein. Warum dann nicht gleich den mega9 nehmen? Preislich sind die 8er tiny nicht gerade interessant. > Solange da nicht auch 5 Drehgeber an der Tina hängen, könnte man > schonmal fragen, warum gerade 5, und nicht nur genau eine pro Drehgeber? Klar darf man(n) fragen! Ich habe eine vorgegebenen Kommunikationsstruktur zu füllen. Die Zähler sind unterschiedlich breit (zwischen 1 und 6 Bit). Ursprünglich hatte ich die Werte direkt in der Struktur verändert, aber auf Anraten Iflands verwende ich einen separaten Zähler für die Werte. Entgegen der Prognose vergrößert das den Code nicht unerheblich. Vor der Übertragung müssen die dann aufs richtige Maß geschoben werden. Ach ja, die Zähler werden "gleichzeitig" oder auch atomar übertragen, deshalb kann ich nicht einen Zähler für alle nehmen. > Eine losgelöste Zeile kann komplett anderen Code erzeugen als im Kontext. Ja, das hatte ich bereits in einem anderen Fred. Dort hatte ich einen Fehler in der Initialisierung, der erst nach Posten des gesamten Codes rauskam. Die Tips zur Beeinflussung der Optimierung sine sehr interessante Konstrukte. Werde per Gelegenheit die Auswirkung mal ausprobieren. Danke. Habe inzwischen auch die Anleitung zur Codeoptimierung gefunden und gelesen. Die meisten Punkte waren mir bekannt und ich hatte sie bereits beachtet (ich hatte mal die entsprechende Appnote von Atmel gelesen).
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.