Forum: Compiler & IDEs AVR und der Umgang mit C++


von Stefan (Gast)


Lesenswert?

Hallo, ich beschäftige mich ein wenig mit C++ und Avr s.
Ich schreibe gerade an einer Classe, ich kann den Konstructor erzeugen 
aber der zugriff auf Methoden bleibt mir versperrt.
1
#include <stdio.h>
2
3
class RX5808 {
4
public:
5
    RX5808( void );
6
    void setFrequency( uint16_t frequency );
7
private:
8
    void setPIN(uint8_t pinNr, uint8_t state);
9
    void spi_1( void );
10
    void spi_0( void );
11
    void spiEnable( bool state );
12
    uint16_t calcFrequencyData( uint16_t frequency );
13
};
14
....
15
16
void init(void) {
17
    RX5808 rx();
18
    rx.setFrequency(0);
19
}
20
21
int main(void) {
22
  init();
23
    
24
    while(1)
25
    {
26
27
    }
28
  return 0; // never reached
29
}

bei rx.setFrequency(0)  kommt Request for member "setFrequency in "rx" 
which is non class typ RX5808()

von Peter II (Gast)


Lesenswert?

lass mal die klammer weg
1
RX5808 rx;

1
void spi_1( void );

bei C++ macht man das nicht mehr, wenn kein Parameter dann klammer leer 
lassen und nicht void reinschreiben

von Stefan (Gast)


Lesenswert?

Wenn ich bei RX5808 rx(); die klammern weg lassen meckert der compile 
das an mit undefined reference to RX5808::RX5808()

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Das ist nicht der Compiler, das ist der Linker.

Und das ist kein Wunder; wo ist die Implementierung des Konstruktors? Du 
hast ihn nur deklariert ...

(Oder hast Du vergessen, das überflüssige "void" zu entfernen?)

von Peter II (Gast)


Lesenswert?

Stefan schrieb:
> Wenn ich bei RX5808 rx(); die klammern weg lassen meckert der compile
> das an mit undefined reference to RX5808::RX5808()

nein, das sagt der Linker.
Ist der Code in verschieden Dateien?

von Stefan (Gast)


Lesenswert?

/main.cpp
/src/"...h"
/src/"...cpp"

Alle libs(h und cpp) befinden sich in src

von Arduinoquäler (Gast)


Lesenswert?

Stefan schrieb:
> bei rx.setFrequency(0)  kommt Request for member "setFrequency in "rx"
> which is non class typ RX5808()

Rufus Τ. F. schrieb:
> Und das ist kein Wunder; wo ist die Implementierung des Konstruktors? Du
> hast ihn nur deklariert ...

Das reicht nicht aus.

Du must auch eine Instanz deiner Klasse anlegen.
Bisher hast du sie nur deklariert.

Also:
1
RX5808 rx;  // Objekt rx anlegen

von Carl D. (jcw2)


Lesenswert?

Peter II schrieb:
> Stefan schrieb:
>> Wenn ich bei RX5808 rx(); die klammern weg lassen meckert der compile
>> das an mit undefined reference to RX5808::RX5808()
>
> nein, das sagt der Linker.
> Ist der Code in verschieden Dateien?

Er (der Linker) hat zuvor nur deshalb nicht gemeckert, weil das schon 
der Compiler gemacht hat.
Ich vermute mal, der TO hat zuvor Java benutzt und stolpert gerade über 
die subtilen Unterschiede zwischen Java und C++. (hab nur gerade keine 
Zeit die runterzuschreiben)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Arduinoquäler schrieb:
> Du must auch eine Instanz deiner Klasse anlegen.

Das macht er:

Stefan schrieb:
> void init(void) {
>     RX5808 rx();
>     rx.setFrequency(0);
> }

von Arduinoquäler (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Das macht er:

... offensichtlich nicht, sonst würde init(void) die
Instanz ja kennen.

von STK500-Besitzer (Gast)


Lesenswert?

Arduinoquäler schrieb:
> ... offensichtlich nicht, sonst würde init(void) die
> Instanz ja kennen.

ein nicht-definierter Konstruktor ist der Grund für den Fehler. Wie 
Rufus schon schrieb.

von Arduinoquäler (Gast)


Lesenswert?

Es macht übrigens auch wenig Sinn in dieser Funktion
1
void init(void)
2
{
3
    RX5808 rx();
4
    rx.setFrequency(0);
5
}

eine Instanz der Klasse anzulegen die global bekannt
sein soll ....

von Peter II (Gast)


Lesenswert?

Arduinoquäler schrieb:
> Es macht übrigens auch wenig Sinn in dieser Funktion

> eine Instanz der Klasse anzulegen die global bekannt
> sein soll ....

wo steht das sie global bekannt sein soll?

von Arduinoquäler (Gast)


Lesenswert?

Peter II schrieb:
> wo steht das sie global bekannt sein soll?

Ja schon gut ... steht nirgends ....

von Arduinoquäler (Gast)


Lesenswert?

STK500-Besitzer schrieb:
> ein nicht-definierter Konstruktor ist der Grund für den Fehler.

Ich hatte im Hinterkpf dass heutige c++ Compiler selbstständig
einen Konstruktor anlegen und bei Instanziierung durchlaufen
lassen, aber scheinbar ist dies beim GCC noch nicht der Fall.

von STK5400-Besitzer (Gast)


Lesenswert?

Arduinoquäler schrieb:
> Ich hatte im Hinterkpf dass heutige c++ Compiler selbstständig
> einen Konstruktor anlegen und bei Instanziierung durchlaufen
> lassen, aber scheinbar ist dies beim GCC noch nicht der Fall.

Ja, wenn er nicht deklariert wurde.

von Arduinoquäler (Gast)


Angehängte Dateien:

Lesenswert?

Ohne weitere Worte. Siehe Source.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du hast das überflüssige "void" noch nicht aus Deiner Deklaration des 
Konstruktors entfernt.

>     RX5808 (void);

Mach das weg.

von Carl D. (jcw2)


Lesenswert?

Arduinoquäler schrieb:
> Es macht übrigens auch wenig Sinn in dieser Funktion
>
>
1
> void init(void)
2
> {
3
>     RX5808 rx();
4
>     rx.setFrequency(0);
5
> }
6
>
>
> eine Instanz der Klasse anzulegen die global bekannt
> sein soll ....

Es ist einfach so, daß in C++ der Default-Konstruktor, also der mit nur 
"()", ohne die beiden Klammer aufgerufen wird. Einfach nur der 
Varablennamen. Der Grund ist ganz einfach. So wie es oben steht, wird 
eine Funktion rx() definiert, die ein Objekt der Klasse RX5808 zurück 
liefert. Das war schon in C so und C++ sollte keine (all zu grossen) 
Semantik-Unterschiede aufweisen.
Also:
1
 RX5808 rx_variable;   // reserviere Platz und Rufe Default-Konstruktor
2
 RX5808 rx_function(); // "der linker wird eine Funktion rx_function
3
                       // finden, die ein RX5808 Objekt zurückgibt
Wenn man sich angewöhnt vor die Funktionsbekanntgabe "extern" zu 
schreiben, wenn man nicht gleich den Funktions-Body hinschreibt, erkennt 
man später schneller, was gemeint ist.

von Carl D. (jcw2)


Lesenswert?

Rufus Τ. F. schrieb:
> Du hast das überflüssige "void" noch nicht aus Deiner Deklaration des
> Konstruktors entfernt.
>
>>     RX5808 (void);
>
> Mach das weg.

Sieht aber nur verwirrend aus, ist aus Sicht des Compilers aber korrekt. 
Ohne "void" ist eigentlich nur "Convenience"

von tictactoe (Gast)


Lesenswert?

C++ zum Programmieren von AVR zu verwenden halte ich prinzipiell für 
eine gute Idee. Mach ich selber auch so.

Meine Empfehlung allerdings: Nicht so:

Stefan schrieb:
> /main.cpp
> /src/"...h"
> /src/"...cpp"
>
> Alle libs(h und cpp) befinden sich in src

sondern schreibe sämtliche Implementierungen in die Header-Dateien (als 
inline Funktionen) und verzichte auf .cpp Dateien außer main.cpp. Dann 
kann der Compiler praktisch alles optimieren. Definiere weiters alle 
globalen Variablen mit 'static', damit sie auch wegoptimiert werden 
können.

von Peter II (Gast)


Lesenswert?

tictactoe schrieb:
> sondern schreibe sämtliche Implementierungen in die Header-Dateien (als
> inline Funktionen) und verzichte auf .cpp Dateien außer main.cpp. Dann
> kann der Compiler praktisch alles optimieren. Definiere weiters alle
> globalen Variablen mit 'static', damit sie auch wegoptimiert werden
> können.

der GCC hat schon eine weile die LTO Funktionalität, damit muss man 
nicht alles in eine Datei schreiben, nur wegen der Optimierung.

von (prx) A. K. (prx)


Lesenswert?

Carl D. schrieb:
> Sieht aber nur verwirrend aus, ist aus Sicht des Compilers aber korrekt.
> Ohne "void" ist eigentlich nur "Convenience"

Typisch für C++ Code ist (), während (void) als Relikt aus C Zeiten 
gilt.

von Bernd K. (prof7bit)


Lesenswert?

Warum willst Du eigentlich überhaupt eine Instanz erzeugen nur um sie 
sofort hinterher wieder wegzuwerfen?

Wenn Deine "Methoden" alle keinen State brauchen dann brauchst Du auch 
keine Klassen und Instanzen sondern bestenfalls Namespaces und normale 
Funktionen.

: Bearbeitet durch User
von tictactoe (Gast)


Lesenswert?

Peter II schrieb:
> der GCC hat schon eine weile die LTO Funktionalität, damit muss man
> nicht alles in eine Datei schreiben, nur wegen der Optimierung.

Hab ich ausprobiert. Das Ergebnis ist WEIT hinter der 
alles-inline-Methode zurückgeblieben.

von Peter II (Gast)


Lesenswert?

tictactoe schrieb:
> Hab ich ausprobiert. Das Ergebnis ist WEIT hinter der
> alles-inline-Methode zurückgeblieben.

ich habe es selber noch nicht getestet, aber hast du auch das LTO bei 
Compiler und beim linker angeben? Sonst Funktioniert es nicht.

von Kaj (Gast)


Lesenswert?

tictactoe schrieb:
> Hab ich ausprobiert. Das Ergebnis ist WEIT hinter der
> alles-inline-Methode zurückgeblieben.
Gib doch mal Beispiel Code, anhand dessen wir alle das nachvollziehen 
können.

von Bernd K. (prof7bit)


Lesenswert?

tictactoe schrieb:
> Peter II schrieb:
>> der GCC hat schon eine weile die LTO Funktionalität, damit muss man
>> nicht alles in eine Datei schreiben, nur wegen der Optimierung.
>
> Hab ich ausprobiert. Das Ergebnis ist WEIT hinter der
> alles-inline-Methode zurückgeblieben.

Dann hast Du was falsch gemacht. Der Linker braucht dazu natürlich auch 
alle Optimierungsflags. Ich benutze das regelmäßig und kann schön 
beobachten wie er zum Beispiel Wrapper-Funktionen (zum Beispiel 
statische Callbacks) über zwei oder mehr Module hinweg problemlos 
inlined.

Seitdem hab ich keine Skrupel mehr zum Beispiel sowas zu schreiben:

1
// uart.c
2
3
void UART0_IRQHandler(void) {
4
    [...]
5
    uart_on_tx_disable();
6
    [...]
7
}
1
// foobus_master.c
2
3
/*
4
 * implement the callbacks from the UART driver
5
 */
6
7
void uart_on_tx_disable(void) {
8
    foobus_master_on_tx_disable();
9
}
1
// main.c
2
3
/*
4
 * implement the callbacks from the FOOBUS driver
5
 */
6
7
void foobus_master_on_tx_disable(void) {
8
    DE_low();
9
}
1
// gpio.h
2
3
static inline void DE_low(void) {
4
    DE_FPT->PCOR = DE_mask;
5
}

Das alles schrumpft durch LTO zusammen auf zwei ASM-Instruktionen im IRQ

: Bearbeitet durch User
von Carl D. (jcw2)


Lesenswert?

A. K. schrieb:
> Carl D. schrieb:
>> Sieht aber nur verwirrend aus, ist aus Sicht des Compilers aber korrekt.
>> Ohne "void" ist eigentlich nur "Convenience"
>
> Typisch für C++ Code ist (), während (void) als Relikt aus C Zeiten
> gilt.

Wir sind uns aber einig, daß beides die gleiche Bedeutung hat, oder?

von (prx) A. K. (prx)


Lesenswert?

Carl D. schrieb:
> Wir sind uns aber einig, daß beides die gleiche Bedeutung hat, oder?

Ja. Steht auch im Standard.

von Carl D. (jcw2)


Lesenswert?

Bernd K. schrieb:
> tictactoe schrieb:
>> Peter II schrieb:
>>> der GCC hat schon eine weile die LTO Funktionalität, damit muss man
>>> nicht alles in eine Datei schreiben, nur wegen der Optimierung.
>>
>> Hab ich ausprobiert. Das Ergebnis ist WEIT hinter der
>> alles-inline-Methode zurückgeblieben.
>
> Dann hast Du was falsch gemacht. Der Linker braucht dazu natürlich auch
> alle Optimierungsflags. Ich benutze das regelmäßig und kann schön
> beobachten wie er zum Beispiel Wrapper-Funktionen (zum Beispiel
> statische Callbacks) über zwei oder mehr Module hinweg problemlos
> inlined.
* implement the callbacks from the UART driver [/c]
> ...
> Das alles schrumpft durch LTO zusammen auf zwei ASM-Instruktionen im IRQ

kann ich zu hundert Prozent bestätigen.
Nur sollte man einen einigermaßen aktuellen Compiler haben (meiner nennt 
sich gerade 6.2, also nicht "sehr alt") und Compiler und Linker müssen 
mit "-Os -flto" gefüttert werden. Beide! Und mit der gleichen 
Optimierungsstufe.

Was dann herauskommt, mag von manchem Experten in Einzelfällen eleganter 
gemacht werden, aber nicht in 500ms. Wenn man z.B. feststellt, daß etwas 
anders gelayoutet ist oder sein sollte, oder low-active doch High-active 
sein soll.

von Plopp (Gast)


Lesenswert?

Carl D. schrieb:
>> Typisch für C++ Code ist (), während (void) als Relikt aus C Zeiten
>> gilt.
>
> Wir sind uns aber einig, daß beides die gleiche Bedeutung hat, oder?

Nur sicherheitshalber, falls jemand über den Thread stolpert und ihn nur 
grob überfliegt: In C++ ja, in C nein.
http://stackoverflow.com/questions/693788/is-it-better-to-use-c-void-arguments-void-foovoid-or-not-void-foo

von Stefan (Gast)


Lesenswert?

So Hallo,

aktuell lag der Fehler im Makefile ich hab ihn aber noch nicht gefunden, 
jetzt sind alle Sources im ersten folder.
1
#include <stdio.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <util/delay.h>
5
6
#include "define.h"
7
#include "RX5808.h"
8
9
// declar
10
11
12
int main(void) {
13
    RX5808 rx;
14
    rx.setFrequency(0);
15
    while(1)
16
    {
17
//        _delay_ms(20);
18
19
        
20
    }
21
22
  return 0; // never reached
23
}

Das ist natürlich klar das rx nicht global definiert war und das war 
jetzt auch nicht das Problem.
Meine Version ist nicht ganz aktuell "avr-gcc (GCC) 4.9.3".
Natürlich braucht es keine Klasse, ich bin einfach nur am 
experimentieren was Sinn und Unsinn im bezug zu den Avr s macht. Die 
Antworten zum Thema optimieren gingen aber schon fast zu weit. Ich 
sollte also den ganzen Code in die .h Datei schreiben, das soll sinn 
machen wieso sollte der Compiler dann besser optimieren können ?

Ich poste gleich mal alles andere damit das hier komplett wird. Wenn ich 
alles richtig verstanden habe ....
1
class RX5808 {
2
public:
3
    RX5808();
4
    void setFrequency( uint16_t frequency );
5
private:
6
    void setPIN( uint8_t pinNr, uint8_t state );
7
    void spi_1();
8
    void spi_0();
9
    void spiEnable( bool state );
10
    uint16_t calcFrequencyData( uint16_t frequency );
11
};
1
// Digital pin definitions , software SPI
2
#define SPI_CLOCK_PIN       2
3
#define SLAVE_SELECT_PIN    3
4
#define SPI_DATA_PIN        4
5
#define LOW                 0
6
#define HIGH                1
7
8
//******************************************************************************
9
//* function: init SPI Pins
10
//******************************************************************************
11
void RX5808::Rx5808(){
12
    DDRD = (1<<SPI_CLOCK_PIN) | (1<<SLAVE_SELECT_PIN) | (1<<SPI_DATA_PIN);
13
}
14
//******************************************************************************
15
//* function: set SPI Pins
16
//******************************************************************************
17
void RX5808::setPIN( uint8_t pinNr, uint8_t state){
18
    if (state) {
19
        PORTD = 1<<pinNr ;
20
    }else{
21
        PORTD = 0<<pinNr ;
22
    }
23
}
24
//******************************************************************************
25
//* function: spi_1
26
//******************************************************************************
27
void RX5808::spi_1()
28
{
29
    
30
    setPIN(SPI_CLOCK_PIN, LOW);
31
    _delay_us(1);
32
    setPIN(SPI_DATA_PIN, HIGH);
33
    _delay_us(1);
34
    setPIN(SPI_CLOCK_PIN, HIGH);
35
    _delay_us(1);
36
    setPIN(SPI_CLOCK_PIN, LOW);
37
    _delay_us(1);
38
}
39
40
//******************************************************************************
41
//* function: spi_0
42
//******************************************************************************
43
void RX5808::spi_0()
44
{
45
    setPIN(SPI_CLOCK_PIN, LOW);
46
    _delay_us(1);
47
    setPIN(SPI_DATA_PIN, LOW);
48
    _delay_us(1);
49
    setPIN(SPI_CLOCK_PIN, HIGH);
50
    _delay_us(1);
51
    setPIN(SPI_CLOCK_PIN, LOW);
52
    _delay_us(1);
53
}
54
55
//******************************************************************************
56
//* function: spiEnableLow
57
//******************************************************************************
58
void RX5808::spiEnable(bool state)
59
{
60
    if (state) {
61
        _delay_us(1);
62
        setPIN(SLAVE_SELECT_PIN, HIGH);
63
        _delay_us(1);
64
        
65
    }else{
66
        _delay_us(1);
67
        setPIN(SLAVE_SELECT_PIN, LOW);
68
        _delay_us(1);
69
        
70
    }
71
}
72
73
//******************************************************************************
74
//* function: calcFrequencyData
75
//*         : calculates the frequency value for the syntheziser register B of
76
//*         : the RTC6751 circuit that is used within the RX5808/RX5880 modules.
77
//*         : this value is inteded to be loaded to register at adress 1 via SPI
78
//*         :
79
//*  Formula: frequency = ( N*32 + A )*2 + 479
80
//******************************************************************************
81
uint16_t RX5808::calcFrequencyData( uint16_t frequency )
82
{
83
    uint16_t N;
84
    uint8_t A;
85
    frequency = (frequency - 479) / 2;
86
    N = frequency / 32;
87
    A = frequency % 32;
88
    return (N << 7) |  A;
89
}
90
91
//******************************************************************************
92
//* function: setRTC6715Frequency
93
//*         : for a given frequency the register setting for synth register B of
94
//*         : the RTC6715 circuit is calculated and bitbanged via the SPI bus
95
//*         : please note that the synth register A is assumed to have default
96
//*         : values.
97
//*
98
//* SPI data: 4  bits  Register Address  LSB first
99
//*         : 1  bit   Read or Write     0=Read 1=Write
100
//*         : 13 bits  N-Register Data   LSB first
101
//*         : 7  bits  A-Register        LSB first
102
//******************************************************************************
103
104
void RX5808::setFrequency( uint16_t frequency){
105
    
106
    uint16_t sRegB;
107
    uint8_t i;
108
    
109
    sRegB = calcFrequencyData(frequency);
110
    
111
    // Bit bang the syntheziser register
112
    
113
    // Clock
114
    spiEnable(true);
115
    _delay_us(1);
116
    spiEnable(false);
117
    
118
    // Address (0x1)
119
    spi_1();
120
    spi_0();
121
    spi_0();
122
    spi_0();
123
    
124
    // Read/Write (Write)
125
    spi_1();
126
    
127
    // Data (16 LSB bits)
128
    for (i = 16; i; i--, sRegB >>= 1 ) {
129
        (sRegB & 0x1) ? spi_1() : spi_0();
130
    }
131
    // Data zero padding
132
    spi_0();
133
    spi_0();
134
    spi_0();
135
    spi_0();
136
    
137
    // Clock
138
    spiEnable(true);
139
    _delay_us(1);
140
    
141
    setPIN(SLAVE_SELECT_PIN, LOW);
142
    setPIN(SPI_CLOCK_PIN, LOW);
143
    setPIN(SPI_DATA_PIN, LOW);
144
}

von Peter II (Gast)


Lesenswert?

Stefan schrieb:
> if (state) {
>         PORTD = 1<<pinNr ;
>     }else{
>         PORTD = 0<<pinNr ;
>     }

also das ist mehr als falsch.

Willst du wirklich alle Bits auf dem Port ändern?
eine 0 kann man schieben wie man will, es bleibt eine 0.


Selbst wenn die Fehler weg sein, ist es sehr ungünstig für die Compiler. 
Weil er vermutlich nicht erkennt, das er den Port mit einer Bitoperation 
bearbeitet kann, es wird auf ein Read-Modify-Write hinauslaufen. Das ist 
langsam und kann ungewünschte Effekte erzeugen.

Es gibt gute gründe warum
[/c]
PORTD |= 1<<pinNr;
[c]
lieber als Makro verwendet wird, hier ist die Kapselung in Methoden 
nicht so einfach.

von Bernd K. (prof7bit)


Lesenswert?

Peter II schrieb:
> Es gibt gute gründe warum [/c]
> PORTD |= 1<<pinNr;
> [c]
> lieber als Makro verwendet wird, hier ist die Kapselung in Methoden
> nicht so einfach.

Unterschätze nicht den Compiler. Wenn er beweisen kann daß pinNr 
konstant ist stehen die Chancen gut dass er an Ort und Stelle ein SBI 
einbaut anstelle eines Methodenaufrufs.

von Stefan (Gast)


Lesenswert?

Peter II schrieb:
> Stefan schrieb:
>> if (state) {
>>         PORTD = 1<<pinNr ;
>>     }else{
>>         PORTD = 0<<pinNr ;
>>     }
>
> also das ist mehr als falsch.
>

Der Code ist noch nicht getestet, stimmt natürlich das war Blödsinn

void RX5808::setPIN( uint8_t pinNr, uint8_t state){
    if (state) {
        PORTD != (1<<pinNr) ;
    }else{
        PORTD &= ~(1<<pinNr) ;
    }
}

Aber es wäre besser als Makro ? Ich könnte mir vorstellen das es als 
Makro Performern wäre da es Inline ausgeführt wird. Bei der Funktion 
muss er sich erst mal die Sprungadresse merken und wieder zurück 
springen ?

von Carl D. (jcw2)


Lesenswert?

Stefan schrieb:
> Aber es wäre besser als Makro ? Ich könnte mir vorstellen das es als
> Makro Performern wäre da es Inline ausgeführt wird. Bei der Funktion
> muss er sich erst mal die Sprungadresse merken und wieder zurück
> springen ?

Beim C-Lernen auf einem AVR macht es Sinn sich die .lss-Datei 
anzuschauen. Da ist man doch (anfangs) überrascht, was der Compiler so 
produziert. Wenige können es (über alles betrachtet) besser und keiner 
von denen auch nur annähernd so schnell. Und viele Gerüchte erkennt man 
als solche.

von Peter II (Gast)


Lesenswert?

Stefan schrieb:
> Aber es wäre besser als Makro ?
> PORTD &= ~(1<<pinNr) ;

der Compiler muss erkennen das PinNr eine Konstante ist, dann wird 
daraus ein SetBit oder ClearBit. Wenn er das nicht erkennt dann wird das 
sehr umständlicher code.

erst wird 1<<PinNr ausgerechnet (was nur über eine schleife geht). Dann 
wird der Port gelesen, die oder Verknüpfung gemacht und dann wird das 
Ergebnis wieder in PortD geschrieben.


Bei einer Methode kann man sich kaum 100% darauf verlassen, das er es 
immer erkennt (hängt von viele Faktoren ab, ob es in der gleichen 
Übersetzungseinheit ist, wie oft die Methode verwendet wird usw.)

Vermutlich geht es dann auch nur mit Optimierung, wogegen es beim Makro 
immer funktioniert.

von Stefan (Gast)


Lesenswert?

Carl D. schrieb:
> Stefan schrieb:
> Beim C-Lernen auf einem AVR macht es Sinn sich die .lss-Datei
> anzuschauen. Da ist man doch (anfangs) überrascht, was der Compiler so
> produziert. Wenige können es (über alles betrachtet) besser und keiner
> von denen auch nur annähernd so schnell. Und viele Gerüchte erkennt man
> als solche.

Gut ich hab mir die .lss jetzt mal angesehen und ehrlich gesagt auch das 
erste mal für mich sieht das jetzt aus wie der tatsächliche Assembler 
code nach der Optimierung ?
1
Builds/main.elf:     file format elf32-avr
2
3
Sections:
4
Idx Name          Size      VMA       LMA       File off  Algn
5
  0 .data         00000000  00800100  00000388  000003fc  2**0
6
                  CONTENTS, ALLOC, LOAD, DATA
7
  1 .text         00000388  00000000  00000000  00000074  2**1
8
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
9
  2 .stab         00001fec  00000000  00000000  000003fc  2**2
10
                  CONTENTS, READONLY, DEBUGGING
11
  3 .stabstr      00002079  00000000  00000000  000023e8  2**0
12
                  CONTENTS, READONLY, DEBUGGING
13
  4 .comment      00000011  00000000  00000000  00004461  2**0
14
                  CONTENTS, READONLY
15
  5 .debug_aranges 00000020  00000000  00000000  00004478  2**3
16
                  CONTENTS, READONLY, DEBUGGING
17
  6 .debug_info   000000be  00000000  00000000  00004498  2**0
18
                  CONTENTS, READONLY, DEBUGGING
19
  7 .debug_abbrev 00000014  00000000  00000000  00004556  2**0
20
                  CONTENTS, READONLY, DEBUGGING
21
  8 .debug_line   00000058  00000000  00000000  0000456a  2**0
22
                  CONTENTS, READONLY, DEBUGGING
23
24
Disassembly of section .text:
25
26
00000000 <__vectors>:
27
   0:  0c 94 34 00   jmp  0x68  ; 0x68 <__ctors_end>
28
   4:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
29
   8:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
30
   c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
31
  10:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
32
  14:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
33
  18:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
34
  1c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
35
  20:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
36
  24:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
37
  28:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
38
  2c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
39
  30:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
40
  34:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
41
  38:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
42
  3c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
43
  40:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
44
  44:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
45
  48:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
46
  4c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
47
  50:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
48
  54:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
49
  58:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
50
  5c:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
51
  60:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
52
  64:  0c 94 3e 00   jmp  0x7c  ; 0x7c <__bad_interrupt>
53
54
00000068 <__ctors_end>:
55
  68:  11 24         eor  r1, r1
56
  6a:  1f be         out  0x3f, r1  ; 63
57
  6c:  cf ef         ldi  r28, 0xFF  ; 255
58
  6e:  d8 e0         ldi  r29, 0x08  ; 8
59
  70:  de bf         out  0x3e, r29  ; 62
60
  72:  cd bf         out  0x3d, r28  ; 61
61
  74:  0e 94 b2 01   call  0x364  ; 0x364 <main>
62
  78:  0c 94 c2 01   jmp  0x384  ; 0x384 <_exit>
63
64
0000007c <__bad_interrupt>:
65
  7c:  0c 94 00 00   jmp  0  ; 0x0 <__vectors>
66
67
00000080 <_ZN6RX5808C1Ev>:
68
69
//******************************************************************************
70
//* function: init SPI Pins
71
//******************************************************************************
72
RX5808::RX5808(){
73
    DDRD = (1<<SPI_CLOCK_PIN) | (1<<SLAVE_SELECT_PIN) | (1<<SPI_DATA_PIN);
74
  80:  8c e1         ldi  r24, 0x1C  ; 28
75
  82:  8a b9         out  0x0a, r24  ; 10
76
  84:  08 95         ret
77
78
00000086 <_ZN6RX58086setPINEhh>:
79
}
80
//******************************************************************************
81
//* function: set SPI Pins
82
//******************************************************************************
83
void RX5808::setPIN( uint8_t pinNr, uint8_t state){
84
    if (state) {
85
  86:  44 23         and  r20, r20
86
  88:  49 f0         breq  .+18       ; 0x9c <_ZN6RX58086setPINEhh+0x16>
87
        PORTD = 1<<pinNr ;
88
  8a:  81 e0         ldi  r24, 0x01  ; 1
89
  8c:  90 e0         ldi  r25, 0x00  ; 0
90
  8e:  06 2e         mov  r0, r22
91
  90:  01 c0         rjmp  .+2        ; 0x94 <_ZN6RX58086setPINEhh+0xe>
92
  92:  88 0f         add  r24, r24
93
  94:  0a 94         dec  r0
94
  96:  ea f7         brpl  .-6        ; 0x92 <_ZN6RX58086setPINEhh+0xc>
95
  98:  8b b9         out  0x0b, r24  ; 11
96
  9a:  08 95         ret
97
    }else{
98
        PORTD = 0<<pinNr ;
99
  9c:  1b b8         out  0x0b, r1  ; 11
100
  9e:  08 95         ret
101
102
000000a0 <_ZN6RX58085spi_1Ev>:
103
  a0:  1b b8         out  0x0b, r1  ; 11
104
  #else
105
    //round up by default
106
    __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
107
  #endif
108
109
  __builtin_avr_delay_cycles(__ticks_dc);
110
  a2:  82 e0         ldi  r24, 0x02  ; 2
111
  a4:  8a 95         dec  r24
112
  a6:  f1 f7         brne  .-4        ; 0xa4 <_ZN6RX58085spi_1Ev+0x4>
113
  a8:  00 c0         rjmp  .+0        ; 0xaa <_ZN6RX58085spi_1Ev+0xa>
114
        PORTD = 1<<pinNr ;
115
  aa:  80 e1         ldi  r24, 0x10  ; 16
116
  ac:  8b b9         out  0x0b, r24  ; 11
117
  ae:  82 e0         ldi  r24, 0x02  ; 2
118
  b0:  8a 95         dec  r24
119
  b2:  f1 f7         brne  .-4        ; 0xb0 <_ZN6RX58085spi_1Ev+0x10>
120
  b4:  00 c0         rjmp  .+0        ; 0xb6 <_ZN6RX58085spi_1Ev+0x16>
121
  b6:  84 e0         ldi  r24, 0x04  ; 4
122
  b8:  8b b9         out  0x0b, r24  ; 11
123
  ba:  82 e0         ldi  r24, 0x02  ; 2
124
  bc:  8a 95         dec  r24
125
  be:  f1 f7         brne  .-4        ; 0xbc <_ZN6RX58085spi_1Ev+0x1c>
126
  c0:  00 c0         rjmp  .+0        ; 0xc2 <_ZN6RX58085spi_1Ev+0x22>
127
        PORTD = 0<<pinNr ;
128
  c2:  1b b8         out  0x0b, r1  ; 11
129
  c4:  82 e0         ldi  r24, 0x02  ; 2
130
  c6:  8a 95         dec  r24
131
  c8:  f1 f7         brne  .-4        ; 0xc6 <_ZN6RX58085spi_1Ev+0x26>
132
  ca:  00 c0         rjmp  .+0        ; 0xcc <_ZN6RX58085spi_1Ev+0x2c>
133
  cc:  08 95         ret
134
135
000000ce <_ZN6RX58085spi_0Ev>:
136
  ce:  1b b8         out  0x0b, r1  ; 11
137
  d0:  82 e0         ldi  r24, 0x02  ; 2
138
  d2:  8a 95         dec  r24
139
  d4:  f1 f7         brne  .-4        ; 0xd2 <_ZN6RX58085spi_0Ev+0x4>
140
  d6:  00 c0         rjmp  .+0        ; 0xd8 <_ZN6RX58085spi_0Ev+0xa>
141
  d8:  1b b8         out  0x0b, r1  ; 11
142
  da:  82 e0         ldi  r24, 0x02  ; 2
143
  dc:  8a 95         dec  r24
144
  de:  f1 f7         brne  .-4        ; 0xdc <_ZN6RX58085spi_0Ev+0xe>
145
  e0:  00 c0         rjmp  .+0        ; 0xe2 <_ZN6RX58085spi_0Ev+0x14>
146
        PORTD = 1<<pinNr ;
147
  e2:  84 e0         ldi  r24, 0x04  ; 4
148
  e4:  8b b9         out  0x0b, r24  ; 11
149
  e6:  82 e0         ldi  r24, 0x02  ; 2
150
  e8:  8a 95         dec  r24
151
  ea:  f1 f7         brne  .-4        ; 0xe8 <_ZN6RX58085spi_0Ev+0x1a>
152
  ec:  00 c0         rjmp  .+0        ; 0xee <_ZN6RX58085spi_0Ev+0x20>
153
        PORTD = 0<<pinNr ;
154
  ee:  1b b8         out  0x0b, r1  ; 11
155
  f0:  82 e0         ldi  r24, 0x02  ; 2
156
  f2:  8a 95         dec  r24
157
  f4:  f1 f7         brne  .-4        ; 0xf2 <_ZN6RX58085spi_0Ev+0x24>
158
  f6:  00 c0         rjmp  .+0        ; 0xf8 <_ZN6RX58085spi_0Ev+0x2a>
159
  f8:  08 95         ret
160
161
000000fa <_ZN6RX58089spiEnableEb>:
162
//******************************************************************************
163
//* function: spiEnableLow
164
//******************************************************************************
165
void RX5808::spiEnable(bool state)
166
{
167
    if (state) {
168
  fa:  66 23         and  r22, r22
169
  fc:  39 f0         breq  .+14       ; 0x10c <_ZN6RX58089spiEnableEb+0x12>
170
  fe:  82 e0         ldi  r24, 0x02  ; 2
171
 100:  8a 95         dec  r24
172
 102:  f1 f7         brne  .-4        ; 0x100 <_ZN6RX58089spiEnableEb+0x6>
173
 104:  00 c0         rjmp  .+0        ; 0x106 <_ZN6RX58089spiEnableEb+0xc>
174
        PORTD = 1<<pinNr ;
175
 106:  88 e0         ldi  r24, 0x08  ; 8
176
 108:  8b b9         out  0x0b, r24  ; 11
177
 10a:  05 c0         rjmp  .+10       ; 0x116 <_ZN6RX58089spiEnableEb+0x1c>
178
 10c:  82 e0         ldi  r24, 0x02  ; 2
179
 10e:  8a 95         dec  r24
180
 110:  f1 f7         brne  .-4        ; 0x10e <_ZN6RX58089spiEnableEb+0x14>
181
 112:  00 c0         rjmp  .+0        ; 0x114 <_ZN6RX58089spiEnableEb+0x1a>
182
        PORTD = 0<<pinNr ;
183
 114:  1b b8         out  0x0b, r1  ; 11
184
 116:  82 e0         ldi  r24, 0x02  ; 2
185
 118:  8a 95         dec  r24
186
 11a:  f1 f7         brne  .-4        ; 0x118 <_ZN6RX58089spiEnableEb+0x1e>
187
 11c:  00 c0         rjmp  .+0        ; 0x11e <_ZN6RX58089spiEnableEb+0x24>
188
 11e:  08 95         ret
189
190
00000120 <_ZN6RX580817calcFrequencyDataEj>:
191
//******************************************************************************
192
uint16_t RX5808::calcFrequencyData( uint16_t frequency )
193
{
194
    uint16_t N;
195
    uint8_t A;
196
    frequency = (frequency - 479) / 2;
197
 120:  6f 5d         subi  r22, 0xDF  ; 223
198
 122:  71 40         sbci  r23, 0x01  ; 1
199
 124:  cb 01         movw  r24, r22
200
 126:  96 95         lsr  r25
201
 128:  87 95         ror  r24
202
    N = frequency / 32;
203
    A = frequency % 32;
204
 12a:  28 2f         mov  r18, r24
205
 12c:  2f 71         andi  r18, 0x1F  ; 31
206
    N = frequency / 32;
207
 12e:  cb 01         movw  r24, r22
208
 130:  36 e0         ldi  r19, 0x06  ; 6
209
 132:  96 95         lsr  r25
210
 134:  87 95         ror  r24
211
 136:  3a 95         dec  r19
212
 138:  e1 f7         brne  .-8        ; 0x132 <_ZN6RX580817calcFrequencyDataEj+0x12>
213
    return (N << 7) |  A;
214
 13a:  96 95         lsr  r25
215
 13c:  98 2f         mov  r25, r24
216
 13e:  88 27         eor  r24, r24
217
 140:  97 95         ror  r25
218
 142:  87 95         ror  r24
219
}
220
 144:  82 2b         or  r24, r18
221
 146:  08 95         ret
222
223
00000148 <_ZN6RX580812setFrequencyEj>:
224
//*         : 1  bit   Read or Write     0=Read 1=Write
225
//*         : 13 bits  N-Register Data   LSB first
226
//*         : 7  bits  A-Register        LSB first
227
//******************************************************************************
228
229
void RX5808::setFrequency( uint16_t frequency){
230
 148:  ff 92         push  r15
231
 14a:  0f 93         push  r16
232
 14c:  1f 93         push  r17
233
 14e:  cf 93         push  r28
234
 150:  df 93         push  r29
235
 152:  ec 01         movw  r28, r24
236
    
237
    uint16_t sRegB;
238
    uint8_t i;
239
    
240
    sRegB = calcFrequencyData(frequency);
241
 154:  0e 94 90 00   call  0x120  ; 0x120 <_ZN6RX580817calcFrequencyDataEj>
242
 158:  8c 01         movw  r16, r24
243
 15a:  82 e0         ldi  r24, 0x02  ; 2
244
 15c:  8a 95         dec  r24
245
 15e:  f1 f7         brne  .-4        ; 0x15c <_ZN6RX580812setFrequencyEj+0x14>
246
 160:  00 c0         rjmp  .+0        ; 0x162 <_ZN6RX580812setFrequencyEj+0x1a>
247
        PORTD = 1<<pinNr ;
248
 162:  88 e0         ldi  r24, 0x08  ; 8
249
 164:  8b b9         out  0x0b, r24  ; 11
250
 166:  82 e0         ldi  r24, 0x02  ; 2
251
 168:  8a 95         dec  r24
252
 16a:  f1 f7         brne  .-4        ; 0x168 <_ZN6RX580812setFrequencyEj+0x20>
253
 16c:  00 c0         rjmp  .+0        ; 0x16e <_ZN6RX580812setFrequencyEj+0x26>
254
 16e:  82 e0         ldi  r24, 0x02  ; 2
255
 170:  8a 95         dec  r24
256
 172:  f1 f7         brne  .-4        ; 0x170 <_ZN6RX580812setFrequencyEj+0x28>
257
 174:  00 c0         rjmp  .+0        ; 0x176 <_ZN6RX580812setFrequencyEj+0x2e>
258
 176:  82 e0         ldi  r24, 0x02  ; 2
259
 178:  8a 95         dec  r24
260
 17a:  f1 f7         brne  .-4        ; 0x178 <_ZN6RX580812setFrequencyEj+0x30>
261
 17c:  00 c0         rjmp  .+0        ; 0x17e <_ZN6RX580812setFrequencyEj+0x36>
262
        PORTD = 0<<pinNr ;
263
 17e:  1b b8         out  0x0b, r1  ; 11
264
 180:  82 e0         ldi  r24, 0x02  ; 2
265
 182:  8a 95         dec  r24
266
 184:  f1 f7         brne  .-4        ; 0x182 <_ZN6RX580812setFrequencyEj+0x3a>
267
 186:  00 c0         rjmp  .+0        ; 0x188 <_ZN6RX580812setFrequencyEj+0x40>
268
    spiEnable(true);
269
    _delay_us(1);
270
    spiEnable(false);
271
    
272
    // Address (0x1)
273
    spi_1();
274
 188:  ce 01         movw  r24, r28
275
 18a:  0e 94 50 00   call  0xa0  ; 0xa0 <_ZN6RX58085spi_1Ev>
276
    spi_0();
277
 18e:  ce 01         movw  r24, r28
278
 190:  0e 94 67 00   call  0xce  ; 0xce <_ZN6RX58085spi_0Ev>
279
    spi_0();
280
 194:  ce 01         movw  r24, r28
281
 196:  0e 94 67 00   call  0xce  ; 0xce <_ZN6RX58085spi_0Ev>
282
    spi_0();
283
 19a:  ce 01         movw  r24, r28
284
 19c:  0e 94 67 00   call  0xce  ; 0xce <_ZN6RX58085spi_0Ev>
285
    
286
    // Read/Write (Write)
287
    spi_1();
288
 1a0:  ce 01         movw  r24, r28
289
 1a2:  0e 94 50 00   call  0xa0  ; 0xa0 <_ZN6RX58085spi_1Ev>
290
 1a6:  60 e1         ldi  r22, 0x10  ; 16
291
 1a8:  f6 2e         mov  r15, r22
292
    
293
    // Data (16 LSB bits)
294
    for (i = 16; i; i--, sRegB >>= 1 ) {
295
        (sRegB & 0x1) ? spi_1() : spi_0();
296
 1aa:  ce 01         movw  r24, r28
297
 1ac:  00 ff         sbrs  r16, 0
298
 1ae:  03 c0         rjmp  .+6        ; 0x1b6 <_ZN6RX580812setFrequencyEj+0x6e>
299
 1b0:  0e 94 50 00   call  0xa0  ; 0xa0 <_ZN6RX58085spi_1Ev>
300
 1b4:  02 c0         rjmp  .+4        ; 0x1ba <_ZN6RX580812setFrequencyEj+0x72>
301
 1b6:  0e 94 67 00   call  0xce  ; 0xce <_ZN6RX58085spi_0Ev>
302
    for (i = 16; i; i--, sRegB >>= 1 ) {
303
 1ba:  16 95         lsr  r17
304
 1bc:  07 95         ror  r16
305
 1be:  fa 94         dec  r15
306
 1c0:  a1 f7         brne  .-24       ; 0x1aa <_ZN6RX580812setFrequencyEj+0x62>
307
    }
308
    // Data zero padding
309
    spi_0();
310
 1c2:  ce 01         movw  r24, r28
311
 1c4:  0e 94 67 00   call  0xce  ; 0xce <_ZN6RX58085spi_0Ev>
312
    spi_0();
313
 1c8:  ce 01         movw  r24, r28
314
 1ca:  0e 94 67 00   call  0xce  ; 0xce <_ZN6RX58085spi_0Ev>
315
    spi_0();
316
 1ce:  ce 01         movw  r24, r28
317
 1d0:  0e 94 67 00   call  0xce  ; 0xce <_ZN6RX58085spi_0Ev>
318
    spi_0();
319
 1d4:  ce 01         movw  r24, r28
320
 1d6:  0e 94 67 00   call  0xce  ; 0xce <_ZN6RX58085spi_0Ev>
321
 1da:  82 e0         ldi  r24, 0x02  ; 2
322
 1dc:  8a 95         dec  r24
323
 1de:  f1 f7         brne  .-4        ; 0x1dc <_ZN6RX580812setFrequencyEj+0x94>
324
 1e0:  00 c0         rjmp  .+0        ; 0x1e2 <_ZN6RX580812setFrequencyEj+0x9a>
325
        PORTD = 1<<pinNr ;
326
 1e2:  88 e0         ldi  r24, 0x08  ; 8
327
 1e4:  8b b9         out  0x0b, r24  ; 11
328
 1e6:  82 e0         ldi  r24, 0x02  ; 2
329
 1e8:  8a 95         dec  r24
330
 1ea:  f1 f7         brne  .-4        ; 0x1e8 <_ZN6RX580812setFrequencyEj+0xa0>
331
 1ec:  00 c0         rjmp  .+0        ; 0x1ee <_ZN6RX580812setFrequencyEj+0xa6>
332
 1ee:  82 e0         ldi  r24, 0x02  ; 2
333
 1f0:  8a 95         dec  r24
334
 1f2:  f1 f7         brne  .-4        ; 0x1f0 <_ZN6RX580812setFrequencyEj+0xa8>
335
 1f4:  00 c0         rjmp  .+0        ; 0x1f6 <_ZN6RX580812setFrequencyEj+0xae>
336
        PORTD = 0<<pinNr ;
337
 1f6:  1b b8         out  0x0b, r1  ; 11
338
 1f8:  1b b8         out  0x0b, r1  ; 11
339
 1fa:  1b b8         out  0x0b, r1  ; 11
340
    _delay_us(1);
341
    
342
    setPIN(SLAVE_SELECT_PIN, LOW);
343
    setPIN(SPI_CLOCK_PIN, LOW);
344
    setPIN(SPI_DATA_PIN, LOW);
345
}
346
 1fc:  df 91         pop  r29
347
 1fe:  cf 91         pop  r28
348
 200:  1f 91         pop  r17
349
 202:  0f 91         pop  r16
350
 204:  ff 90         pop  r15
351
 206:  08 95         ret
352
353
00000208 <_Z8spi_initv>:
354
void spi_init()
355
// Initialize pins for spi communication
356
{
357
//    DDRB &= ~((1<<MOSI)|(1<<MISO)|(1<<SS)|(1<<SCK));
358
    // Define the following pins as output
359
    DDRB |= ((1<<MOSI)|(1<<SS)|(1<<SCK)) | (1<<RESET);
360
 208:  84 b1         in  r24, 0x04  ; 4
361
 20a:  8d 62         ori  r24, 0x2D  ; 45
362
 20c:  84 b9         out  0x04, r24  ; 4
363
            (0<<SPIE)|              // SPI Interupt Enable
364
            (0<<DORD)|              // Data Order (0:MSB first / 1:LSB first)
365
            (1<<MSTR)|              // Master/Slave select
366
            (0<<SPR1)|(1<<SPR0)|    // SPI Clock Rate
367
            (0<<CPOL)|              // Clock Polarity (0:SCK low / 1:SCK hi when idle)
368
            (0<<CPHA));             // Clock Phase (0:leading / 1:trailing edge sampling)
369
 20e:  81 e5         ldi  r24, 0x51  ; 81
370
 210:  8c bd         out  0x2c, r24  ; 44
371
    
372
    SPSR = (1<<SPI2X);              // Double Clock Rate
373
 212:  81 e0         ldi  r24, 0x01  ; 1
374
 214:  8d bd         out  0x2d, r24  ; 45
375
    
376
    PORTB |= (1<<PB2);              //set SS to hight = deselected
377
 216:  2a 9a         sbi  0x05, 2  ; 5
378
 218:  08 95         ret
379
380
0000021a <_Z15spi_selectSlaveb>:
381
}
382
383
void spi_selectSlave(bool select){
384
    if( select ){
385
 21a:  88 23         and  r24, r24
386
 21c:  11 f0         breq  .+4        ; 0x222 <_Z15spi_selectSlaveb+0x8>
387
        PORTB &= ~(1<<PB2);          //set SS to low , selected
388
 21e:  2a 98         cbi  0x05, 2  ; 5
389
 220:  08 95         ret
390
    }else{
391
        PORTB |= (1<<PB2);
392
 222:  2a 9a         sbi  0x05, 2  ; 5
393
 224:  08 95         ret
394
395
00000226 <_Z17spi_transfer_syncPhS_h>:
396
    }
397
}
398
399
void spi_transfer_sync (uint8_t * dataout, uint8_t * datain, uint8_t len)
400
// Shift full array through target device
401
{
402
 226:  26 2f         mov  r18, r22
403
    uint8_t i;
404
    for (i = 0; i < len; i++) {
405
 228:  fb 01         movw  r30, r22
406
 22a:  3e 2f         mov  r19, r30
407
 22c:  32 1b         sub  r19, r18
408
 22e:  34 17         cp  r19, r20
409
 230:  50 f4         brcc  .+20       ; 0x246 <_Z17spi_transfer_syncPhS_h+0x20>
410
        SPDR = dataout[i];
411
 232:  dc 01         movw  r26, r24
412
 234:  3d 91         ld  r19, X+
413
 236:  cd 01         movw  r24, r26
414
 238:  3e bd         out  0x2e, r19  ; 46
415
        while((SPSR & (1<<SPIF))==0);
416
 23a:  0d b4         in  r0, 0x2d  ; 45
417
 23c:  07 fe         sbrs  r0, 7
418
 23e:  fd cf         rjmp  .-6        ; 0x23a <_Z17spi_transfer_syncPhS_h+0x14>
419
        datain[i] = SPDR;
420
 240:  3e b5         in  r19, 0x2e  ; 46
421
 242:  31 93         st  Z+, r19
422
 244:  f2 cf         rjmp  .-28       ; 0x22a <_Z17spi_transfer_syncPhS_h+0x4>
423
    }
424
}
425
 246:  08 95         ret
426
427
00000248 <_Z17spi_transmit_syncPhh>:
428
429
void spi_transmit_sync (uint8_t * dataout, uint8_t len)
430
// Shift full array to target device without receiving any byte
431
{
432
 248:  28 2f         mov  r18, r24
433
    uint8_t i;
434
    for (i = 0; i < len; i++) {
435
 24a:  fc 01         movw  r30, r24
436
 24c:  8e 2f         mov  r24, r30
437
 24e:  82 1b         sub  r24, r18
438
 250:  86 17         cp  r24, r22
439
 252:  30 f4         brcc  .+12       ; 0x260 <_Z17spi_transmit_syncPhh+0x18>
440
        SPDR = dataout[i];
441
 254:  81 91         ld  r24, Z+
442
 256:  8e bd         out  0x2e, r24  ; 46
443
        while((SPSR & (1<<SPIF))==0);
444
 258:  0d b4         in  r0, 0x2d  ; 45
445
 25a:  07 fe         sbrs  r0, 7
446
 25c:  fd cf         rjmp  .-6        ; 0x258 <_Z17spi_transmit_syncPhh+0x10>
447
 25e:  f6 cf         rjmp  .-20       ; 0x24c <_Z17spi_transmit_syncPhh+0x4>
448
    }
449
}
450
 260:  08 95         ret
451
452
00000262 <_Z14spi_fast_shifth>:
453
454
uint8_t spi_fast_shift (uint8_t data)
455
// Clocks only one byte to target device and returns the received one
456
{
457
    SPDR = data;
458
 262:  8e bd         out  0x2e, r24  ; 46
459
    while((SPSR & (1<<SPIF))==0);
460
 264:  0d b4         in  r0, 0x2d  ; 45
461
 266:  07 fe         sbrs  r0, 7
462
 268:  fd cf         rjmp  .-6        ; 0x264 <_Z14spi_fast_shifth+0x2>
463
    return SPDR;
464
 26a:  8e b5         in  r24, 0x2e  ; 46
465
 26c:  08 95         ret
466
467
0000026e <_ZN7Max74564initEv>:
468
469
//-----------------------------------------------------------------------------
470
// Implements Max7456::init
471
//-----------------------------------------------------------------------------
472
void Max7456::init( void )
473
{
474
 26e:  ef 92         push  r14
475
 270:  ff 92         push  r15
476
 272:  0f 93         push  r16
477
 274:  1f 93         push  r17
478
 276:  cf 93         push  r28
479
 278:  df 93         push  r29
480
 27a:  ec 01         movw  r28, r24
481
    _isActivatedOsd = false;
482
 27c:  19 82         std  Y+1, r1  ; 0x01
483
    
484
    _regVm1.whole = 0b01000111;
485
 27e:  87 e4         ldi  r24, 0x47  ; 71
486
 280:  8b 83         std  Y+3, r24  ; 0x03
487
    spi_init();
488
 282:  0e 94 04 01   call  0x208  ; 0x208 <_Z8spi_initv>
489
  __builtin_avr_delay_cycles(__ticks_dc);
490
 286:  8f e3         ldi  r24, 0x3F  ; 63
491
 288:  9c e9         ldi  r25, 0x9C  ; 156
492
 28a:  01 97         sbiw  r24, 0x01  ; 1
493
 28c:  f1 f7         brne  .-4        ; 0x28a <_ZN7Max74564initEv+0x1c>
494
 28e:  00 c0         rjmp  .+0        ; 0x290 <_ZN7Max74564initEv+0x22>
495
 290:  00 00         nop
496
    _delay_ms(20);
497
498
    spi_selectSlave(true);
499
 292:  81 e0         ldi  r24, 0x01  ; 1
500
 294:  0e 94 0d 01   call  0x21a  ; 0x21a <_Z15spi_selectSlaveb>
501
    spi_fast_shift(VM0_ADDRESS_WRITE);
502
 298:  80 e0         ldi  r24, 0x00  ; 0
503
 29a:  0e 94 31 01   call  0x262  ; 0x262 <_Z14spi_fast_shifth>
504
    
505
    _regVm0.whole = 0x00;
506
    _regVm0.bits.videoSelect=1; //PAL
507
    _regVm0.bits.softwareResetBit = 1;
508
 29e:  82 e4         ldi  r24, 0x42  ; 66
509
 2a0:  8a 83         std  Y+2, r24  ; 0x02
510
    spi_fast_shift(_regVm0.whole);
511
 2a2:  0e 94 31 01   call  0x262  ; 0x262 <_Z14spi_fast_shifth>
512
    spi_selectSlave(false);
513
 2a6:  80 e0         ldi  r24, 0x00  ; 0
514
 2a8:  0e 94 0d 01   call  0x21a  ; 0x21a <_Z15spi_selectSlaveb>
515
 2ac:  ef e3         ldi  r30, 0x3F  ; 63
516
 2ae:  fc e9         ldi  r31, 0x9C  ; 156
517
 2b0:  31 97         sbiw  r30, 0x01  ; 1
518
 2b2:  f1 f7         brne  .-4        ; 0x2b0 <_ZN7Max74564initEv+0x42>
519
 2b4:  00 c0         rjmp  .+0        ; 0x2b6 <_ZN7Max74564initEv+0x48>
520
 2b6:  00 00         nop
521
    _delay_ms(20);
522
    
523
    spi_selectSlave(true);
524
 2b8:  81 e0         ldi  r24, 0x01  ; 1
525
 2ba:  0e 94 0d 01   call  0x21a  ; 0x21a <_Z15spi_selectSlaveb>
526
    for(int x = 0 ; x < 16 ; x++)
527
 2be:  00 e0         ldi  r16, 0x00  ; 0
528
 2c0:  10 e0         ldi  r17, 0x00  ; 0
529
 2c2:  7e 01         movw  r14, r28
530
 2c4:  e0 0e         add  r14, r16
531
 2c6:  f1 1e         adc  r15, r17
532
    {
533
        _regRb[x].whole = 0x00;
534
        _regRb[x].bits.characterWhiteLevel = 2;
535
 2c8:  82 e0         ldi  r24, 0x02  ; 2
536
 2ca:  f7 01         movw  r30, r14
537
 2cc:  87 87         std  Z+15, r24  ; 0x0f
538
        spi_fast_shift(x+RB0_ADDRESS_WRITE);
539
 2ce:  80 e1         ldi  r24, 0x10  ; 16
540
 2d0:  80 0f         add  r24, r16
541
 2d2:  0e 94 31 01   call  0x262  ; 0x262 <_Z14spi_fast_shifth>
542
        spi_fast_shift(_regRb[x].whole);
543
 2d6:  f7 01         movw  r30, r14
544
 2d8:  87 85         ldd  r24, Z+15  ; 0x0f
545
 2da:  0e 94 31 01   call  0x262  ; 0x262 <_Z14spi_fast_shifth>
546
    for(int x = 0 ; x < 16 ; x++)
547
 2de:  0f 5f         subi  r16, 0xFF  ; 255
548
 2e0:  1f 4f         sbci  r17, 0xFF  ; 255
549
 2e2:  00 31         cpi  r16, 0x10  ; 16
550
 2e4:  11 05         cpc  r17, r1
551
 2e6:  69 f7         brne  .-38       ; 0x2c2 <_ZN7Max74564initEv+0x54>
552
    }
553
    
554
    _regVm0.whole = 0x00;
555
    
556
    _regVm0.bits.verticalSynch = 1;
557
 2e8:  84 e0         ldi  r24, 0x04  ; 4
558
 2ea:  8a 83         std  Y+2, r24  ; 0x02
559
    
560
    spi_fast_shift(VM0_ADDRESS_WRITE);
561
 2ec:  80 e0         ldi  r24, 0x00  ; 0
562
 2ee:  0e 94 31 01   call  0x262  ; 0x262 <_Z14spi_fast_shifth>
563
    
564
    spi_fast_shift(_regVm0.whole);
565
 2f2:  8a 81         ldd  r24, Y+2  ; 0x02
566
 2f4:  0e 94 31 01   call  0x262  ; 0x262 <_Z14spi_fast_shifth>
567
    //
568
    //  digitalWrite(_pinCS,LOW);
569
    //SPI.transfer(VM1_ADDRESS_WRITE);
570
    //SPI.transfer(0x0C);
571
    
572
    spi_selectSlave(false);
573
 2f8:  80 e0         ldi  r24, 0x00  ; 0
574
}
575
 2fa:  df 91         pop  r29
576
 2fc:  cf 91         pop  r28
577
 2fe:  1f 91         pop  r17
578
 300:  0f 91         pop  r16
579
 302:  ff 90         pop  r15
580
 304:  ef 90         pop  r14
581
    spi_selectSlave(false);
582
 306:  0c 94 0d 01   jmp  0x21a  ; 0x21a <_Z15spi_selectSlaveb>
583
584
0000030a <_ZN7Max745611activateOSDEb>:
585
 30a:  0f 93         push  r16
586
 30c:  1f 93         push  r17
587
 30e:  cf 93         push  r28
588
 310:  df 93         push  r29
589
 312:  1f 92         push  r1
590
 314:  cd b7         in  r28, 0x3d  ; 61
591
 316:  de b7         in  r29, 0x3e  ; 62
592
 318:  8c 01         movw  r16, r24
593
 31a:  fc 01         movw  r30, r24
594
 31c:  81 81         ldd  r24, Z+1  ; 0x01
595
 31e:  86 17         cp  r24, r22
596
 320:  d9 f0         breq  .+54       ; 0x358 <_ZN7Max745611activateOSDEb+0x4e>
597
 322:  82 81         ldd  r24, Z+2  ; 0x02
598
 324:  80 64         ori  r24, 0x40  ; 64
599
 326:  82 83         std  Z+2, r24  ; 0x02
600
 328:  66 23         and  r22, r22
601
 32a:  11 f0         breq  .+4        ; 0x330 <_ZN7Max745611activateOSDEb+0x26>
602
 32c:  88 60         ori  r24, 0x08  ; 8
603
 32e:  02 c0         rjmp  .+4        ; 0x334 <_ZN7Max745611activateOSDEb+0x2a>
604
 330:  87 7f         andi  r24, 0xF7  ; 247
605
 332:  f8 01         movw  r30, r16
606
 334:  82 83         std  Z+2, r24  ; 0x02
607
 336:  81 e0         ldi  r24, 0x01  ; 1
608
 338:  69 83         std  Y+1, r22  ; 0x01
609
 33a:  0e 94 0d 01   call  0x21a  ; 0x21a <_Z15spi_selectSlaveb>
610
 33e:  80 e0         ldi  r24, 0x00  ; 0
611
 340:  0e 94 31 01   call  0x262  ; 0x262 <_Z14spi_fast_shifth>
612
 344:  f8 01         movw  r30, r16
613
 346:  82 81         ldd  r24, Z+2  ; 0x02
614
 348:  0e 94 31 01   call  0x262  ; 0x262 <_Z14spi_fast_shifth>
615
 34c:  80 e0         ldi  r24, 0x00  ; 0
616
 34e:  0e 94 0d 01   call  0x21a  ; 0x21a <_Z15spi_selectSlaveb>
617
 352:  69 81         ldd  r22, Y+1  ; 0x01
618
 354:  f8 01         movw  r30, r16
619
 356:  61 83         std  Z+1, r22  ; 0x01
620
 358:  0f 90         pop  r0
621
 35a:  df 91         pop  r29
622
 35c:  cf 91         pop  r28
623
 35e:  1f 91         pop  r17
624
 360:  0f 91         pop  r16
625
 362:  08 95         ret
626
627
00000364 <main>:
628
#include "RX5808.h"
629
630
// declar
631
632
633
int main(void) {
634
 364:  cf 93         push  r28
635
 366:  df 93         push  r29
636
 368:  1f 92         push  r1
637
 36a:  cd b7         in  r28, 0x3d  ; 61
638
 36c:  de b7         in  r29, 0x3e  ; 62
639
    RX5808 rx;
640
 36e:  ce 01         movw  r24, r28
641
 370:  01 96         adiw  r24, 0x01  ; 1
642
 372:  0e 94 40 00   call  0x80  ; 0x80 <_ZN6RX5808C1Ev>
643
    rx.setFrequency(0);
644
 376:  60 e0         ldi  r22, 0x00  ; 0
645
 378:  70 e0         ldi  r23, 0x00  ; 0
646
 37a:  ce 01         movw  r24, r28
647
 37c:  01 96         adiw  r24, 0x01  ; 1
648
 37e:  0e 94 a4 00   call  0x148  ; 0x148 <_ZN6RX580812setFrequencyEj>
649
 382:  ff cf         rjmp  .-2        ; 0x382 <main+0x1e>
650
651
00000384 <_exit>:
652
 384:  f8 94         cli
653
654
00000386 <__stop_program>:
655
 386:  ff cf         rjmp  .-2        ; 0x386 <__stop_program>

Was hats eigentlich mit den UNDEFINED SYMBOLS in der .lst auf sich ->
_ZN6RX5808C1Ev
_ZN6RX580812setFrequencyEj

von Stefan (Gast)


Lesenswert?

Peter II schrieb:
> Stefan schrieb:
>> Aber es wäre besser als Makro ?
>> PORTD &= ~(1<<pinNr) ;
>
> der Compiler muss erkennen das PinNr eine Konstante ist, dann wird
> daraus ein SetBit oder ClearBit. Wenn er das nicht erkennt dann wird das
> sehr umständlicher code.

Okay ich kann dir folgen, aber der Compiler sollte ja auch erkennen dass 
es eine konstante ist da sie über #define deklariert wird oder nicht ?

von Peter II (Gast)


Lesenswert?

Stefan schrieb:
> code nach der Optimierung ?

nein, das ist überhaupt nichts optimiert.

Da ist der oben angesprochen umständliche code mit schleife. Bei einer 
guten Optimierung, dürfte das nur 1 Zeile sein.
1
  86:  44 23         and  r20, r20
2
  88:  49 f0         breq  .+18       ; 0x9c <_ZN6RX58086setPINEhh+0x16>
3
        PORTD = 1<<pinNr ;
4
  8a:  81 e0         ldi  r24, 0x01  ; 1
5
  8c:  90 e0         ldi  r25, 0x00  ; 0
6
  8e:  06 2e         mov  r0, r22
7
  90:  01 c0         rjmp  .+2        ; 0x94 <_ZN6RX58086setPINEhh+0xe>
8
  92:  88 0f         add  r24, r24
9
  94:  0a 94         dec  r0
10
  96:  ea f7         brpl  .-6        ; 0x92 <_ZN6RX58086setPINEhh+0xc>
11
  98:  8b b9         out  0x0b, r24  ; 11
12
  9a:  08 95         ret
13
    }else{
14
        PORTD = 0<<pinNr ;
15
  9c:  1b b8         out  0x0b, r1  ; 11
16
  9e:  08 95         ret
17
18
000000a0 <_ZN6RX58085spi_1Ev>:
19
  a0:  1b b8         out  0x0b, r1  ; 11
20
  #else
21
    //round up by default
22
    __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
23
  #endif

von Carl D. (jcw2)


Lesenswert?

Stefan schrieb:
> Carl D. schrieb:
>> Stefan schrieb:
>> Beim C-Lernen auf einem AVR macht es Sinn sich die .lss-Datei
>> anzuschauen. Da ist man doch (anfangs) überrascht, was der Compiler so
>> produziert. Wenige können es (über alles betrachtet) besser und keiner
>> von denen auch nur annähernd so schnell. Und viele Gerüchte erkennt man
>> als solche.
>
> Gut ich hab mir die .lss jetzt mal angesehen und ehrlich gesagt auch das
> erste mal für mich sieht das jetzt aus wie der tatsächliche Assembler
> code nach der Optimierung ?
>

Das sieht eher so aus, als würde der Optimizer noch darauf warten 
eingeschaltet zu werden.
Allein daß der Konstruktor für rx, der aus 2 Befehlen besteht, nicht 
inlined wird, zeigt das.
Wie wurde der AVR-GCC gerufen und welche Version ist es. Option -v macht 
ihn gesprächig.

von Carl D. (jcw2)


Angehängte Dateien:

Lesenswert?

So, jetzt hab ich dem GCC mal die Chance gegeben, sich zu 
rehabilitieren.
AVR-GCC 6.2 mit Optimierung -Os, was Size bedeutet'und weshalb die 
diversen Pinwackler nicht inlined werden.
Gebraucht hat er dafür 410ms. Nur so als zeitlich Vorgabe für "Freund" 
Moby, falls der das besser machen will. Ich kann notfalls auch auf das 
Milli verzichten ;-)

von tictactoe (Gast)


Lesenswert?

Stefan schrieb:
> PORTD != (1<<pinNr) ;

Sollte doch wohl eher
1
PORTD |= (1<<pinNr) ;
sein.

Peter II schrieb:
> der Compiler muss erkennen das PinNr eine Konstante ist, dann wird
> daraus ein SetBit oder ClearBit. Wenn er das nicht erkennt dann wird das
> sehr umständlicher code.

Um das zu garantieren, würde ich die Funktion als Template schreiben:
1
template<uint8_t pinNr>
2
void setPIN(uint8_t state) {
3
    if (state) {
4
        PORTD |= 1<<pinNr;
5
    }else{
6
        PORTD &= ~(1<<pinNr);
7
    }
8
}
Benutzt wird die Funktion dann so:
1
setPIN<SPI_CLOCK_PIN>(LOW);
Der Vorteil ist, dass man dann nur mehr Aufrufe hinschreiben kann, die 
der Compiler auch wirklich optimieren kann.

Ich persönlich würde auch noch auf den state Parameter verzichten und 
zwei Funktionen machen: setPIN und clearPIN.

von René H. (Gast)


Lesenswert?

tictactoe schrieb:
> Um das zu garantieren, würde ich die Funktion als Template schreiben:

Saubere Lösung!

von Markus F. (mfro)


Lesenswert?

Stefan schrieb:
> Der Code ist noch nicht getestet, stimmt natürlich das war Blödsinn
>
> void RX5808::setPIN( uint8_t pinNr, uint8_t state){
>     if (state) {
>         PORTD != (1<<pinNr) ;
>     }else{
>         PORTD &= ~(1<<pinNr) ;
>     }
> }

Das auch. Was willst Du mit dem Ausrufezeichen da?

von Stefan (Gast)


Lesenswert?

Markus F. schrieb:
> Stefan schrieb:
>> Der Code ist noch nicht getestet, stimmt natürlich das war Blödsinn
>>
>> void RX5808::setPIN( uint8_t pinNr, uint8_t state){
>>     if (state) {
>>         PORTD != (1<<pinNr) ;
>>     }else{
>>         PORTD &= ~(1<<pinNr) ;
>>     }
>> }
>
> Das auch. Was willst Du mit dem Ausrufezeichen da?

Nichts besonderes, es sollte nur einleuten einfach mal schlafen zu 
gehen.
Ich bin gerade in der Arbeit, und hab das Makefile nicht mit. Ich denke 
es ist ein "s" eingetragen.

von Mich (Gast)


Lesenswert?

Carl D. schrieb:
> Stefan schrieb:
>> Carl D. schrieb:
>>> Stefan schrieb:
> Das sieht eher so aus, als würde der Optimizer noch darauf warten
> eingeschaltet zu werden.
> Allein daß der Konstruktor für rx, der aus 2 Befehlen besteht, nicht
> inlined wird, zeigt das.
> Wie wurde der AVR-GCC gerufen und welche Version ist es. Option -v macht
> ihn gesprächig.

Hier gleich mal ein kleiner Auszug mit allen Infos

"
# Optimization level, can be [0, 1, 2, 3, s].
#     0 = turn off optimization. s = optimize for size.
#     (Note: 3 is not always the best optimization level. See avr-libc 
FAQ.)
OPT = s


# Debugging format.
#     Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
#     AVR Studio 4.10 requires dwarf-2.
#     AVR [Extended] COFF format requires stabs, plus an avr-objcopy 
run.
DEBUG = stabs


# List any extra directories to look for include files here.
#     Each directory must be seperated by a space.
#     Use forward slashes for directory separators.
#     For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS = src


# Compiler flag to set the C Standard level.
#     c89   = "ANSI" C
#     gnu89 = c89 plus GCC extensions
#     c99   = ISO C99 standard (not yet fully implemented)
#     gnu99 = c99 plus GCC extensions
CSTANDARD = -std=gnu++03


# Place -D or -U options here
CDEFS = -DF_CPU=$(F_CPU)UL


# Place -I options here
CINCS =



#---------------- Compiler Options ----------------
#  -g*:          generate debugging information
#  -O*:          optimization level
#  -f...:        tuning, see GCC manual and avr-libc documentation
#  -Wall...:     warning level
#  -Wa,...:      tell GCC to pass this to the assembler.
#    -adhlns...: create assembler listing
CFLAGS = -g$(DEBUG)
CFLAGS += $(CDEFS) $(CINCS)
CFLAGS += -O$(OPT)
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct 
-fshort-enums
CFLAGS += -Wall -Wstrict-prototypes
CFLAGS += -Wa,-adhlns=$(addprefix $(OBJDIR)/,$(<:.cpp=.lst))
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
CFLAGS += $(CSTANDARD)
CFLAGS += -gstabs
CFLAGS += -gstrict-dwarf
"
Avr-gcc ist in der version 4.8.3

von Carl D. (jcw2)


Lesenswert?

Da hat GCC aber erheblich dazugelernt, denn der 6.2 (aber auch 5.3) hat 
kein Probleme Konstanten über mehrere Call-Level hinweg als solche zu 
erkennen.
Das fehlt in dem 4.8er .lss völlig. Die Bitmaske für den (eigentlich 
unnötigen) Byte-Zugriff auf die Ports wird zur Laufzeit berechnet. Wenn 
ein AVR etwas nich mag, dann daß.
Beim 6.2er Binary sind ab 0x74/0xa4 die Routinen für Bit-Ausgabe an SPI 
zu finden. Überall SBI/CBI. Nur das delay_us(1) macht eine Schleife, 
alternativ wären da 16 NOPs, aber Wir optimieren ja "auf Größe" und als 
Schleife sind es nur 4 Befehle. Wenn man da noch drunter kommen will, 
dann braucht man eine eigene Funktion für "Delay 1μs", deren Aufruf 
braucht nur 2 Byte. Die muß man aber vor LTO retten.
Ich hatte verschieden Varianten des Programms ausprobiert, mit/ohne 
Templates, wie oben vorgeschlagen, und noch ein Paar Änderungen. Mit 
frustrierendem Ergebnis: immer das gleiche Binary. Man muß dem Compiler 
also nur sagen, was er machen soll, das Wie kann er selber.

von c-hater (Gast)


Lesenswert?

Bernd K. schrieb:

> Seitdem hab ich keine Skrupel mehr zum Beispiel sowas zu schreiben:
[...]

> Das alles schrumpft durch LTO zusammen auf zwei ASM-Instruktionen im IRQ

Siehste, und genau deswegen schreibe ich für kleine µC gleich in Asm. 
Warum sollte man auch das ganze, offensichtlich völlig redundante 
Syntaxgelalle von C oder gar C++ hinschreiben, wenn man die gleiche 
Funktionalität mit zwei simplen Zeilen Asm erreichen kann? Das ist doch 
extrem widersinnig! Der Plan bei Hochsprachen war doch eigentlich, 
Programmcode schneller und fehlerfreier schreiben zu können...

Dieses Ziel wurde ganz offensichlich megamäßig verfehlt...

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Carl D. schrieb:

ad LTO

> Nur sollte man einen einigermaßen aktuellen Compiler haben (meiner nennt
> sich gerade 6.2, also nicht "sehr alt") und Compiler und Linker müssen
> mit "-Os -flto" gefüttert werden. Beide! Und mit der gleichen
> Optimierungsstufe.

Ab GCC 5 gilt für LTO:
1
Command-line optimization and target options are now streamed on a
2
per-function basis and honored by the link-time optimizer. [...]
3
Contrary to earlier GCC releases, the optimization and target options passed on the link command line are ignored.
4
5
Note that this applies only to those command-line options that can be
6
passed to optimize and target attributes. Command-line options affecting
7
global code generation, warnings, optimizations affecting the way static
8
variables are optimized, debug output, and --param parameters can be
9
applied only to the whole link-time optimization unit.

http://gcc.gnu.org/gcc-5/changes.html

von Carl D. (jcw2)


Lesenswert?

Johann L. schrieb:
> Carl D. schrieb:
>
> ad LTO
>
>> Nur sollte man einen einigermaßen aktuellen Compiler haben (meiner nennt
>> sich gerade 6.2, also nicht "sehr alt") und Compiler und Linker müssen
>> mit "-Os -flto" gefüttert werden. Beide! Und mit der gleichen
>> Optimierungsstufe.
>
> Ab GCC 5 gilt für LTO:
>
>
1
> Command-line optimization and target options are now streamed on a
2
> per-function basis and honored by the link-time optimizer. [...]
3
> Contrary to earlier GCC releases, the optimization and target options 
4
> passed on the link command line are ignored.
5
> 
6
> Note that this applies only to those command-line options that can be
7
> passed to optimize and target attributes. Command-line options affecting
8
> global code generation, warnings, optimizations affecting the way static
9
> variables are optimized, debug output, and --param parameters can be
10
> applied only to the whole link-time optimization unit.
>
> http://gcc.gnu.org/gcc-5/changes.html

Danke Johann für diesen Hinweis. Das muß ich mir dann irgendwie zu 
4.9-Zeiten gemerkt haben.

Und wenn ich dich schon da hab, vielen Dank für die phantastische Arbeit 
am GCC AVR-Backend.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

c-hater schrieb:
> Warum sollte man auch das ganze, offensichtlich völlig redundante
> Syntaxgelalle von C oder gar C++ hinschreiben, wenn man die gleiche
> Funktionalität mit zwei simplen Zeilen Asm erreichen kann?

Machst Du jetzt den Moby?

von Bernd K. (prof7bit)


Lesenswert?

c-hater schrieb:
> Der Plan bei Hochsprachen war doch eigentlich,
> Programmcode schneller und fehlerfreier schreiben zu können...

Und genau das wird hier erreicht. Ich kann so viele 
Abstraktionsschichten einziehen wie ich der Modularität, Entkopplung, 
Wiederverwendbarkeit und Übersicht zuliebe für sinnvoll erachte und der 
Compiler macht trotzdem weitaus effizienteren Code draus als Du oder 
Moby oder ich oder sonstwer es jemals in akzeptabler Zeit zu Fuß 
erreichen könnten und ohne daß sich dann irgendeine arme Seele immer und 
immer wieder durch zigtausend Zeilen undurchdringliches 
ASM-Spaghetti-Gestrüpp durchschlagen müsste für jede popelige Änderung 
oder Erweiterung oder gar Wiederverwendung.

von M.Peter (Gast)


Lesenswert?

Bernd K. schrieb:
> Und genau das wird hier erreicht. Ich kann so viele
> Abstraktionsschichten einziehen wie ich der Modularität, Entkopplung,
> Wiederverwendbarkeit und Übersicht zuliebe für sinnvoll erachte und der
> Compiler macht trotzdem weitaus effizienteren Code draus als Du oder
> Moby oder ich oder sonstwer es jemals in akzeptabler Zeit zu Fuß
> erreichen könnten und ohne daß sich dann irgendeine arme Seele immer und
> immer wieder durch zigtausend Zeilen undurchdringliches
> ASM-Spaghetti-Gestrüpp durchschlagen müsste für jede popelige Änderung
> oder Erweiterung oder gar Wiederverwendung.

Offensichtlich kannst Du mit C++ gut umgehen und für Dich und Deine 
Anwendungen einen Vorteil daraus ziehen. Das sei Dir von Herzen gegönnt. 
Deine Darstellung krankt aber ganz erheblich an ihrer absolutgültigen 
Aussage, weil sie Art der Anwendung, Fähigkeiten des Programmierers und 
die konkreten Anforderungen aus dem Betriebsalltag völlig außen vor 
lässt.

von Oliver S. (oliverso)


Lesenswert?

Bernd K. schrieb:
> Modularität, Entkopplung,
> Wiederverwendbarkeit und Übersicht

M.Peter schrieb:
> krankt aber ganz erheblich an ihrer absolutgültigen
> Aussage, weil sie Art der Anwendung, Fähigkeiten des Programmierers und
> die konkreten Anforderungen aus dem Betriebsalltag völlig außen vor
> lässt.

Ganz ehrlich, wer sein Geld mit professioneller Softwareerstellung 
verdient, der sollte das auch können. Und da kann es gar nicht so viel 
"Betriebsalltag" geben, als daß die grundlegendsten Anforderungen außer 
acht gelassen werden sollten.

Viele Wege führen nach Rom, und C++ ist nur einer davon.

Unkoordiniertes draufloshacken ist allerdings grundsätzlich für keine 
Anwendung eine Option.

Oliver

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Was ich bislang vermisse ist ein praktikabler Ersatz für __flash, 
zumindest für avr-g++.  Für C gibt's __flash zwar nur als C-Erweiterung, 
allerdings scheint es ganz gut akzeptiert zu werden.

Zwar werden immer wieder Buzzwords wie "Smart Pointer" genannt, aber 
eine allgemein akzeptierte und verbreitete Lösung scheint es nicht zu 
geben.

Ein Problem bei C++ ist auch, das im Gegensatz zu C ein const Objekt zur 
Laufzeit geändert werden kann, etwa wenn die Konstruktion eines 
statischen Konstruktors bedarf.

Falls jemand eine zufriedenstellende Implementierung in C++ hat, kann 
man davon bestimmt einiges lernen :-)

von Carl D. (jcw2)


Lesenswert?

Johann L. schrieb:
> Was ich bislang vermisse ist ein praktikabler Ersatz für __flash,
> zumindest für avr-g++.  Für C gibt's __flash zwar nur als C-Erweiterung,
> allerdings scheint es ganz gut akzeptiert zu werden.
>
> Falls jemand eine zufriedenstellende Implementierung in C++ hat, kann
> man davon bestimmt einiges lernen :-)

Für einen nicht unwichtigen Teil des Flash-Problems, String-Konstanten, 
gibt es diesen Lösungsweg:

Beitrag "Interessante g++ Erweiterung für user-defined literals"

oder kurz: mit ca 20 Zeilen Code (und aktuell nur an ostream angebunden 
:-( ) ist folgendes möglich:
1
  os << "ein Text in Flash"_pgm;
wobei mehrfaches Auftreten des selben Strings zu nur einer Instanz im 
Flash führt.



PS: das ganze geht auch universeller. Gibt mir einen Tag, dann hab 
ich's.

: Bearbeitet durch Moderator
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.