Forum: Compiler & IDEs codegröße zu groß


von Tseug H. (tseug)


Lesenswert?

Hallo Forum,

benutzte seit kurzem den GCC im AVR-Studio. Jetzt habe ich das Problem 
dass der Code für meinen 2313 etwas zu groß ist (5k7Bytes). Mir ist 
schon klar dass durch das einbinden von Bibliotheken der Code wächst.

Wie kann man aber einstellen dass nicht alle Funktionen gelinkt werden 
die in der Bib drin sind. Ich benötige Funktionen aus <stdio.h> 
<ctype.h> und <stdlib.h> (fdevopen, printf, gets, scanf) und möchte die 
nicht unbedingt selber schreiben.

Hab keine Ahnung wo ich das einstellen kann und von Makefiles hab ich 
ehrlich gesagt keine Ahnung.

Schönen Gruß
Timo


von johnny.m (Gast)


Lesenswert?

Bist Du sicher, dass Du z.B. printf wirklich brauchst? Wenn Du nur 
irgendwelche Zahlen in Strings konvertieren willst (was viele Leute z.T. 
aus Unwissenheit über Alternativen immer noch mit dem "Monster" printf 
implementieren), dann benutze besser die Funktionen itoa, dtostr usw. 
aus der stdlib.h. Die erzeugen signifikant weniger Overhead (weil sie 
eben nur spezielle Funktionen ausführen und nicht den ganzen anderen 
Mist mit rumschleppen) und sind deshalb für solche Aufgaben eher zu 
empfehlen. Und wenn Du Strings z.B. über die serielle Schnittstelle 
ausgeben willst, und es von der Codegröße her nicht passt, wirst Du 
nicht umhinkommen, zumindest die für Deine Anwendung spezifischen 
Ausgaberoutinen selber zu schreiben (was aber auch nicht so kompliziert 
ist, wenn man die Strings, die man ausgeben will, schon vorliegen hat).

von Tseug H. (tseug)


Lesenswert?

Danke für deine Antwort johnny,


hab mir jetzt mal das Listfile angeschaut. Da werden ja fast alle 
Funktionen von der Stdiolib eingebunden. Die Funktionen die ich aufrufe 
brauchen wohl wieder andere Funktionen aus dieser Bibliothek.

Werde also nicht drum rum kommen selbst was zu schreiben.

Es geht eigentlich nur darum an den UART einen Befehl (AT-Befehl) zu 
senden.

Hab mir halt dazu ein Beispiel für nen 8535 konvertiert, allerdings sind 
da halt printf scanf und gets drin.

Hab auch schon im Datenblatt von 2313 ein sendebeispiel für den UART 
gefunden. Werde mich also da heute mal ran machen. Falls Du ein Beispiel 
kennst immer her damit.

Timo

von Karl heinz B. (kbucheg)


Lesenswert?

> Es geht eigentlich nur darum an den UART einen Befehl (AT-Befehl) zu
> senden.

Dafür ist aber printf und das ganze Drumherum mächtiger
Overkill. Ersetz das mal. Du wirst sehen, das ist nicht
weiter schwer.
Das Problem bei printf() ist, dass es allgemein sein muss.
printf() hat ne Menge Möglichkeiten die Ausgabe zu formatieren.
Auf einem µC braucht man aber >90% der Funktionalität die
printf() bietet meist gar nicht. Bei größeren µC ist das
kein Problem, die haben Speicher genug. Bei den Kleinen ist das
aber kostbarer, verschenkter Speicherplatz.

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


Lesenswert?

Ich halte printf() für einen 2-KiB-Controller auch für zu heftig (und
ich habe große Teile davon geschrieben -- ich preise das also eher
lieber an, als die Leute von der Benutzung abhalten zu wollen :).  Das
Mindeste, was du aber tun kannst, ist die Umstellung von fdevopen()
auf FDEV_SETUP_STREAM(), damit du das malloc() los wirst.

Hab's gerade mal probiert, eine minimale Applikation (mit
FDEV_SETUP_STREAM()), die printf() benutzt, um eine UART-Ausgabe zu
machen, braucht mit GCC 4.1.1 und -Os für einen ATtiny2313 compiliert
2042 bytes an ROM, lässt also nur noch 6 bytes frei.  Wenn du gegen
die Minimalversion von printf() linken kannst (die versteht keine
Feldbreiten und precision), dann sinkt der ROM-Verbrauch auf 1400
bytes -- das würde wohl gerade noch ein wenig Luft lassen für die
Applikation.

Wenn du was testest, denk dran, dass
1
printf("Hello world!\n");

noch kein printf() mit dazu linkt; der Compiler optimiert das
zu
1
puts("Hello world!");

Wirklich praktikabel halte ich stdio für Controller so ab 8 KiB ROM.
Allerdings gibt's da nichts mehr, was pinkompatibel zum ATtiny2313
wäre.

von Tseug H. (tseug)


Lesenswert?

Nur der Vollständigkeit halber noch kurz meine Lösung:

Verwende quasi die Beispiel Software aus dem Atmel Datenblatt. Hab mir 
auch ein paar anregungen von der Fleury Lib geholt und das ganze sieht 
dann folgendermaßen aus.

#define F_CPU          11095200
#define UART_BAUD_RATE 19200
#define UART_BAUD_SELECT(baudRate,xtalCpu) 
((xtalCpu)/((baudRate)*16l)-1)

void uart_init(unsigned int baudrate)
{
    /* set baud rate */
    UBRR = (unsigned char)baudrate;
    /* enable UART receiver and transmmitter */
    UCR = _BV(RXEN)|_BV(TXEN);
}

void uart_putc(unsigned char data)
{
    while (!(USR & (1<<UDRE)));
    UDR = data;
}

void uart_puts(const char *s )
{
    while (*s)
      uart_putc(*s++);
}




Im Main dann mit...

uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
void uart_puts("Hallo Welt");

...aufrufen.
...und der Code ist auf ein Minimum geschrupft.

Schönen Gruß
Timo


von Robert (Gast)


Lesenswert?

void uart_puts("Hallo Welt");

So aber nicht!!!

Wenn so: uart_puts("Hallo Welt");

Gruß Robert

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.