www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATtiny24 - Codegröße, Flashgrenze erreicht


Autor: Harald X. (harald1976)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe für einen ATtiny24 ein C-Programm mit AVR Studio geschrieben. 
Nun habe ich das Problem, dass ich bereits an der Flashgrenze von 2kByte 
angelangt bin.

Ich vermute um die Funktionalität fertigzustellen wird die Codegröße in 
C bei 2,5 -3 kByte liegen.

Ich habe schon einige Optimierungen gemacht: keine FloatingPoint, Zeiger 
auf Strukturen...

Vermutlich kann man es nur noch mit Assembler in die Flashgrenze 
bekommen.

Ich habe keine Erfahrung mit Assembler. Wie könnte man vorgehen um das 
Programm teilweise in Assembler umzuschreiben.

Würdet ich auch so vorgehen:

1) Programm in C fertigstellen ( mit 3kB)

2) Teile des Programms in C umschreiben, bis 2kB Größe erreicht.


Wird das Programm wirklich kleiner wenn man C direkt in Assembler 
übersetzt? Oder muss man mehr Kniffe anwenden.

Wie schnell kann man sich in Assembler hineindenken, wenn man bisher 
noch kein Assemblerprogramm erstellt hat.

Wo findet man gute Assembler Beispielprogramme?

Ich weiß, dass man hier zu dem Thema schon viel findet. Vielleicht könnt 
Ihr mir einige gute Links geben.

Gruß
Harald

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einfacher: ATtiny44 verwenden.

Autor: Harald X. (harald1976)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bin leider gezwungen den ATtiny24 zu verwenden, da dieser auf Lager ist.

Autor: Harald X. (harald1976)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich meine das Programm hat schon eine Größe, aber das in C die 2kByte so 
schnell verbraten werden, dachte ich nicht.

Jedes mal wenn ich eine Codezeilen hinzufügte waren wieder 100Byte weg.

Gruß
Harald

Autor: Harald X. (harald1976)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
einige Codezeilen

Autor: Mehmet Kendi (mkmk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde auch das raten, was A.K. geraten hat.
In einer aehnlicher Situation, wobei der zusaetzlich benötigte 
Speicherplatzt nicht so gross war wie bei Dir, hatte ich alle 
String-Konstanten ins Eeeprom ausgelagert und mir so Platz im Flash 
geschaffen.
Aber das war ein Atmega8 mit 512Bytes Eeprom.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zeig mal was du da machst, d.h. den Code. Gibt Dinge die übel ausgehen.

Autor: Bernd N. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du den Code nicht herzeigen kannst, dann beschreibe mal was du für 
eine Aufgabe hast. Ohne Code oder Codebeschreibung ist das ein 
Ratespiel.

Autor: Alter Hase (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hatte schon mal ein ähnliches Problem, ist aber einige Jahre her.
War damals ein Keil Compiler für 8051.
Ich habe mir den Compiler-Ouput als Assembler Listing ausgeben lassen.
Dann "sinnlose" Befehle bei Bit-Opreationen, die generell über das
Carry statt über das adressierbare! Bit gemacht wurden eliminiert,
und ähnliches.
Würde mich aber schon wundern, wenn ein moderner optimierender 
Compiler-Code
um ca. 30% gekürzt werden kann, einem Assembler-Guru mag das noch
gelingen.

Fragt sich nur ob sich der ganze Aufwand rechnet.
Der nächst größere Tiny kostet kaum mehr, und Argumente wie "Tiny 24
liegt am Lager, der Tiny44 nicht" würden mich als Entwickler erst mal
nicht stören.
Es ist ein Rechenexempel:
Was kostet die Einführung/Lagerhaltung etc. eines neuen µP?
Was kostet die (nur einmal nötige) Schrumpfung des Programms, wenn es 
denn geht?
Oder gleich auf den Tiny44 umstellen, der dann vielleicht sogar 
günstiger
wird?

Mit dieser Vorgehensweise hatte ich bisher immer Erfolg.

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein Tiny24 kostet 1.15Euro, ein Tiny44 kostet 1.55Euro. Dh bei pro 100 
stueck spart man 40 Euro beim kleineren, aequivalent einer 
Arbeitsstunde. Dh ein Tag Mehrarbeit frist die Minderkosten von 1000 
Stueck auf.
Bei wieviel 10'000 stueck liegt denn dieses Projekt ?

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Harald X. schrieb:
> Wird das Programm wirklich kleiner wenn man C direkt in Assembler
> übersetzt? Oder muss man mehr Kniffe anwenden.

Die selbe Funktionalität in Assembler oder C macht kaum einen 
Größenunterschied -  wenn du Assembler kannst. 30% weniger 
Platzverbrauch ist nicht möglich.

Wenn dein Programm 3kB Codegröße hat, du keine Böcke drin hast, dann ist 
es 3kB groß. Das passt einfach nicht auf einen Tiny24.

Oliver

Autor: Michael H. (overthere)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Iwo, ich habe mal für den Tiny22A und Tiny44A ein Angebot eingeholt, 
unterschied waren knapp 7 ct (bei 1000 Stück) (war glaube ich so bei 89 
ct dann)
Wenn man richtig billig werden will, würde ich die MSP430G Series 
anschauen, da kann man richtig sparen. (So um die 50ct/Stück!) zudem hat 
man noch einen sparsameren 16bitter. Nachteile: Schlechterer 
Community-Support, Unübersichtliche Datenblätter, und weniger Timer (nur 
einen). Vorteil: DMA, und verdammt schneller ADC. 200kSamples (sec).
Edit: Gerade nochmal nachgeschaut: Es waren 90ct, unterschied 7 ct. 
Anyway, ich steig gerade auf MSP430 um...

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Einsparung von ASM kann doch gross sein. Die Compiler sind nicht so 
gut wie sie sein koennten. Die groesste einsparung sind die angepassten 
Datentypen. Da muss man sich bei jeder Variable ueberlegen, was man 
wirklich braucht.

Autor: Michael H. (overthere)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem bei ASM ist aber, dass man sich viel zu viel im Detail 
verliert und damit auch die Übersicht. (Ist jedenfalls bei mir so). ASM 
macht nur im Inline Assembler sinn, und dann auch nur, wenn der Compiler 
deftigen Mist baut. Wegen einem unnötigen mov auf 100 andere Befehle 
schreibe ich den Mist nicht nochmal in ASM.
Fazit: Man kann was sparen, aber 30%. No Way. Schau dir lieber mal das 
Listing durch, wo der Compiler mist baut.
Noch einen Tipp: Man kann in ISR gut Platz sparen...

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey noch Was schrieb:
> Die groesste einsparung sind die angepassten
> Datentypen. Da muss man sich bei jeder Variable ueberlegen, was man
> wirklich braucht.

Ein Byte ist ein Byte ist ein Byte ist ein Byte. Egal, ob in Assembler, 
oder C.

Oliver

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver schrieb:
> Hey noch Was schrieb:
>> Die groesste einsparung sind die angepassten
>> Datentypen. Da muss man sich bei jeder Variable ueberlegen, was man
>> wirklich braucht.
>
> Ein Byte ist ein Byte ist ein Byte ist ein Byte. Egal, ob in Assembler,
> oder C.

Nein. Es kommt noch auf andere Faktoren an. Z.B. wo sich dieses Byte 
befindet. Liegt es im SRAM, dann kann es nur benutzt (damit gearbeitet) 
werden, wenn man es vorher holt und hinterher zurückschafft. Bei 
kleineren Programmen kann es aber durchaus hilfreich sein, oft 
gebrauchten Variablen Exklusivregister zu spendieren, die Bytes also in 
Registern zu halten. Dies wäre ein Argument für ASM.

Oft reicht es aber, die verwendeten Algorithmen nochmal zu überdenken. 
Denn oft wird in C sehr ressourcenverschwendend progrmmiert, besonders 
wenn der Programmierer seine Erfahrungen mit PC-Programmierung gemacht 
hat, wo ressourcensparendes Programmieren ja ein Fremdwort ist.

Oft reicht es auch, auf C-Bibliotheken zu verzichten und sich seine 
Funktionen selbst zu schreiben, und zwar so, dass sie exakt das können, 
was auch gebraucht wird und kein bissel mehr. Das kann erheblichen 
Speicherplatz sparen, den viele C-Funktionen sind eierlegende 
Wollmilchsäue und verbraten viel Speicherplatz für Funktionalität, die 
im speziellen Fall gar nicht gebraucht wird.

>
> Oliver

Autor: Harald X. (harald1976)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe jetzt ein neues Projekt mit einer leeren Main Funktion 
angelegt.

int main(void)
{

}


Dieses belegt bereits 58 Bytes.
58 bytes (2.8% Full)
(.text + .data + .bootloader)

Wozu wird der bootloader benötigt bzw. kann man hier noch etwas 
optimieren?

Gruß
Harald

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Harald X. schrieb:
> Ich habe jetzt ein neues Projekt mit einer leeren Main Funktion
> angelegt.
>
> int main(void)
> {
>
> }
>
>
> Dieses belegt bereits 58 Bytes.

Naja, Interrupt-Sprungtabelle und Handler für unbenutzte Interrupts 
brauchen auch ihren Flash. Dazu die Mainloop, 29 Adressen sind da 
schnell belegt.

> 58 bytes (2.8% Full)
> (.text + .data + .bootloader)
>
> Wozu wird der bootloader benötigt bzw. kann man hier noch etwas
> optimieren?

Schau Dir den erzeugten ASM-Code an, alles Andere ist Kaffesatzleserei.

>
> Gruß
> Harald

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Harald X. schrieb:
> Ich meine das Programm hat schon eine Größe, aber das in C die 2kByte so
> schnell verbraten werden, dachte ich nicht.

In 2kB paßt schon ne Menge, wenn man sorgfältig programmiert.
Ein häufiger Anfängerfehler ist, für alles "int" zu nehmen, das bläht 
den Code auf.
Besser nimmt man uint8_t und nur da, wo wirklich notwendig uint16_t.

Strukturen sollten möglichst flach sein, d.h. möglichst wenig Pointer 
auf Pointer auf Pointer ....


> Jedes mal wenn ich eine Codezeilen hinzufügte waren wieder 100Byte weg.

Versuche mal, modular zu programmieren, d.h. ähnliche Programmteile in 
Funktionen zusammen zu fassen..
Oftmals sieht man Copy&Paste Monstercode, z.B. um Menüs zu erstellen. 
Jedes Menü wird als komplettes Programm hintereinander geklatscht.
Besser, man macht eine Menüfunktion, und der wird nur der Pointer auf 
den Formatstring, auf die Parameterliste, auf die Tastenliste übergeben.

Es gibt noch weitere Optimierungen (Compilerschalter) und oftmals hilft 
auch eine Überarbeitung des Programmablaufplans, bzw. erstmal die 
Erstellung eines solchen.


Peter

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Harald X. schrieb:
> Wozu wird der bootloader benötigt bzw. kann man hier noch etwas
> optimieren?

Mal eine ganz andere Frage: Die Optimierung -Os hast du aber aktiviert, 
oder?

Und nein, am bootloader kannst du nichts optimieren, es gibt da nämlich 
keinen.

Oliver

Autor: Ulrich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wieviel man mit ASM sparen kann hängt ganz vom Problem ab. Es gibt Fälle 
da kreigt man es ASM kaum so kurz hin wie GCC es schaft, aber es gibt 
auch welche, da kommt man mit 1/4 des Platzes aus. Für einige der 
Einsparungen hilft es aber nicht C mis ASM zu mischen, die kommen erst 
zum Tragen wenn man ganz auf ASM umstellt. Ohne Code, oder wenigstens 
eine BEschreibung worum es geht, ist das aber ein Stochern im Nebel.  Es 
wäre auch mögloch das mand en C Code so weit hinkriegt dass man noch in 
die 2 KB reinpaßt.

Autor: Oliver Döring (odbs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Einsparmöglichkeiten in Assembler sind oft gigantisch, wenn man sie 
denn nutzt. Eine Pauschalaussage wie "mehr als 30% sind nicht drin", ist 
Mumpitz.

Der C-Compiler tut sein bestes, ja. Wenn du also von einem Listing 
ausgehst, das von einem C-Compiler erzeugt wurde, und manuell darin nach 
Einsparmöglichkeiten suchst, dann mögen die 30% hinkommen. Aber wenn du 
das Problem in C formuliert hast, hast du schon alleine dadurch eine 
Menge Einsparmöglichkeiten vertan, von denen der beste Compiler nichts 
wissen kann.

Wenn du alleine vom Pflichtenheft ausgehst und das Programm von Grund 
neu in Assembler erstellst, wirst du erstaunt sein, wie effizient man 
mit kleinen Controllern arbeiten kann. Das erfordert allerdings 
Erfahrung und viel vorbereitende Handarbeit.

Schreib doch mal mehr dazu, was dein Programm können muß.

Autor: gagosoft (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke auch, dass Du Dir den C-Code ganz gründlich ansehen solltest.
Oft kann mit einer anderen Herangehensweise an ein Problem ein viel 
schlankerer Algorithmus gefunden werden.
Hast Du viele Macros in deinem Code (=Codekopien)?
Tief verschachtelte Funktionsaufrufe?
Viele globale Variablen?

Bei ASM ist meist nicht viel drinnen!
Ich hab meist mehr Erfolg den C-Code und speziell den Algorithmus zu 
optimieren!

Hmm was programmierts Du da, nur grob umrissen?

[ ]User-Interface
[ ]Signalverarbeitung (ADC->rechnen->PWM)
[ ]rechenintensives Zeug
[ ]timing-lastiges Zeug
[ ]top secret (dann kann Dir keiner wirklich helfen)
[ ]ganz was anderes

...bitte ankreuzen ;)

Autor: Zwölf Mal Acht (hacky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was macht der Bootloader eines C programmes ?

zB die vordefinierten Variablen initialisieren.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Harald X. schrieb:

> [...] Zeiger auf Strukturen...

Zweischneidige Sache das...
typedef struct ... data_t;

data_t data;

void foo ()
{
    data_t d = &data;
    d->a = d->a + 1;
}

Sowas führ nur zu kleinerem Code, wenn der Compiler (hier geht's wohl um 
avr-gcc) die Zugriffsadresse zur Compilezeit nicht kennt. ANsonsten 
macht er gerne absoluten Zugriff und Code wie für
void foo ()
{
    data.a = data.a + 1;
}

Bei mehreren Strukturen und wenn GCC die Adressen nicht kennt, ist man 
evtl. auch nicht besser:

void bar (data_t *d1, data_t *d2, 1data_t *d3, ...)
{
    ...
}

AVR hat nur wenige Pointer-Register. Daher legt er d1, d2, d3 nicht 
unbedingt in diesen an, sondern in anderen GPRs oder sogar im Frame. 
Selbst wenner sie in GPRs anlegt, braucht er für einen Zugriff 4 Byte: 2 
Byte, um den Zeigen in ein Pointer-Register zu bekommen und (mindestens) 
2 Byte für den indirekten Zugriff. Man ist dann nicht besser als mit 
absoluten Adressen -- dafür langsamer.

Um solche Features zu verwenden, um kleinen Code zu bekommen, sind 
Pauschaltipps oft unbrauchbar. Man muss schon recht gut wissen, wie GCC 
arbeitet, um den Code klenier zu bekommen, wenn er denn unnötig groß 
ist. Und es ist natürlich abhäbngig vom Code und von der GCC-Version.

Wenn man wirklich sowas machen muss, weil es von "oben" vorgegeben ist, 
dann erst man das Listfile überfliegen und checken, ob der Compiler 
guten Code macht oder mies arbeitet, und warum. Bei 2k ist das gut 
machbar.

Aber ohne was von dem Code zu sehen und was avr-gcc draus macht, kann 
man wie gesagt kaum verwertbare Tipps geben (ausser triviale wie kein 
float zu nehmen; das ist in 2k Flash eh obsolet).

Autor: Harald X. (harald1976)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

es handelt sich um ein spez. Akkuladegerät und unterbrechungsfreie 
Stromversorgung

1) Dabei werden mehrere Spannungen im Viertelsekundentakt gemessen und 
ausgewertet. U.a. die Temperatur der Akkus.
Mit ADC-ISR und sleepmode

2) Eine zwei-farbige Leuchtdiode dient dabei als Zustandsanzeige. Dabei 
sollen auch Blinkfolgen ausgegeben werden können.
Einlegen der Akkus 3 x grün, Entnahme der Akkus 3 x rot, Laden langsam 
grün blinkend, Schnell-Entladen schnell grün blinkend, Akkus schwach 
rot, Akkus in gutem Ladezustand dauernd grün

3) Da das Gerät keine Tasten zur Eingabe hat soll mit dem Schalter der 
Versorgungsspg. über eine Art Morsecode einfache Einstellungen und 
Ausgaben Systemzustand (Gib Status) durchgeführt werden können. Das wäre 
aber mehr Schön-zu-haben.

4) Watchdog

===

5) Reduzierter Ladestrom (über MOSFET toggeln), falls Last am Ausgang 
sehr groß.

6) Timerinterrupt mit sleep_mode() anstatt delay_ms


Punkte 1-4 habe ich umgesetzt, wobei 3) nur teilweise. Ab hier bin ich 
an der Flashgrenze.

Mir fehlen also teilweise Punkt 3) sowie 5) und 6)

Gruß
Harald

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt zeig doch mal den Code. Sonst wird das nix.

Falk Brunner schrieb:
> AVR-GCC-Codeoptimierung

Hast du das Schritt für Schritt durchgearbeitet? Welche Einstellung hat 
was gebracht, welche nicht?

Oliver

Autor: Oliver Döring (odbs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Harald,

deine Anforderungen sind leicht in Assembler zu erfüllen und passen ganz 
sicher locker in die 2k. Da bleibt sogar noch jede Menge Platz frei.

Da du nicht viel rechnen, nicht viele Daten zwischenspeichern musst und 
kein kompliziertes User-Interface brauchst (Display mit Formatierung der 
Daten etc.), bietet sich Assembler sogar an.

Wenn du dir vorher das Programm im Pseudocode auf Papier überlegst, wird 
die Umsetzung auch nicht schwer.

Deinen Punkt 6) verstehe ich nicht.

Poste deinen Code!

Autor: MarioT (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,  Harald X.
Das klinkt jetzt aber nicht gerade viel. Ich könnte mir vorstellen alles 
drauf zu bekommen.

Harald X. schrieb:
> gemessen und
> ausgewertet

Durch geschicktes Anordnen der Rechenoperationen und Formeln oder auch 
eine komplette andere Vorgehensweise läßt sich da manchmal sehr viel 
rausholen. Es ist wirklich nur eine Spekulatuion ohne Code.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Harald X. schrieb:
> 1) Dabei werden mehrere Spannungen im Viertelsekundentakt gemessen und
> ausgewertet. U.a. die Temperatur der Akkus.
> Mit ADC-ISR und sleepmode
> ... usw.

Das klingt alles nicht aufwendig, sollte spielend in 2kB passen.


> Dabei
> sollen auch Blinkfolgen ausgegeben werden können.
...
> 3) Da das Gerät keine Tasten zur Eingabe hat soll mit dem Schalter der
> Versorgungsspg. über eine Art Morsecode ...

Soll das nur für Dich sein?
Bedenke, daß ein anderer Benutzer nicht die Zeit hat, erstmal einen 
Bedienungslehrgang zu absolvieren.
Also LEDs und Tasten maximal mit 2 Funktionen belegen, sonst gebe ich 
Dir für Ergonomie (Benutzbarkeit) ne glatte 6-Minus.



> 6) Timerinterrupt mit sleep_mode() anstatt delay_ms

Das klingt schon verdächtig nach unüberlegtem Spaghetticode, sowas hat 
die Tendenz zu explodieren und unübersichtlich zu werden.
Deutlich effizienter ist es, Du programmierst ne Statemachine.


Peter

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.