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!
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
> 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).