Forum: Mikrocontroller und Digitale Elektronik SPI mit GCC sehr speicherintensiv


von Eddy (Gast)


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.
1
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

1
#include <avr/io.h>
2
#include <util/delay.h>    
3
#define RS PINB2
4
5
6
int main (void){
7
 spiInit();
8
 initDisplay();
9
return 0;
10
}
11
12
13
void spiInit(void){            // Initialisierung des SPI
14
 DDRB= (1<<DDB5 | 1<<DDB3 | 1<< DDB2);  // mosi und SCK als ausgang definieren
15
 SPCR   = (1<<SPE | 1<< MSTR);      // SPI enable, Master
16
}
17
18
 void spiSend(uint8_t data){      // Senden eines Datums
19
 SPDR = data;               // daten in SPI Datenregister laden
20
/* Wait for transmission complete */
21
 while(!(SPSR & (1<<SPIF)))
22
;
23
24
}
25
26
void sendCommand(uint8_t datah,uint8_t datal ){  // Befehl an Display senden
27
 PINB = (1<< RS);          // RS auf high setzten ( display erwartet befehle)
28
 spiSend(datah);    // In high und low teil senden.
29
 spiSend(datal);      // low
30
}
31
32
33
void sendData(uint8_t datah,uint8_t datal ){  // daten an Display senden
34
 PINB = (0<< RS);          // RS auf high setzten ( display erwartet daten)
35
 spiSend(datah);    // In high und low teil senden.
36
 spiSend(datal);      // low
37
}
38
39
40
void initDisplay(void){
41
 sendCommand(0xFD,0xFD);
42
 sendCommand(0xFD,0xFD);
43
 _delay_ms(50);
44
 sendCommand(0xEF,0x00);
45
 sendCommand(0xEE,0x04);
46
 sendCommand(0x1B,0x04);
47
 sendCommand(0xFE,0xFE);
48
 sendCommand(0xFE,0xFE);
49
 sendCommand(0xEF,0x90);
50
 sendCommand(0x4A,0x04);
51
 sendCommand(0x7F,0x3F);
52
 sendCommand(0xEE,0x04);
53
 sendCommand(0x43,0x06);
54
55
56
 
57
}

von Sven P. (Gast)


Lesenswert?

Quelltext? Assembler-Listing?

von Eddy (Gast)


Angehängte Dateien:

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^^

von Sven P. (Gast)


Lesenswert?

Ist doch ok:
1
/* Wait for transmission complete */
2
 while(!(SPSR & (1<<SPIF)))
wird
1
/* Wait for transmission complete */
2
 while(!(SPSR & (1<<SPIF)))
3
  74:  0d b4         in  r0, 0x2d  ; 45
4
  76:  07 fe         sbrs  r0, 7
5
  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...

von Eddy (Gast)


Angehängte Dateien:

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.

von User (Gast)


Lesenswert?


von Simon K. (simon) Benutzerseite


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.

von Sven P. (Gast)


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).

von Eddy (Gast)


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.

von Simon K. (simon) Benutzerseite


Lesenswert?

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

von Sven P. (Gast)


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.

von Simon K. (simon) Benutzerseite


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

von (prx) A. K. (prx)


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.

von Eddy (Gast)


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.

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.