www.mikrocontroller.net

Forum: Compiler & IDEs Mega88 SPI Soft->Hard Jetzt Flash zu klein,HILFE


Autor: Avr Noob (balze)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich bin dabei aus einem Mega88 , einem S65 Display und einer SD Karte 
einen digitalen Bilderrahmen zu bauen.
Meinem Projekt liegt der Code von Marc Meise zugrunde. (siehe hier: 
Beitrag "Re: Digitaler Bilderrahmen mit mega8 S65 Display und SD-Kart" )

Jetzt habe ich ein (Platz-)Problem beim Umstellen von Software- auf 
Hardware-SPI.

Kann mir das jemand erklären? Ich habe hier im Forum ausgiebig gesucht 
aber nichts ähnliches finden können.

Mein Problem ist folgendes:
Ich benutze am Mega88 sowohl die USART im SPI Modus, als auch den SPI 
Port.
Das S65 Display läuft mit Harware-SPI an der USART (PortD).

Die SPI Schnittstelle ist fuer Hardware SPI konfiguriert.
Ändere ich jetzt die Funktion zum Schreiben von Soft auf Hardware, passt 
es nicht mehr in den Flash :(

Also, dies hier:
uint8 SpiByte(unsigned char outbyte)
{
  uint8 a, inbyte=0, comp = 0x80;
  // use soft-SPI to be flexible with different pins and CPU types
  for (a=8; a>0; a--) //das Byte wird Bitweise nacheinander Gesendet MSB First
  {
    if (outbyte & comp)        //Ist Bit a in Byte gesetzt
    {
      MMC_PORT |= (1<<MMC_DO);   //Set Output High
    }
    else
    {
      MMC_PORT &= ~(1<<MMC_DO);   //Set Output Low
    }  
    MMC_PORT &= ~(1<<MMC_Clock);  //erzeugt ein Clock Impuls (LOW)
    asm volatile("nop");
    if (MMC_PIN & (1<<MMC_DI))     //Lesen des Pegels von MMC_DI
    {
      inbyte |= comp;
    }
    else
    {
      inbyte &=~comp;
    }
    MMC_PORT |= (1<<MMC_Clock);   //setzt Clock Impuls wieder auf (High)
    asm volatile("nop");
    comp >>= 1;
  }
  MMC_PORT |= (1<<MMC_DO);      //setzt Output wieder auf High  
  return inbyte;
}

tauschen gegen :
uint8 SpiByte(unsigned char outbyte)
{
  SPDR = outbyte;
  while(!(SPSR & (1 << SPIF)));
  SPSR &= ~(1 << SPIF);
  return SPDR;
}

Und ich bekomme die schoene Meldung region text is full :)
Mit SoftSPI (ohne HardwareSPI zu initialisieren) sind es nach dem 
Compilieren (mit -Os) 7910 bytes (96,6% Full)
Mit SoftSPI (MIT HardwareSPI Initialisierung) sind es nach dem 
Compilieren (mit -Os) 7920 bytes (96,7% Full)


Jede Hilfe ist willkommen !!

Schoenen Gruss,

Balze der AVR Noob

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>uint8 SpiByte(unsigned char outbyte)
>{
>  SPDR = outbyte;
>  while(!(SPSR & (1 << SPIF)));
>  SPSR &= ~(1 << SPIF);
>}

Der Aufruf einer Funktion mit Parameter
kostet dich mehr als wenn du das so machst:

 SPDR = outbyte;
 while(!(SPSR & (1 << SPIF)));

>  SPSR &= ~(1 << SPIF);

Und die Zeile hier drüber brauchst du nicht.

Autor: Avr Noob (balze)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nochmals,

holger wrote:
> Der Aufruf einer Funktion mit Parameter
> kostet dich mehr als wenn du das so machst:
>
>  SPDR = outbyte;
>  while(!(SPSR & (1 << SPIF)));

OK, das kann ich verstehen, allerdings ist es mit SoftSPI auch ein 
Funktionsaufruf mit Parametern. Wo ist der gravierende Unterschied 
zwischen Hard- und-Soft SPI bzgl. Speicherbedarf? Jemand eine Ahnung?

Ich habe mal alle Funktionsaufrufe durch das direkte Schreiben/Lesen der 
Register ersetzt, leider ohne Erfolg (bzgl. Speicherbedarf)

Kann mir jemand sagen, wie ich rausbekommen kann WIE GROSS der Flash den 
sein muesste? (Damit ich einen Anhaltspunkt bekomme, wo ich diese 
notwendige Reserve locker machen kann). Leider bekommt man ja keine 
Angaben mehr, sobald man den zulaessigen Flashbereich ueberschritten 
hat.
(Kann man das aus der Groesse des entstandenen HEX files ableiten? Ist 
ja anzunehmen, nur wie?)


holger wrote:
>>  SPSR &= ~(1 << SPIF);
>
> Und die Zeile hier drüber brauchst du nicht.

Diese Zeile ist aber NUR ueber, wenn man nach dem Lesen von SPSR AUCH 
auf SPDR zugreift, oder habe ich das Datenblatt falsch verstanden?

Vielen Dank, schoenen Gruss,

Balze, der AVR Noob

Autor: Hmm... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Kann mir jemand sagen, wie ich rausbekommen kann WIE GROSS der Flash den
> sein muesste? (Damit ich einen Anhaltspunkt bekomme, wo ich diese
> notwendige Reserve locker machen kann). Leider bekommt man ja keine
> Angaben mehr, sobald man den zulaessigen Flashbereich ueberschritten
> hat.
> (Kann man das aus der Groesse des entstandenen HEX files ableiten? Ist
> ja anzunehmen, nur wie?)

Beim GCC (bzw WinAVR) liegt das schöne Tool 'size' bzw. 'avr-size' bei. 
Damit kannst du die größe der Binary-Datei (.elf) anzeigen lassen.


Ansonsten schau mal hier, ob du vielleicht auf andere Weise noch ein 
paar Bytes rausquetschen kannst:

http://www.mikrocontroller.net/articles/AVR-GCC-Co...

Autor: Jörg G. (joergderxte)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Diese Zeile ist aber NUR ueber, wenn man nach dem Lesen von SPSR AUCH
> auf SPDR zugreift, oder habe ich das Datenblatt falsch verstanden?
machst du ja, mit "return SPDR;"

Probier doch, entweder:
/* Besonders gut, wenn die Funktion nur in einer Datei gebraucht wird, 
    oder in einem Header steht
*/
static uint8_t SpiByte(unsigned char outbyte)
{
    SPDR = outbyte;
    while(!(SPSR & (1 << SPIF)))
        ;
    return SPDR;
}
Oder (Es gibt auch noch einen -fnoinline... Parameter für den gcc, weiß 
ich aber nicht auswendig):
//Prototyp, gehoert eigentlich in eine header-Datei:
uint8 SpiByte(unsigned char outbyte) __attribute__((noinline));
/* das Attribut sorgt dafuer, dass die funktion IMMER aufgerufen wird
*/
uint8_t SpiByte(unsigned char outbyte)
{
    SPDR = outbyte;
    while(!(SPSR & (1 << SPIF)))
        ;
    return SPDR;
}
hth, Jörg

Autor: Avr Noob (balze)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

@Hmm... :
Danke fuer den Tipp mit avr-size. Leider erstellt der Compiler aber 
scheinbar keine .elf (oder .hex ) Datei mehr, wenn er wegen eines zu 
kleinen Flash abbricht. Deshalb kann ich die Groesse doch nicht 
bestimmen. (Oder ich gehe da falsch ran, kann natuerlich sein, bin 
schliesslich der AVR Noob :)
Danke fuer den Link zur Optimierung, werde ich mir mal genauer ansehen! 
(Ich habe ehrlich gesagt gehofft, dass ich bei diesem Projekt nicht so 
tief einsteigen muss, bin eben noch ziemlich neu auf dem Gebiet)

@Jörg :
Danke fuer Deine Tipps!
Habe ich beides ausprobiert, leider auch ohne Erfolg.

Kann mir jemand erklaeren, warum der Code SOO gross wird mit Hardware 
SPI?

Wenn ich die Funktion so definiere:
uint8 SpiByte(unsigned char outbyte) 
{
/*  
    SPDR = outbyte;
    while(!(SPSR & (1 << SPIF)));
    return SPDR;
*/
while (outbyte-- != 0);
return outbyte;
}

Erhalte ich folgendes Ergebnis:
Program:    7432 bytes (90.7% Full)

Was ist so anders, wenn ich in einer Funktion auf Register zugreife ?

Irgendwie fuehle ich mich gerade dem Compiler ausgeliefert. :)

Immerhin zeigt sich, dass ich meinen Namen mit Bedacht gewaehlt habe :)

MfG,

Balze, der AVR Noob

Autor: Jörg G. (joergderxte)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  uint8 SpiByte(unsigned char outbyte)
>  {
>  ..snip..
>    while (outbyte-- != 0);
>  return outbyte;
>}

wird vom Compiler zu "return = 0;" optimiert und falls du den 
rückgabewert nicht verwendest, fliegt die Funktion ganz raus.
static uint8_t SpiByte(unsigned char outbyte)
{
    SPDR = outbyte;
    while(!(SPSR & (1 << SPIF)))
        ;
    return SPDR;
}
wird zu sowas wie:
  out     SPDR,   r24
1:
  sbis    SPSR,   SPIF
  rjmp    1b
  in      r24,    SPDR
aber die Funktion wird nie aufgerufen sondern immer in den Code 
kopiert (zumindest beim GCC >= 4.) - daher mein Versuch mit "noinline": 
ein simples "rcall SpiByte" ist noch kürzer als die ganze Funkition.

Wenn die Funktion nicht "static" ist, muss der Compiler (genau genommen 
der Linker) aber noch eine Kopie  behalten, falls die Funktion von 
außen doch noch aufgerufen wird (hier könnte der GCC-Parameter 
"-ffunction-sections" helfen, falls der noch nicht im Makefile (oder den 
AVR-Studioproject-settings) steht).

Vielleicht hilft dir noch AVR-GCC-Codeoptimierung, Aber mehr fällt 
mir auch jetzt nicht ein.
Schreib mal, welche GCC-Version du verwendest, evtl. helfen jakleine 
verbesserungen im Makefile noch ("-lm" "-fno-inline-small-functions",
"-fno-split-wide-types", "-fno-tree-scev-cprop", siehe hier: 
Beitrag "WinAvr 20080411 veröffentlicht" und hier 
Beitrag "Re: avr-gcc: 3.4.6 contra 4.3.0" )

hth, Jörg

Autor: Helmut Lenzen (helmi1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn der GCC die Funktion einfach mehrfach in den Code kopiert kann man 
die doch in ein separates File auslagern und sie im dem Programmteil wo 
sie gebraucht wird als "extern" deklarieren.
So ist der Compiler gezwungen die Funktion als Unterprogramm aufzurufen 
und nicht mehrfach in den Code zu kopieren.

Also lager die Funktion mal in eine andere 'C' Datei aus.

Gruss Helmi

Autor: Avr Noob (balze)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Helmut Lenzen wrote:
> Also lager die Funktion mal in eine andere 'C' Datei aus.

Helmi Du bist mein Held !  :)

Du hast Recht, jetzt funktioniert es !!!

Danke Euch alle, die Ihr mir geholfen habt!!

Jetzt kann es weitergehen.
Optimieren werde ich trotzdem noch muessen, damit ich das was ich 
vorhabe auch noch mit ins Flash bekomme. 8-0  ;-)

Danke nochmals, habe wieder eine Menge gelernt !

MfG,

Balze, der AVR Noob

Autor: Helmut Lenzen (helmi1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja ab und zu muss man halt den Compiler zu seinem Glueck zwingen.

Schoen das es jetzt laeuft.

Gruss Helmi

Autor: Avr Noob (balze)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Helmut Lenzen wrote:
> Naja ab und zu muss man halt den Compiler zu seinem Glueck zwingen.

Naja ab und zu muss man einfach nur wissen wie es geht :) THX

Dafuer bin ich einfach ein (noch) zu schlechter C Programmierer.
Das moechte ich aber trotz meines Methusalem gleichen Alters noch 
aendern :)

@Jörg G.:
Ich habe WinAVR-20080512 installiert (gcc-4.3.0)
(Schon Lustig, habe das STK500 zu meinem Geburtstag 2008 bekommen und 
die Version von WinAVR ist nur 10 Tage juenger 8-0 )

Ich habe mir ehrlich gesagt keine grossen Gedanken um die Version der 
Entwicklungsumgebung gemacht, da ich angenommen habe, dass man mit der 
letzten nichts verkehrt macht. Ich haette es als Windows Nutzer 
eigentlich besser wissen muessen und die neue Version zumindest 
hinterfragen sollen. (Hab schliesslich auch kein Vista installiert :)

Nochmal Danke,

MfG,

Balze, der (stets bemuehte) AVR Noob :)

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Helmut Lenzen wrote:
> Also lager die Funktion mal in eine andere 'C' Datei aus.


Dann wirds aber schwierig mit der Registeroptimierung.
Besser also mit "-fno-inline-small-functions" dem GCC seine Inline-Sucht 
abzugewöhnen.


Ich würde aber für die Entwicklung zum ATmega328P raten (z.B. CSD).
Der hat auch noch doppelt SRAM (2kB), könnte für ein Filesystem ganz 
nützlich sein.


Peter

Autor: Avr Noob (balze)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter:

Ja, ich habe auch schon ueber eine "groessere" Alternative nachgedacht.
In meinem (lokalen) Datenblatt vom Mega88 gibt es aber nur den Mega168, 
deshalb waere dieser meine Wahl gewesen, aber 2kByte SRAM waeren 
genial!!

Ist der 328P neu??

THX,

MfG,

Balze, der AVR Noob

P.S.: Hab gerade welche bestellt :) Meine Probleme werden kleiner :)

Autor: Avr Noob (balze)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe noch einen Helden : PETER   :)

Ich habe mal die von Dir vorgeschlagenen Compileroptionen eingestellt.
(Siehe hier: Beitrag "Re: avr-gcc: 3.4.6 contra 4.3.0" )

Und siehe da, auch ohne die Funktion in ein externes File auszulagern

Program:    7574 bytes (92.5% Full)

Dann hab ich ja wieder MASSENHAFT Platz :)

Danke,

mfG,

Balze, der AVR Noob

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.