Forum: Compiler & IDEs Programm zu gross/ Sparpotential?


von flyingwolf (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,
das Programm das ich im Anhang mitgeschickt habe ist für meine Hardware
zu gross geworden. Damit ich es überhaupt in Teilen testen kann, habe
ich Funktionen in Main.c auskommentiert, die aber wichtig sind.
Das Einfachste wäre, einen mega16 statt einem Mega 8 zu verwenden, aber
die Hardware ist blöder Weise schon fertig.
Wo habe ich noch Sparpotential?

von dasdas (Gast)


Lesenswert?

Hast du vielleicht unnötige Bibliotheken mit dazu gelinkt?
Hast du -Os im Makefile gesetzt, so dass der Compiler auf Größe
Optimiert?

Ansonsten sollte das doch eigentlich in 8K reinpassen!?

von peter dannegger (Gast)


Lesenswert?

Da gibts ne Menge:

- nimm char statt int, wenns ausreicht
- nimm unsigned statt signed, wenns ausreicht
- nimm float nur wo nötig
- fasse gleichartige Funktionen zusammen


Peter

von Karl H. (kbuchegg)


Lesenswert?

Ich hab mir mal deine Funktion 'daten_auswerten_1'
vorghenommen.

Im Original, mit O3 kompiliert:

Program:  5730 bytes

Nachdem ich sie umgestrickt habe:

Program:  5496 bytes

also 234 Bytes gespart (und, so denke ich, einen Fehler gefunden)

'daten_auswerten_2' ist nicht ganz so einfach. Das Hauptproblem
dürfte hierbei die float-Arithmetik sein. Durch Probieren
hab ich gefunden, dass zb.

 rsl = rsl + ( demost[0] - '0' );

weniger Code erzeugt als

 rsl = rsl + ( demost[0] - 48.0 );

usw. Ich denke aber mal, dass man durch Durchforsten der
komplizierten if-Bedingungen wieder einiges einsparen kann.
Ein anderer heisser Kandidat, ist für micht die
Funktion ir_string()  aus ir_out.c
Wenn du da ein paar Tabellen einführst und den grossen switch-case
rauswirfst, muesste
  1. Der Code wesentlich klarer werden
  2. ein Einsparungspotential da sein.
(Vielleicht probier ich das noch).

Grundlegend solltest du dir aber ueberlegen, ob die Gleitkomma-
Arithmetik überhaupt notwendig ist oder ob da nicht auch was
anderes ausreichend wäre (zb ein int oder long, wobei alle
Zahlen implizit mit 1000 multipliziert sind. 1.0 wird dann
als 1000 in einem int gespeichert, 1.45 wäre 1450, usw.)

von Karl H. (kbuchegg)


Lesenswert?

Ooops. Ich sollte die daten_auswerten1 auch zeigen.

Hier ist sie:

char convert( char* Digit )
{
  return ( *Digit - '0' ) * 10 + ( *(Digit+1) - '0' );
}

void daten_auswerten_1 (void)
{
  if( tabcount == 3 && demost[0] ==';') {
    if( demost[1] == 'V' )
      setbit( status2, 7 );
    else
      clearbit( status2, 7 );
  }

  if( tabcount == 4 ) {
    if( demost[0] ==';' && demost[1] !=';' && zeichenzaehler == 1
)
      tag = convert( &demost[1] );
    if( demost[0] == '.' && demost[1] !=';' ) {
      if( zeichenzaehler == 4 )
        monat = convert( &demost[1] );
      else if( zeichenzaehler == 7 )
        jahr = convert( &demost[1] );
    }
  }

  if( tabcount == 5 ) {
    if( demost[0] ==';' && demost[1] !=';' && zeichenzaehler == 1
)
      stunde = convert( &demost[1] );
    if( demost[0] ==':' && demost[1] !=';' ) {
      if( zeichenzaehler == 4 )
        minute = convert( &demost[1] );
      else if( zeichenzaehler == 7 ) {
        sekunde = convert( &demost[1] );
        step = 3; //test
      }
    }
  }
}

von Werner B. (Gast)


Lesenswert?

Nachdem du in daten_auswerten_1 immer wieder auf demost[0] und
demost[1]
zugreift, könnte es einige ersparnis bringen diese zuerst in lokale
registervariable zu legen und mit diesen Variablen zu arbeiten.
1
void daten_auswerten_1 (void)
2
{
3
   register uint8_t v0, v1;
4
5
   v0 = demost[0];
6
   v1 = demost[1];
7
8
  if( tabcount == 3 && v0 ==';') {
9
    if( v1 == 'V' )
10
      ...
11
  }
12
  ... 
13
}

Zudem kannt du im unteren Bereich (tabcount==4 und 5)
demost[1] !=';';
ausklammern.

von Tom (Gast)


Lesenswert?

Hallo.
Kannst du dir nicht eine eigene sprintf() stricken, die nur die
benötigten Funktionen enthält? printf() braucht allein schon ca. 5k an
Speicher.
Für characters und Dezimalzahlen sollte das nicht schwer sein, nur die
Floats werden komplizierter. Falls du die durch Fixkommazahlen ersetzen
könntest, ginge das aber auch.

Gruss

von Jürgen (Gast)


Lesenswert?

Falls Du das Programm(habe mir den Quelltext nicht angesehen) nicht
kleiner bekommst, kannst Du ja mal probieren es auf den ATmega168
umzuschreiben. Sollte nicht so schwierig sein.

von flyingwolf (Gast)


Lesenswert?

ich könnte die floats auch durch Strings ersetzen, aber ich komme mit
den Dingern einfach in C nicht klar. Zeichenweis kopieren bis eine ;
kommt wäre nicht das Problem, aber dann komme ich mit dem zeug nicht
mehr klar.
Einfaches Beispiel:

sprintf(sendstring,"DIS!%c", 0x0d);
send_string_uart(sendstring);

Das ist schon nicht so gut. Das müßtre doch auch direkt gehen, sowas
wie
send_string_uart("DIS!"); aber wie bekomme ich 0x13 ans Ende der
Ausgabe?

von Wolfram (Gast)


Lesenswert?

send_string_uart("DIS!"); aber wie bekomme ich 0x13 ans Ende der
Ausgabe?
send_string_uart("DIS!\n");

von Fritz G. (fritzg)


Lesenswert?

send_string_uart("DIS!\n");
bzw.
send_string_uart("DIS!\r");
wenns wirklich CR sein muss.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> printf() braucht allein schon ca. 5k an
> Speicher.

% avr-size ~/avr/lib/avr4/libprintf_flt.a
   text    data     bss     dec     hex filename
   2684       0       0    2684     a7c vfprintf_flt.o (ex
/user/jwunsch/avr/lib/avr4/libprintf_flt.a)

von flyingwolf (Gast)


Lesenswert?

es muss ganz sicher CR sein, aber wenn ich es recht in Erinnerung habe
ging \r nicht, aber ich bin mir nicht ganz sicher obs daran lag oder
an einem anderen Fehler

von Karl H. (kbuchegg)


Lesenswert?

Ich hab mal ein wenig rumprobiert.
Die grösste Zunahme, die ich gesehen habe
ist die floating point Arithmetik. Sobald da
irgendwas reinkommt, schnalzt die Statistik
nach oben.

von Karl H. (kbuchegg)


Lesenswert?

> send_string_uart("DIS!"); aber wie bekomme ich 0x13 ans Ende der
> Ausgabe?

Falls alle Stricke reissen:
send_string_uart( "DIS!\x13" );

Aber was hat das mit float zu tun?

von flyingwolf (Gast)


Lesenswert?

@Karl Heinz
<< Aber was hat das mit float zu tun?

erst mal nix. Es ging um die wegrationalisierung des speicherfressenden
sprintf

Vielen Dank an alle, die sich hier so hingebungsvoll um mein Problem
kümmern. Ich werde mal versuchen, die floats rauszulassen ...
An dem Versuch, die Sache mit Strings zu behandeln, bin ich allerdings
schon einmal furchtbar gestrandet ...

von André K. (freakazoid)


Lesenswert?

BTW: 0x0d != 0x13 ;-)

von Karl H. (kbuchegg)


Lesenswert?

> An dem Versuch, die Sache mit Strings zu behandeln

Nicht Strings. Fixed Point Arithmetik.

Ist im Grunde ganz einfach: Du rechnest immer nur mit
ganzen Zahlen, merkst Dir aber, dass das Komma an
der zb. 2. Stelle steht.

Du kannst das und machst das schon seit Jahren.
Zb. rechnest du   2 Euro 60  plus 3 Euro 70 ergibt  6 Euro 30
oder mit Gleitkomma:  2.60 + 3.70 -> 6.30
Du hast aber gelernt, dass du das ganze aber auch komplett in Cent
rechnen kannst:
                      260 cent  plus  370 cent ergibt  630 cent
                      260 + 370 -> 630
Das ist auch nichts anderes als oben. Denk dir einfach
ein Komma zwischen die Hunderter und Zehnerstelle und du hast
wieder deine Eurorechnung von oben.

von Dirk (Gast)


Lesenswert?

Hi,

falls du dein Code nicht weiter optimiert bekommst sollte der Mega8
Nachfolger helfen.

http://www.atmel.com/dyn/products/product_card.asp?part_id=3303

von flyingwolf (Gast)


Lesenswert?

@Dirk
Super Idee. Danke.

von flyingwolf (Gast)


Lesenswert?

@André Kronfeldt
Du hat natürlich Recht 0x0d muss es heissen und nicht 0x13

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
Noch kein Account? Hier anmelden.