mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik SPI mit GCC sehr speicherintensiv


Autor: Eddy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
ich versuche grade mein erstes AVR Programm( ATMEGA48) in C zu 
schreiben.
In assembler habe ich schon einige Erfahrungen.
Nun Ich möchte via SPI Daten an ein display übertragen (ls020)
und bin gerade dabei mir die SPI routinen zusammenzufummeln
( teilweise aus atmel app notes)
Mein Problem ist folgendes:
Das warten bis SPIF 1 ist, nimmt unglaubliche 220 bytes ein.
while(!(SPSR & (1<<SPIF)))
als würde das UP niemals aufgerufen Sondern durch ein Makro ersetzt.
Optimiert der gcc das programm nur auf laufzeit?
( optimierungseinstellung os)
Ps ich nutzte das Aktuellste WINAVR unter AVRstudio

#include <avr/io.h>
#include <util/delay.h>    
#define RS PINB2


int main (void){
 spiInit();
 initDisplay();
return 0;
}


void spiInit(void){            // Initialisierung des SPI
 DDRB= (1<<DDB5 | 1<<DDB3 | 1<< DDB2);  // mosi und SCK als ausgang definieren
 SPCR   = (1<<SPE | 1<< MSTR);      // SPI enable, Master
}

 void spiSend(uint8_t data){      // Senden eines Datums
 SPDR = data;               // daten in SPI Datenregister laden
/* Wait for transmission complete */
 while(!(SPSR & (1<<SPIF)))
;

}

void sendCommand(uint8_t datah,uint8_t datal ){  // Befehl an Display senden
 PINB = (1<< RS);          // RS auf high setzten ( display erwartet befehle)
 spiSend(datah);    // In high und low teil senden.
 spiSend(datal);      // low
}


void sendData(uint8_t datah,uint8_t datal ){  // daten an Display senden
 PINB = (0<< RS);          // RS auf high setzten ( display erwartet daten)
 spiSend(datah);    // In high und low teil senden.
 spiSend(datal);      // low
}


void initDisplay(void){
 sendCommand(0xFD,0xFD);
 sendCommand(0xFD,0xFD);
 _delay_ms(50);
 sendCommand(0xEF,0x00);
 sendCommand(0xEE,0x04);
 sendCommand(0x1B,0x04);
 sendCommand(0xFE,0xFE);
 sendCommand(0xFE,0xFE);
 sendCommand(0xEF,0x90);
 sendCommand(0x4A,0x04);
 sendCommand(0x7F,0x3F);
 sendCommand(0xEE,0x04);
 sendCommand(0x43,0x06);


 
}

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Quelltext? Assembler-Listing?

Autor: Eddy (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
quelltext habe ich doch im post. assemblerlisting hab ich vergessen 
sorry.
quelltext mach ich auch och mal als anhang.
danke für die schnelle antwort^^

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist doch ok:
/* Wait for transmission complete */
 while(!(SPSR & (1<<SPIF)))
wird
/* Wait for transmission complete */
 while(!(SPSR & (1<<SPIF)))
  74:  0d b4         in  r0, 0x2d  ; 45
  76:  07 fe         sbrs  r0, 7
  78:  fd cf         rjmp  .-6        ; 0x74 <sendData+0x4>

Ansonsten: Ja, er baut dir ein inline aus der Sende-Prozedur. Sollte 
sich mit -Os aber abstellen lassen. Da wäre dann das Makefile 
interessant...

Autor: Eddy (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Das problem ist halt das ich pro sendevorgang ca 20 byte verliere, 
wobeis eigentlich nur ein unterprogrammaufruf ist. und os scheints eben 
nich abzustellen.
naja werde ich das ganze wohl doch in assembler schreiben müssen.
hardwarenah ist besser glaub ich.

Autor: User (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum möchtest du nicht, dass es geinlined wird?

Du hast zwei Möglichkeiten
1. __attribute__((noinline)) an die Funktion ranpappen
2. -fno-inline als Compileroption.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Laut Makefile übersetzt du den Quelltext mit -O2, da ists kein Wunder, 
dass inlines gebaut werden, solange noch Platz im Speicher frei ist (was 
an sich ja vollkommen ok ist, wenns mal eng wird, wird der GCC sich 
schon melden und anders optimieren).

Autor: Eddy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Simon
wo soll ich das "__attribute__((noinline))" ranpappen?
im c quelltext? ( wenn ja wie und wo^^)
warum ich keine inlines möchte: weil mir der speicherplatz ausgeht wenn 
ich die ganze initialisierungssequenz senden will.
das sind 20 sendebefehle, jedesma 20 byte---> wird entwas eng auf dem 
48er.
würde man das ganze in assembler schreiben würde man vlt 10 % dessen 
benötigen.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der GCC hat doch gar keine Ahnung vom verfügbaren Speicher des MCUs ;)

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1. Lass die Finger weg von _attribute_, der GCC ist nicht annähernd so 
dumm, wie man meint.

2. Übersetze nicht mit -O2, sondern mit -Os. In deinem Makefile steht 
-O2, also Optimierung auf Geschwindigkeit.

3. Verpacke die Initialisierungssequenz in ein const-Array im 
Programmspeicher (PROGMEM) und laufe mit einer Schleife durch. Fertig.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eddy schrieb:
> würde man das ganze in assembler schreiben würde man vlt 10 % dessen
> benötigen.

Das hat nichts mit Assembler oder C zu tun, sondern mit der richtigen 
Bedienung deiner Entwicklungswerkzeuge.
Siehe Post von Sven.


Das __attribute__((noinline)) muss in die Funktionssignatur. Wo genau 
ist nicht so wichtig.

void __attribute__((noinline)) sendCommand(uint8_t datah,uint8_t datal )

PS: ungetestet.
Du solltest aber dringendst erst mal die Os Optimierung wählen. Die 
bringt auf Mikroprozessoren ohnehin meistens mehr als 02

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sven P. schrieb:

> Laut Makefile übersetzt du den Quelltext mit -O2, da ists kein Wunder,
> dass inlines gebaut werden, solange noch Platz im Speicher frei ist (was
> an sich ja vollkommen ok ist, wenns mal eng wird, wird der GCC sich
> schon melden und anders optimieren).

Melder wird er sich, d.h. der Linker wird es. Die Optimierung umstellen 
musst du dann aber schon selber.

Autor: Eddy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Size Optimierung hat nichts gebracht.
__attribute__((noinline)) hingegen schon. ( statt 22% speicherauslastung 
nur 8 % nenn ich mal optimiert^^)
Danke für die schnelle hilfe.
Wie gesagt kenne mich mit der c toolchain für avr noch nicht sehr aus.

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.