SPI mit GCC sehr speicherintensiv

Gast #1529949
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
}
Gast #1529976
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...
Gast #1529977
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.
Angehängte Dateien:
Gast #1529987
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).
Gast #1529992
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.
Gast #1529998
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.
Persönliche Seite #1530001
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
#1530009
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.
Gast #1530013
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren