Forum: Compiler & IDEs avr-gcc 11.1.0 defekt?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Veit D. (devil-elec)


Angehängte Dateien:

Lesenswert?

Hallo,

aus irgendwelchen Gründen macht der avr-gcc 11.1.0 Mist. Ich habe 
festgestellt das SPI mit Arduino IDE und Arduino Nano Every (ATmega4809) 
nicht mit dem avr-gcc 11.1.0 funktioniert. Der Code wird nachweislich 
ausgeführt und dennoch läuft dabei etwas schief. Ich habe die Methoden 
mittels Pin Toggle "überwacht". Am Ende werden die CTRLA und CTRLB 
Register der SPI Einheit nicht gesetzt. Obwohl wie gesagt der Code 
nachweislich an den Stellen durchläuft.

Ein weiterer Beweis dafür ist folgender. Wenn ich die lokalen Member 
ctrla und ctrlb in SPI.h Zeile 146 mit irgendeinem Wert initialisiere, 
dann bleiben die Werte bestehen. Sie werden nicht geändert obwohl sie 
von init_AlwaysInline() geändert werden müßten.

init_MightInline und init_AlwaysInline werden nachweislich durch Pin 
Toggle ausgeführt.

Es funktionieren folgende Kombinationen:
Arduino IDE 1.8.15 + avr-gcc 10.3.0
Arduino IDE 1.8.15 + avr-gcc 11.1.0 + Arduino Mega2560 (ATmega2560)
Arduino IDE 1.8.15 + avr-gcc 11.1.0 + MCUdude MegaCoreX Package 
(ATmega4809)
Arduino IDE 1.8.15 + avr-gcc 11.1.0 + SpenceKonde DxCore Package 
(AVR128DB48)

Es funktioniert nicht:
Arduino IDE 1.8.15 + avr-gcc 11.1.0 + Arduino megaavr0 Package 
(ATmega4809)

Ich erhalte keinerlei Warnungen oder Fehlermeldungen. Ich habe es auch 
mit der Toolchain von Zakkemble gegen getestet. Gleiches Ergebnis.

Es gibt eine kleine Abhilfe. Wenn ich den Methodenaufruf 
config(DEFAULT_SPI_SETTINGS) in der SPI.cpp Zeile 53 weglasse, dann 
funktioniert SPI wieder. Aber das kann nicht die Endlösung sein. Das 
deutet nur auf ein Problem hin. Nur welches?

Ich habe das Problem zuerst im Arduino Forum besprochen.
https://forum.arduino.cc/t/houston-spi-has-a-problem-with-avr-gcc-11-1-0/876291
Wir sind beide der Meinung das beim kompilieren etwas schief läuft. Wir 
wissen nur noch nicht ob es am Quellcode liegt oder an der Compilierung. 
Nur wenn es am Quellcode liegen würde sollte doch schon ein älterer gcc 
meckern zudem der 11.1.0 keine Warnung/Fehler ausgibt. Was wir sehen 
sind Unterschiede in den Adressen wenn man die Assembler Dumpfiles 
vergleicht. Ist das ein Fehler im gcc oder in den Files des ATmega4809 
oder ... ?

Kann jemand einen Fehler entdecken?
Kann es jemand nachvollziehen?

Alle Dateien zusammengefasst hängen oben dran.

von Wilhelm M. (wimalopaan)


Lesenswert?

Die SPI-Instanzen beim avr0 und dahaben unterschiedliche Basisadressen. 
Bist Du sicher, dass Du die richtigen verwendest?

von Wilhelm M. (wimalopaan)


Lesenswert?

gcc-11.1 kann ich nicht nachvollziehen, aber ich hatte bisher nie 
Probleme damit und gcc-12.0 geht definitiv.

von Wilhelm M. (wimalopaan)


Lesenswert?

Dein Klasse ist allerdings etwas merkwürdig: was sofort auffällt:

- warum Pin-Nummern angeben? Die liegen fest, auch bei Portmux sind sie 
nicht frei wählbar.
- Du verwendest immer SPI0, es gibt aber beim DA zwei Instanzen. DAs 
wird dann schon mal falsch.
- ...

von Wilhelm M. (wimalopaan)


Lesenswert?

Veit D. schrieb:
> Arduino IDE 1.8.15 + avr-gcc 11.1.0 + MCUdude MegaCoreX Package
> (ATmega4809)

> Es funktioniert nicht:
> Arduino IDE 1.8.15 + avr-gcc 11.1.0 + Arduino megaavr0 Package
> (ATmega4809)

Wie kommst Du dazu, dass es der Compiler sein sollte. Was sich hier 
unterscheidet sind diese Packages.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

die SPI.h/cpp stammt nicht von mir. Das ist orignal Arduino Code.

> Wie kommst Du dazu, dass es der Compiler sein sollte. Was sich hier
> unterscheidet sind diese Packages.

Egal was ich verwende, sobald ich für den ATmega4809 (Nano Every) den 
avr-gcc 11.1.0 verwende funktioniert SPI nicht. Gleicher kurzer 
Testcode, gleiche Lib, nur anderer avr-gcc -> andere Adressen. Worauf 
lässt das schließen?

von Wilhelm M. (wimalopaan)


Lesenswert?

Veit D. schrieb:
> Egal was ich verwende, sobald ich für den ATmega4809 (Nano Every) den
> avr-gcc 11.1.0 verwende funktioniert SPI nicht. Gleicher kurzer
> Testcode, gleiche Lib, nur anderer avr-gcc -> andere Adressen. Worauf
> lässt das schließen?

Schau nochmal was Du oben geschrieben hast: da ist es derselbe Compiler. 
Aber vielleicht ist Deine Auflistung auch falsch.

von Wilhelm M. (wimalopaan)


Lesenswert?

Veit D. schrieb:
> die SPI.h/cpp stammt nicht von mir. Das ist orignal Arduino Code.

oh je ...

von Veit D. (devil-elec)


Lesenswert?

> warum Pin-Nummern angeben?
Weil die Lib auch Software SPI zulässt.

> Schau nochmal was Du oben geschrieben hast: da ist es derselbe Compiler.
> Aber vielleicht ist Deine Auflistung auch falsch.
Lies nochmal bitte genau was ich aufgelistet und geschrieben habe.

von mh (Gast)


Lesenswert?

Veit D. schrieb:
>> Schau nochmal was Du oben geschrieben hast: da ist es derselbe Compiler.
>> Aber vielleicht ist Deine Auflistung auch falsch.
> Lies nochmal bitte genau was ich aufgelistet und geschrieben habe.

Vielleicht solltest du selbst nochmal nachschauen was du geschrieben 
hast. Du hast 3 Kombinationen mit dem gcc 11.1.0 die funktionieren und 
eine die nicht funktioniert. Warum glaubst du, dass es am Compiler liegt 
und nicht an dem zusammengewürfelten Rest? Und kannst du nicht 
nachgucken, was der Compiler für Code generiert?

von Wilhelm M. (wimalopaan)


Lesenswert?

Veit D. schrieb:
> Es funktionieren folgende Kombinationen:
> Arduino IDE 1.8.15 + avr-gcc 11.1.0 + MCUdude MegaCoreX Package
> (ATmega4809)
> Es funktioniert nicht:
> Arduino IDE 1.8.15 + avr-gcc 11.1.0 + Arduino megaavr0 Package
> (ATmega4809)

Und nocheinmal ... worin unterscheiden die sich: richtig, nicht im 
Compiler.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

Leute, der generierte Code hängt doch oben dran. Beide Dumpfiles mit
Arduino IDE 1.8.15 + Arduino megaavr0 Package (ATmega4809). Irgendwelche 
Adressen unterscheiden sich. Ich bin aber kein Compilerguru.

Gegenfrage. Warum funktioniert
Arduino IDE 1.8.15 + avr-gcc 10.3.0 + Arduino megaavr0 Package 
(ATmega4809)
und warum funktioniert nicht
Arduino IDE 1.8.15 + avr-gcc 11.1.0 + Arduino megaavr0 Package 
(ATmega4809)

Worauf lässt das als Erstes schließen? Der erzeugte Code unterscheidet 
sich jedenfalls.

von mh (Gast)


Lesenswert?

Veit D. schrieb:
> Leute, der generierte Code hängt doch oben dran.

Du hast nen zip hochgeladen. Um zu wissen was drin ist, müsste man die 
Datei runterladen und öffnen. Ich traue dir nicht genug und bin zu faul 
ne sichere Umgebung zu starten ...
Ich gehe auch davon aus, dass es sich nicht um ein minimales, 
compilierbares und lauffähiges Beispiel handelt, das den Fehler 
reproduziert.

Veit D. schrieb:
> Irgendwelche
> Adressen unterscheiden sich. Ich bin aber kein Compilerguru.
Man muss man kein "Compilerguru" sein, um nachvollziehen zu können, was 
der Compiler generiert. Der AVR ist nun wirklich nicht kompliziert.

Veit D. schrieb:
> Gegenfrage. Warum funktioniert
> Arduino IDE 1.8.15 + avr-gcc 10.3.0 + Arduino megaavr0 Package
> (ATmega4809)
> und warum funktioniert nicht
> Arduino IDE 1.8.15 + avr-gcc 11.1.0 + Arduino megaavr0 Package
> (ATmega4809)
Weil megaavr0 nen Bug hat? Weil du etwas falsch bedienst, das du nicht 
verstanden hast? Weil es eigentlich funktioniert und du interpretierst 
etwas falsch?

von Veit D. (devil-elec)


Lesenswert?

Ganz schön starker Tobak. Ich verstehe dich so, du möchtest nur nörgeln 
und wolltest niemals helfen.

von Wilhelm M. (wimalopaan)


Lesenswert?

Hast Du denn jetzt wenigstens schon meinen ersten Kommentar gelesen bzw. 
Geprüft?

von Veit D. (devil-elec)


Lesenswert?

Welchen von den vielen meinst du? Falls du die Adressen von CTRLA/CTRLB 
meinst, die habe ich schon lange geprüft. Die stimmen.

: Bearbeitet durch User
von Veit D. (devil-elec)


Lesenswert?

Hallo,

da niemand gewillt ist dem Link zu folgen nochmal.
Dieser Code in der SPI.h wird nachweislich ausgeführt.
1
  private:
2
  void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) {
3
    init_AlwaysInline(clock, bitOrder, dataMode);
4
  }
5
6
  void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) __attribute__((__always_inline__)) {
7
    // Clock settings are defined as follows. Note that this shows SPI2X
8
    // inverted, so the bits form increasing numbers. Also note that
9
    // fosc/64 appears twice.  If FOSC is 16 Mhz
10
    // PRESC[1:0]  ~SPI2X Freq
11
    //   0    0     0   fosc/2    8.00 MHz 
12
    //   0    0     1   fosc/4    4.00 MHz
13
    //   0    1     0   fosc/8    2.00 MHz
14
    //   0    1     1   fosc/16   1.00 MHz
15
    //   1    0     0   fosc/32   500  kHz
16
    //   1    0     1   fosc/64   250  kHz
17
    //   1    1     0   fosc/64   250  kHz
18
    //   1    1     1   fosc/128  125  kHz
19
20
    // We find the fastest clock that is less than or equal to the
21
    // given clock rate. The clock divider that results in clock_setting
22
    // is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the
23
    // slowest (128 == 2 ^^ 7, so clock_div = 6).
24
    uint8_t clockDiv;
25
    
26
    // When the clock is known at compiletime, use this if-then-else
27
    // cascade, which the compiler knows how to completely optimize
28
    // away. When clock is not known, use a loop instead, which generates
29
    // shorter code.
30
    
31
    /*  This is no longer the case since, F_CPU_CORRECTED is variable */
32
    /*  set at run time.                                             */
33
34
    uint32_t clockSetting = 0; 
35
    
36
    clockSetting = F_CPU_CORRECTED / 2;
37
    clockDiv = 0;
38
    while ((clockDiv < 6) && (clock < clockSetting)) {
39
      clockSetting /= 2;
40
      clockDiv++;
41
    }
42
        
43
    // Compensate for the duplicate fosc/64,
44
    // should be fosc/128 if clockdiv 6.
45
    if (clockDiv == 6)
46
    {
47
      clockDiv++;
48
    }
49
        
50
    // Invert the SPI2X bit
51
    clockDiv ^= 0x1;
52
        
53
    /* Pack into the SPISettings::ctrlb class */
54
    /* Set mode, disable master slave select, and disable buffering. */
55
    /* dataMode is register correct, when using SPI_MODE defines     */
56
    ctrlb = (dataMode)            |
57
            (SPI_SSD_bm)          |
58
            (0 << SPI_BUFWR_bp)   |
59
            (0 << SPI_BUFEN_bp);
60
                
61
    /* Get Clock related values.*/
62
    uint8_t clockDiv_mult = (clockDiv & 0x1);
63
    uint8_t clockDiv_pres = (clockDiv >> 1);
64
        
65
    /* Pack into the SPISettings::ctrlb class     */
66
    /* Set Prescaler, x2, SPI to Master, and Bit Order. */
67
    
68
    ctrla = (clockDiv_pres  << SPI_PRESC_gp)        |
69
            (clockDiv_mult << SPI_CLK2X_bp)         |
70
            (SPI_ENABLE_bm)                         |
71
            (SPI_MASTER_bm)                         |
72
            ((bitOrder == LSBFIRST) << SPI_DORD_bp);
73
    
74
  }
75
  /* member variables containing the desired SPI settings */
76
  uint8_t ctrla;
77
  uint8_t ctrlb;
78
  friend class SPIClassMegaAVR;
79
};

Demzufolge müßte den Membern ctrla und ctrlb ein Wert zugewiesen werden. 
Das funktioniert jedoch aus unbekannten Gründen nicht. Denn der Wert 
dieser Member sollte in der Methode config() in SPI.cpp den Registern 
SPI0.CTRLA und SPI0.CTRLB zugewiesen werden. Dort kommt jedoch kein Wert 
an. In der begin Methode wird vorher noch SPI enable usw. gesetzt usw. 
Auch das kommt nicht an. Die Register bleiben leer. Kommentiere ich den 
config() Aufruf in der begin() Methode aus, dann funktioniert 
komischerweise alles. Wenn das ansonsten funktioniert nur mit dem 
avr-gcc 11.1.0 nicht, woran soll es dann liegen? Minimale Code 
Änderungen führen zum funktionieren. Das ist aber für mich nicht 
logisch. Es gibt ja auch nie ein Gemecker vom Compiler.

Übrigens Wilhlem, ich rede die ganze Zeit vom ATmega4809, der hat nur 
eine SPI Hardwareeinheit.

Bei dem letzten Test ...
1
#include<utilities.h>
2
#include <SPI.h>
3
4
void setup()
5
{  
6
  Serial.begin(250000);
7
  Serial.println(F("\nµC Reset #### #### ####"));
8
9
  showRegister(); 
10
  SPI.begin();
11
  showRegister(); 
12
  SPI.beginTransaction(DEFAULT_SPI_SETTINGS);
13
  showRegister();
14
  SPI.endTransaction();
15
  showRegister(); 
16
}
17
18
void loop()
19
{ }
20
21
void showRegister (void)
22
{
23
  uint16_t reg16 = 0;
24
  Serial.print(F("SPI0 CTRLA:    ")); formatBIN(Serial, SPI0.CTRLA, true);    reg16 = (uint16_t)&SPI0.CTRLA;    Serial.print(" ");  formatHEXln(Serial, reg16, true);
25
  Serial.print(F("SPI0 CTRLB:    ")); formatBIN(Serial, SPI0.CTRLB, true);    reg16 = (uint16_t)&SPI0.CTRLB;    Serial.print(" ");  formatHEXln(Serial, reg16, true);
26
  Serial.println();
27
}

... kommt nur Müll raus.
1
SPI0 CTRLA:    0b0000'0000 0x08C0
2
SPI0 CTRLB:    0b0000'0000 0x08C1
3
4
SPI0 CTRLA:    0b0000'0000 0x08C0
5
SPI0 CTRLB:    0b0000'0001 0x08C1
6
7
SPI0 CTRLA:    0b0001'0000 0x08C0
8
SPI0 CTRLB:    0b0000'0000 0x08C1
9
10
SPI0 CTRLA:    0b0001'0000 0x08C0
11
SPI0 CTRLB:    0b0000'0000 0x08C1

Erwartet wird das was mit älteren Toolchains rauskommt.
1
avr-gcc 11.1.0: SPI0 CTRLA: 0b0000'0000, CTRLB: 0b0000'0001
2
avr-gcc 10.3.0: SPI0 CTRLA: 0b0010'0001, CTRLB: 0b0000'0100
3
avr-gcc  7.3.0: SPI0 CTRLA: 0b0010'0001, CTRLB: 0b0000'0100

von mh (Gast)


Lesenswert?

Veit D. schrieb:
> Ganz schön starker Tobak. Ich verstehe dich so, du möchtest nur nörgeln
> und wolltest niemals helfen.

Du kannst mich verstehen wie du willst, das steht dir frei. Was genau 
ist starker Tobak?
- Störst du dich an meinem Unwillen, zip-Dateien mit unbekanntem Inhalt 
von unbekannten Personen zu öffnen?
- Ist in der zip-Datei ein minimales, compilierbares und lauffähiges 
Beispiel, das den Fehler reproduziert?
- Sind AVRs deiner Meinung nach so kompliziert, dass es im allgemeinen 
unmöglich ist zu verstehen wie sie funktionieren?
- Deine Gegenfrage mit weiteren Gegenfragen "beantworten", die den 
Fehler bei dir und nicht beim gcc vermuten?

von Wilhelm M. (wimalopaan)


Lesenswert?

Wo wird denn:

init_AlwaysInline(...)

aufgerufen? Das sieht man an Deinem Beispiel nicht.

Veit D. schrieb:
> Demzufolge müßte den Membern ctrla und ctrlb ein Wert zugewiesen werden.
> Das funktioniert jedoch aus unbekannten Gründen nicht.

Woher willst Du das wissen. Gibt die beiden doch mal aus.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

init_AlwaysInline(...) wird in init_MightInline(...) aufgerufen.
init_MightInline(...) wird im Konstruktor SPISettingsMegaAVR(...) 
aufgerufen.
Die beiden Methoden werden jeweils nur einmal aufgerufen. Das habe ich 
mittels Pin Toggle geprüft.
Die Member ctrla und ctrlb direkt auszugeben ist nicht so einfach. Habe 
ich wegen dem Datentyp noch nicht geschafft. Würde ich eine eigene 
Instanz erzeugen hätte ich nicht mehr die "originalen Werte". Da ich 
aber weiß wann sie den Registern zugewiesen werden, habe ich immer 
zwischendurch die Register ausgelesen die diese Werte enthalten müssen. 
Tun sie aber nicht. Siehe meiner vorherigen Antwort.

: Bearbeitet durch User
von Wilhelm M. (wimalopaan)


Lesenswert?

Veit D. schrieb:
> Die Member ctrla und ctrlb direkt auszugeben ist nicht so einfach. Habe
> ich wegen dem Datentyp noch nicht geschafft.

Oh ha, ein uint8_t ist auch echt schwierig auszugeben ;-)
Oder meinst Du, Du hast keinen Zugriff, weil sie private sind?

Veit D. schrieb:
> Da ich
> aber weiß wann sie den Registern zugewiesen werden, habe ich immer
> zwischendurch die Register ausgelesen die diese Werte enthalten müssen.
> Tun sie aber nicht. Siehe meiner vorherigen Antwort.

Woher willst Du das wissen. Wo passiert das?

von Mitleserin (a.b.) (Gast)


Lesenswert?

0 - Man sollte nicht einfach eine ino ins Forum stellen und schreiben 
"avr-gcc 11.1.0 defekt ?" Das ist viel zu pauschal.

Ein Versuch der Versachlichung:

A - in der AVR128DB-TCB32.ino steht
1
  AVR128DB48 Curiosity Nano Board
2
  https://github.com/SpenceKonde/DxCore
3
  TCBn 32Bit Counter ohne Kaskadierung, Pulsweitenmessung
4
  Takteingang Pin PA4
5
  30.10.2020
6
********************************************************************************/
7
8
  #include <avr/io.h>
9
  #include <avr/interrupt.h>
10
  #include <util/atomic.h>
11
  #include <AVR128DB_PinLib.h>
12
  #include <pins_arduino.h>
Das setzt unter ArduinoIDE voraus, dass der Boardmanager dieses Board 
mit AVR128DB kennt und das setzt voraus, dass unter Preferences der Link 
http://drazzy.com/package_drazzy.com_index.json eingetragen und 
anschliessend der Boardmanager aufgerufen wird. Bei meiner ArduinoIDE 
1.8.15 ist das jedenfalls so.

B - Die AVR-Toolchain 10.0.1 bzw. 11.0.1 müssen in der Lage sein den 
entsprechenden Code für AVR128DB zu generieren. Das setzt voraus, dass 
das entsprechenden Microchip.ATtiny_DFP.2.6.122.atpack vorhanden ist und 
die notwendigen ioavr32dbnn.h, crtavr32dbnn.o, libavr32dbnn.a, 
specs-avr32dbnn in die entsprechenden Verzeichnisse kopiert werden. Bei 
meinen AVR-Toolchains 10.0.1/11.0.1 ist das jedenfalls so.

Nur unter diesen Voraussetzungen können Foristen das Problem 
nachvollziehen und eventuell helfen heraus zu finden, was wo klemmt.

Unter diesen Voraussetzungen kompiliert das im 
/home/ab/.arduino15/packages/DxCore/hardware/megaavr/1.3.6/libraries/SPI 
/examples/DigitalPotControl  vorhandene SPI-Beispiel unter 
avr-gcc-10.1.0-x64-linux/

... bash -c "/home/ab/Installed/avr-gcc-10.1.0-x64-linux/bin/avr-nm 
--numeric-sort --line-numbers --demangle --print-size --format=s
/home/ab/.arduino15/debug/DigitalPotControl.ino.elf > 
/home/ab/.arduino15/debug/DigitalPotControl.ino.map"
Using library SPI at version 1.0.2 in folder: 
/home/ab/.arduino15/packages/DxCore/hardware/megaavr/1.3.6/libraries/SPI
/home/ab/Installed/avr-gcc-10.1.0-x64-linux/bin/avr-size -A 
/home/ab/.arduino15/debug/DigitalPotControl.ino.elf
Sketch uses 1500 bytes (1%) of program storage space. Maximum is 131072 
bytes.
Global variables use 117 bytes (0%) of dynamic memory, leaving 16267 
bytes for local variables. Maximum is 16384 bytes.


und unter avr-gcc-11.1.0-x64-linux/ kompiliert das Beispiel NICHT.

Die entscheidende Fehlermeldung unter avr-gcc-11.1.0-x64-linux/ lautet:

... /home/ab/Installed/avr-gcc-11.1.0-x64-linux/bin/avr-gcc-ar rcs
/home/ab/.arduino15/debug/core/core.a
/home/ab/.arduino15/debug/core/wiring_pulse.S.o
/home/ab/Installed/avr-gcc-11.1.0-x64-linux/bin/../lib/gcc/avr/11.1.0/.. 
/../../../avr/bin/ar:
error while loading shared libraries: libfl.so.2: cannot open shared 
object file: No such file or directory
Using library SPI at version 1.0.2 in folder:
/home/ab/.arduino15/packages/DxCore/hardware/megaavr/1.3.6/libraries/SPI
exit status 127
/home/ab/Installed/arduino-1.8.15/arduino-builder returned 127
Error compiling for board AVR DB-series (no bootloader).
************************
Weshalb libfl.so.2 nicht vorhanden ist, habe ich noch nicht untersucht.
************************

Das Beispiel AVR128DB-TCB32.ino kompiliert unter meinen Randbedingungen 
nicht, weil die #include <AVR128DB_PinLib.h> nicht 
in/home/ab/.arduino15/packages/DxCore vorhanden ist.

von Mitleserin (a.b.) (Gast)


Lesenswert?

https://blog.zakkemble.net/avr-gcc-builds/

Known Issues
Using avr-ar will return an error about libdep.dll.a not being designed 
to run on Windows. To fix this error delete 
avr-gcc-11.1.0-x64-windows/lib/bfd-plugins/libdep.dll.a

Korrigendum zu oben:
... entsprechenden Atmel.AVR-Dx_DFP.1.8.95.atpack vorhanden ist ...

von Oliver S. (oliverso)


Lesenswert?

Mitleserin (a.b.) schrieb:
> Nur unter diesen Voraussetzungen können Foristen das Problem
> nachvollziehen und eventuell helfen heraus zu finden, was wo klemmt.

Das Problem ist halt, daß die Schnittmenge derjenigen, die was zur 
Problemlösung beitragen können und Arduino nutzen und das auch noch für 
diesen Prozessor genau eine Person enthält: den TO selber.

Daher sind die Anfragen zu diesen Themen selten von Erfolg gekrönt.

Oliver

: Bearbeitet durch User
von Veit D. (devil-elec)


Lesenswert?

Hallo,

das hast du nett zusammengefasst Oliver. Es kommt jedoch noch ein 
Problem hinzu was ich immer wieder feststelle. Das dem TO (in dem Fall 
mir) immer wieder etwas vor die Füße geworfen wird, aber die angeblichen 
Helfer selbst nicht lesen können. Anders kann ich mir die sinnfreien 
provozierenden Nachfragen nicht erklären. Alles was nachgefragt wird 
hatte ich schon geschrieben und zur Verfügung gestellt. Nachfragen wegen 
unklaren Formulierungen sehen anders aus.

Und was hat ein Timercode vom AVR128DB48 hier zu suchen? Dazu das Ding 
mit der Pin Lib. Das ist meine Lib. Wer die nicht hat kann nicht 
kompilieren. Das ist völlig logisch. Ich habe jetzt in dessen älteren 
Thread nicht nachgeschaut ob die bereit steht oder nicht. Aber selbst 
wenn nicht kann man ja danach ganz normal fragen ob man die Lib bekommen 
kann. Aber nein, wird gleich quer geschossen. Das Thema vom Thread hier 
wurde demnach überhaupt nicht verstanden. Dabei ist der Thread noch 
nicht lang sodass man alles lesen kann.

Auch der Vorwurf mit der Arduino IDE und dem avr-gcc kann ich nicht 
verstehen. Wer die Arduino IDE nicht verwendet und keine aktuelle 
Toolchain hinzufügen kann, der kann mir in dem konkreten Problem sowieso 
nicht helfen. Gewisse Dinge setze ich einfach voraus.

Auch das man sich an der Betreffzeile aufhängt finde ich unmöglich. 
Alles weitere steht im Text. Ein Betreff kann niemals alles 
wiederspiegeln. Man hätte bei allen irgendwas zu meckern.

Das Problem tritt nur mit dem "Atmega4809", der Arduino SPI Lib und dem 
avr-gcc 11.1.0 auf. Also eine spezielle Kombination. Der gcc 11 hat ein 
neues Frontend und ein neues Backend. Kann ja durch im Rahmen des 
Möglichen liegen das mit bestimmten Quellcode falsch kompiliert wird. 
Das liegt für mich jedenfalls nicht vom Tisch wischbar nachwievor auf 
der Hand.

Wenn jemand wirklich helfen möchte, dann klingen die Nachfragen 
sicherlich anders und dem würde ich sogar erklären wie er eine aktuelle 
Toolchain der IDE hinzufügt. Nur kamen dazu nie Nachfragen, sodass das 
nie ein Thema war.

Ich weiß nicht was ich zu dem Threadverlauf noch sagen soll. Hatte ich 
mir anders vorgestellt. Jedenfalls nicht so ein oberflächliches an der 
Nase herumführen. Wer nicht helfen möchte der muss nicht helfen. Das ist 
ganz einfach.

von Oliver S. (oliverso)


Lesenswert?

Nun ja, du bist lange genug dabei…

Bei solchen Problemen braucht es ein aufs wesentliche reduziertes 
compilierbares Beispiel, das den angeblichen Fehler reproduzierbar 
zeigt. Alles andere ist zwecklos.

Wenn das Problem halt nur bei mit völlig exotischen libs und völlig 
exotischen Prozessoren auftritt, und das daher eh niemand compilieren 
könnte, ist Hilfe kaum möglich.

Warum du dir allerdings die paar Zeilen Assembler, die da generiert 
werden, nicht selber anschaust, ist schon komisch.

Oliver

: Bearbeitet durch User
von Wilhelm M. (wimalopaan)


Lesenswert?

Wilhelm M. schrieb:
> Veit D. schrieb:
>> Demzufolge müßte den Membern ctrla und ctrlb ein Wert zugewiesen werden.
>> Das funktioniert jedoch aus unbekannten Gründen nicht.
>
> Woher willst Du das wissen. Gibt die beiden doch mal aus.

Veit D. schrieb:
> Die Member ctrla und ctrlb direkt auszugeben ist nicht so einfach. Habe
> ich wegen dem Datentyp noch nicht geschafft.

Wilhelm M. schrieb:
> Oh ha, ein uint8_t ist auch echt schwierig auszugeben ;-)
> Oder meinst Du, Du hast keinen Zugriff, weil sie private sind?

Darauf hast Du bisher gar nicht reagiert.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

@ Wilhelm
Mit private und uint8_t habe ich kein Problem. Ich bekomme keinen 
Zugriff durch die Verzwickung der verschiedenen Klassen die im Spiel 
sind. Deswegen hatte ich erstmal den Umweg über die SPI Register 
gemacht.

Ich muss von SPIClass:: eine Methode bauen um auf ctrla/ctrlb von 
SPISettingsMegaAVR:: zuzugreifen. Ich meine die Klasse SPIClassMegaAVR 
hat doch mittels friend class SPIClassMegaAVR; vollen Zugriff auf die 
Member der Klasse SPISettingsMegaAVR. Klappt aber nicht. Alle 3 return 
Varianten führen  zur Meldung ctrla is not a member  of ...
1
uint8_t SPIClass::getCtrla (void)
2
{
3
  return SPISettingsMegaAVR::ctrla;
4
  return SPIClassMegaAVR::ctrla;
5
  return ctrla;
6
}

von mh (Gast)


Lesenswert?

Veit D. schrieb:
> Ich weiß nicht was ich zu dem Threadverlauf noch sagen soll. Hatte ich
> mir anders vorgestellt. Jedenfalls nicht so ein oberflächliches an der
> Nase herumführen. Wer nicht helfen möchte der muss nicht helfen. Das ist
> ganz einfach.

Du hast als TO halt auch Pflichten. Zu diesen Pflichten gehört das 
Darstellen des Problems in einem Format, so dass dir geholfen werden 
kann. Das wird üblicherweise mit einem minimalen compilierbaren (und 
wenn möglich lauffähigen) Beispiel, das den Fehler reproduziert. Wenn du 
das nicht machst, musst du dich rechtfertigen. Wenn du deinen Pflichten 
selbständig, oder auf Nachfrage nachkommst, wird dir geholfen, soweit es 
möglich ist.

von Johannes S. (jojos)


Lesenswert?

Was für bescheuerte Prinzipienreiter hier nur noch unterwegs sind. 
Entwerft doch mal ein Formular welches jemand als Antrag auf die 
Bearbeitung seines Anliegens ausfüllen muss. In dreifacher Ausführung 
mit notarieller Beglaubigung natürlich.

von Wilhelm M. (wimalopaan)


Lesenswert?

Veit D. schrieb:
> Hallo,
>
> @ Wilhelm
> Mit private und uint8_t habe ich kein Problem.

Ja, warum schreibst Du es denn?
Das hast Du gesagt hier:

Veit D. schrieb:
> Die Member ctrla und ctrlb direkt auszugeben ist nicht so einfach. Habe
> ich wegen dem Datentyp noch nicht geschafft.

> Ich bekomme keinen
> Zugriff durch die Verzwickung der verschiedenen Klassen die im Spiel
> sind. Deswegen hatte ich erstmal den Umweg über die SPI Register
> gemacht.

Was ist denn daran verzwickt?
Du übergibt Deiner Funktion config(...) eine Instanz von 
SPISettingsMegaAVR.
Dann für doch da zwei Beobachter-Funktionen ein oder mache testweise die 
Elemente grad public.

> Ich muss von SPIClass:: eine Methode bauen um auf ctrla/ctrlb von
> SPISettingsMegaAVR:: zuzugreifen. Ich meine die Klasse SPIClassMegaAVR
> hat doch mittels friend class SPIClassMegaAVR; vollen Zugriff auf die
> Member der Klasse SPISettingsMegaAVR. Klappt aber nicht. Alle 3 return
> Varianten führen  zur Meldung ctrla is not a member  of ...
>
>
1
> uint8_t SPIClass::getCtrla (void)
2
> {
3
>   return SPISettingsMegaAVR::ctrla;
4
>   return SPIClassMegaAVR::ctrla;
5
>   return ctrla;
6
> }
7
>

Das mit den Beobachtern hast Du immer noch nicht verstanden. Das hatten 
wir schon mal in einem anderen Thread. Das Nachvollziehen der 
Informationen anderer scheint für Dich schwierig zu sein bzw. Du gehst 
darüber einfach hinweg, weil Du meinst es sei völlig unwichtig.

Zu der Funktion: ctrla/ctrlb sind doch keine statischen Datenelemente! 
C++ lernt man nicht durch trial-n-error.

Mach Deine Debug-Ausgabe in der config(...)-Funktion. Dann siehst Du, ob 
die aufgerufen wird und welche Werte in die beiden Register geschrieben 
werden.

von Veit D. (devil-elec)


Angehängte Dateien:

Lesenswert?

Hallo,

Danke Johannes für deine klaren Worte.



Die Klassennamen SPISettingsMegaAVR und SPIClassMegaAVR sind auch 
Datentypen. Nur eben "selbst" gebaute. Diese meinte ich. Im Nachgang 
betrachtet hätte ich das vielleicht näher beschreiben sollen. Gut. Warum 
die Member ctrla/ctrlb für eigene Zugriffe statisch sein sollen kann ich 
nicht nachvollziehen. Die Klassen haben doch mittels Vererbung Zugriff. 
In der Theorie jedenfalls. Ich wollte mir jedenfalls eine eigene 
Rückgabemethode bauen und bin daran gescheitert. Soweit so schlecht.

Jetzt lasse ich mir die Member in der config Methode direkt ausgeben. 
Wie du vorgeschlagen hast. Damit passiert genau das was ich befürchtet 
habe, jede Änderung führt zu anderen Ergebnissen. Vielleicht ist das 
auch nicht verkehrt sieht man doch das da Einiges passiert. Der 
komplette Testcode sieht so aus.
1
#include <utilities.h>
2
#include <SPI.h>
3
4
void setup()
5
{
6
  Serial.begin(250000);
7
  Serial.println(F("\nµC Reset #### #### ####"));
8
9
  showRegister(); 
10
  Serial.println(F("begin"));
11
  SPI.begin();
12
  showRegister(); 
13
  Serial.println(F("beginTransaction"));
14
  SPI.beginTransaction(DEFAULT_SPI_SETTINGS);
15
  showRegister();
16
  Serial.println(F("endTransaction"));
17
  SPI.endTransaction();
18
  showRegister(); 
19
}
20
21
void loop()
22
{ }
23
24
void showRegister (void)
25
{
26
  uint16_t reg16 = 0;
27
  Serial.print(F("SPI0 CTRLA: ")); formatBIN(Serial, SPI0.CTRLA, true); reg16 = (uint16_t)&SPI0.CTRLA; Serial.print(" "); formatHEXln(Serial, reg16, true);
28
  Serial.print(F("SPI0 CTRLB: ")); formatBIN(Serial, SPI0.CTRLB, true); reg16 = (uint16_t)&SPI0.CTRLB; Serial.print(" "); formatHEXln(Serial, reg16, true);
29
  Serial.println();
30
}

Dazu die Änderung in der SPI.cpp.
1
void SPIClass::config(SPISettingsMegaAVR settings)
2
{
3
  Serial.println(settings.ctrla, BIN);
4
  Serial.println(settings.ctrlb, BIN);
5
  SPI0.CTRLA = settings.ctrla;
6
  SPI0.CTRLB = settings.ctrlb;
7
  Serial.println(settings.ctrla, BIN);
8
  Serial.println(settings.ctrlb, BIN);
9
}

Die Ausgabe ist damit wie folgt. Mal abgesehen davon das die Werte nicht 
stimmen, gehen Bits vom Member zum Register verloren. Das Bit 3 in CTRLA 
fehlt.
1
µC Reset #### #### ####
2
SPI0 CTRLA:    0b0000'0000 0x08C0
3
SPI0 CTRLB:    0b0000'0000 0x08C1
4
5
begin
6
0
7
1
8
0
9
1
10
SPI0 CTRLA:    0b0000'0000 0x08C0
11
SPI0 CTRLB:    0b0000'0001 0x08C1
12
13
beginTransaction
14
1010
15
0
16
1010
17
0
18
SPI0 CTRLA:    0b0000'0010 0x08C0
19
SPI0 CTRLB:    0b0000'0000 0x08C1
20
21
endTransaction
22
SPI0 CTRLA:    0b0000'0010 0x08C0
23
SPI0 CTRLB:    0b0000'0000 0x08C1

Lässt man in der config() Methode die ersten beiden Ausgaben weg erhält 
man andere Werte. Bei CTRLB gehen keine Bits verloren.
1
µC Reset #### #### ####
2
SPI0 CTRLA:    0b0000'0000 0x08C0
3
SPI0 CTRLB:    0b0000'0000 0x08C1
4
5
begin
6
0
7
1
8
SPI0 CTRLA:    0b0000'0000 0x08C0
9
SPI0 CTRLB:    0b0000'0001 0x08C1
10
11
beginTransaction
12
0
13
10000010
14
SPI0 CTRLA:    0b0000'0000 0x08C0
15
SPI0 CTRLB:    0b1000'0010 0x08C1
16
17
endTransaction
18
SPI0 CTRLA:    0b0000'0000 0x08C0
19
SPI0 CTRLB:    0b1000'0010 0x08C1


Lässt man in der config() Methode nur die letzten beiden Ausgaben weg 
erhält man wieder andere Werte.
1
µC Reset #### #### ####
2
SPI0 CTRLA:    0b0000'0000 0x08C0
3
SPI0 CTRLB:    0b0000'0000 0x08C1
4
5
begin
6
0
7
1
8
SPI0 CTRLA:    0b0000'0000 0x08C0
9
SPI0 CTRLB:    0b0000'0001 0x08C1
10
11
beginTransaction
12
10
13
0
14
SPI0 CTRLA:    0b0000'0010 0x08C0
15
SPI0 CTRLB:    0b0000'0000 0x08C1
16
17
endTransaction
18
SPI0 CTRLA:    0b0000'0010 0x08C0
19
SPI0 CTRLB:    0b0000'0000 0x08C1

Lässt man die Ausgaben in der config() Methode komplett drin und nimmt 
die "SPI Methoden" Textausgaben im setup() raus, erhält man wieder 
andere Werte.
1
µC Reset #### #### ####
2
SPI0 CTRLA:    0b0000'0000 0x08C0
3
SPI0 CTRLB:    0b0000'0000 0x08C1
4
5
0
6
1
7
0
8
1
9
SPI0 CTRLA:    0b0000'0000 0x08C0
10
SPI0 CTRLB:    0b0000'0001 0x08C1
11
12
11001
13
1010110
14
11001
15
1010110
16
SPI0 CTRLA:    0b0001'0001 0x08C0
17
SPI0 CTRLB:    0b0100'0110 0x08C1
18
19
SPI0 CTRLA:    0b0001'0001 0x08C0
20
SPI0 CTRLB:    0b0100'0110 0x08C1

Das Kombinationsspiel könnte man fortsetzen, aber ich denke das Problem 
ist erkennbar. Wenn ich das mit dem avr-gcc 10.3.0 mache erhalte ich 
immer die gleichen korrekten Daten.
1
µC Reset #### #### ####
2
SPI0 CTRLA:    0b0000'0000 0x08C0
3
SPI0 CTRLB:    0b0000'0000 0x08C1
4
5
begin
6
100001
7
100
8
SPI0 CTRLA:    0b0010'0001 0x08C0
9
SPI0 CTRLB:    0b0000'0100 0x08C1
10
11
beginTransaction
12
100001
13
100
14
SPI0 CTRLA:    0b0010'0001 0x08C0
15
SPI0 CTRLB:    0b0000'0100 0x08C1
16
17
endTransaction
18
SPI0 CTRLA:    0b0010'0001 0x08C0
19
SPI0 CTRLB:    0b0000'0100 0x08C1

Wie nun weiter?

von Wilhelm M. (wimalopaan)


Lesenswert?

Veit D. schrieb:
> Wie nun weiter?

Zunächst erst einmal alles Unnötige aus Deinem Beispiel heraus nehmen. 
Schritt für Schritt, bis zu dem Punkt, wo es dann Deines Erachtens 
wieder konsistent ist. Dann hast Du einen Ansatz gefunden. Könnte ja 
auch ein Stack-Overflow sein ...

Im Moment muss man sich ja alles zusammen suchen. Es wurde ja schon 
geschrieben, dass Du ein "minimum verifying complete example" erstellen 
sollst.

: Bearbeitet durch User
von Wilhelm M. (wimalopaan)


Lesenswert?

Veit D. schrieb:
> Warum
> die Member ctrla/ctrlb für eigene Zugriffe statisch sein sollen kann ich
> nicht nachvollziehen.

Ich auch nicht. Deswegen: warum versuchst Du auf ein nicht existierendes 
statisches Element zuzugreifen. Das hast Du ins Spiel gebracht:

Veit D. schrieb:
> uint8_t SPIClass::getCtrla (void)
> {
>   return SPISettingsMegaAVR::ctrla;
>   return SPIClassMegaAVR::ctrla;
>   return ctrla;
> }

Ich vermute, Du hast meine Bemerkung oben gar nicht verstanden.

: Bearbeitet durch User
von Veit D. (devil-elec)


Lesenswert?

Hallo,

aber soweit war ich doch schon einmal. Wie oft soll ich denn noch von 
vorn anfangen? Ich kann die ewigen Vorwürfe nicht mehr hören zeige was 
Komplettes. Wie kompletter als komplett soll es denn noch sein? Das 
Gezeigte ist doch komplett. Ich verstehe das Problem nicht. Für den 
Testcode liefere sich sogar frei Haus meine Lib mit. Damit ja niemand 
seine Maus vom zu vielen klicken kaputt macht. Kann aber jeder auch ohne 
machen wenn er auf die Formatierung verzichtet. Arduino IDE, ggf. mein 
Lib importieren, den Sketch kopieren und schon kann es los gehen. 
Einfacher gehts ja nun wirklich nicht. Was soll ich daran noch 
vereinfachen? Das hätte ich gern einmal gewusst.

Wenn ich config() Methodenaufruf weglasse, leere Methode, stimmen alle 
Registerwerte. Sobald die config aufgerufen wird kommt wieder Mist raus. 
Hatte ich aber alles schon mehrfach geschrieben. Das ist der Punkt ab 
der es schief läuft.

Warum sollte ein möglicher Stack Overflow ausgerechnet mit dem gcc 11 
auftreten? Fakt ist doch das gcc 11 irgendwie anders kompiliert was zum 
Fehler führt. Das kann man doch nicht ignorieren.

PS: Wegen Member ctrla/ctrlb. Ich vermute auch wir reden komplett 
aneinander vorbei.

von Wilhelm M. (wimalopaan)


Lesenswert?

Veit D. schrieb:
> Wenn ich config() Methodenaufruf weglasse, leere Methode, stimmen alle
> Registerwerte. Sobald die config aufgerufen wird kommt wieder Mist raus.
> Hatte ich aber alles schon mehrfach geschrieben. Das ist der Punkt ab
> der es schief läuft.

Meine Güte, ist das so schwer zu verstehen? Koche das Beispiel so weit 
herunter, dass es jeder - auch ohne diesen Arduino-Kram - nachvollziehen 
kann. Du hast da mehrere Riesen-Klassen, von deren Inhalt 95% nicht 
benötigt wird. Entkerne das soweit, bis der Fehler ggf. gar nicht mehr 
auftritt, dann gehe einen Schritt zurück, und Du hast genau das, um 
Hilfe zu bekommen.

Wie kommen denn die Registerinhalte in CTRLA, wenn config() gar nicht 
aufgerufen wird? Oder meinst Du die Reset-Inhalte? Worher hast Du es 
genau anders herum gesagt, ohne config() nur 0x00 drin. Was denn nun?

von Wilhelm M. (wimalopaan)


Lesenswert?

Veit D. schrieb:
> PS: Wegen Member ctrla/ctrlb. Ich vermute auch wir reden komplett
> aneinander vorbei.

Dann mache es klar. Jedenfalls hast Du einen stat. Elementzugriff 
codiert, auf ein Element, das es nicht gibt. Das lese ich aus dem 
Code-Schnipsel. Den Rest musst Du erklären.

von mh (Gast)


Lesenswert?

Veit D. schrieb:
> Wie oft soll ich denn noch von
> vorn anfangen? Ich kann die ewigen Vorwürfe nicht mehr hören zeige was
> Komplettes. Wie kompletter als komplett soll es denn noch sein?

Das Wort, dass du immer zu überlesen scheinst ist "minimal". Falls du es 
noch nicht verstanden hast. Die Forderung nach einem minimalen, 
compilierbaren und lauffähigen Beispiel, das den Fehler reporduziert hat 
zwei Aspekte.
- Es ist deutlich einfacher für andere Personen zu überblicken.
- In 95% der Fälle findest du selbst auf dem Weg zu diesem Beispiel die 
Ursache und eine Lösung (und meistens andere Probleme, von denen du bis 
jetzt nichts wusstest).

von Wilhelm M. (wimalopaan)


Lesenswert?

Falls Du aber mit diesen Antworten hier nicht zufrieden bist, dann poste 
das als gcc-bug (Du bist ja der Meinung, dass es einer ist) im 
gcc-bugzilla. Wenn Du da dann kein "minimal verifying complete example" 
lieferst, ist der Eintrag schneller zu, als Du ihn aufgemacht hast. 
Gleiches gilt für Stack-Overflow. Also, versuche es doch dort einmal.

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Veit D. schrieb:
> aber soweit war ich doch schon einmal. Wie oft soll ich denn noch von
> vorn anfangen? Ich kann die ewigen Vorwürfe nicht mehr hören zeige was
> Komplettes. Wie kompletter als komplett soll es denn noch sein? Das
> Gezeigte ist doch komplett. Ich verstehe das Problem nicht.

Das Problem fängt mit A… an und endet auf ...ino.

Kaum jemand hat große Lust, in dem wilden Mischmasch von Bibliotheken 
und sonstigem Gedöns irgendwelche Fehler zu suchen.

Oliver

von Kaj (Gast)


Lesenswert?

Veit D. schrieb:
> Hallo
Hab mal in das Zip aus diesem Beitrag geschaut... Hat nichts mit dem 
Problem zu tun, aber:
Du weisst was include macht und wie man das nutzt?
Da fehlen saemtliche includes in deiner tollen utilities.h. Wo kommt 
Stream her? Wo kommt uint8_t her? Wo kommen byte und Serial in den 
examples her? Warum sind die includes mit <> und nicht mit ""?
Wie soll man damit das Problem nachvollziehen?

Wie waere es, wenn du dir Register/Speicher/was auch immer einfach im 
Debugger anschaust?

Wilhelm M. schrieb:
> Wenn Du da dann kein "minimal verifying complete example"
> lieferst, ist der Eintrag schneller zu, als Du ihn aufgemacht hast.
> Gleiches gilt für Stack-Overflow. Also, versuche es doch dort einmal.
Da muss ich Wilhelm leider recht geben. Mit dem Beispiel wird das 
nichts. Nach ueber 2700 eigenen Beitraegen in diesem Forum sollte der TO 
das aber wissen.

von Johannes S. (jojos)


Lesenswert?

Arduino ist nicht meine bevorzugte Umgebung, aber ich kann das Internet 
bedienen und kann dem Problem folgen.
Stream und anderes Zeug kommt aus 
https://github.com/arduino/ArduinoCore-API, was ist daran so schwierig?
Ein Debugger wäre tatsächlich ein feines Hilfsmittel, ein Grund warum 
ich schon lange bei ARM CM gelandet bin. Trotzdem sollte sich auch 
dieses Puzzle lösen lassen, und halte die Wahrscheinlichkeit für groß 
das es tatsächlich ein gcc Problem ist weil im 10/11er einiges umgebaut 
wurde.
Ich bin bei AVR Tools nicht mehr aktuell, kann man evtl. mit dem AVR 
Studio Simulator da durch steppen? Das AVR Studio konnte Arduino 
Projekte lesen und konvertieren, ich weiß nur nicht ob man dem einfach 
die gcc11 unterjubeln kann.

Der Programablauf ist etwas tricky weil die SPISettings in 
https://github.com/arduino/ArduinoCore-API/blob/master/api/HardwareSPI.h, 
also in einem gemeinsamen core liegen. Diese Klasse ist nur ein Helfer 
um die SPI Einstellungen zu halten.
Im 
https://github.com/arduino/ArduinoCore-megaavr/blob/master/libraries/SPI/src/SPI.h
gibt es eine für den megaAVR angepasste Settings Klasse. Der Ablauf ist 
dann:
config(DEFAULT_SPI_SETTINGS);
Makro expandiert zum default constructor für SPISettings im gemeinen 
core
damit ruft config einen Konverter von SPISettings nach 
SPISettingsMegaAVR auf, in 
https://github.com/arduino/ArduinoCore-megaavr/blob/5717c2a3ac8ecc6e5f382715b7f6225e1c809007/libraries/SPI/src/SPI.h#L179-L181
Da werden mehrfach temporäre Objekte auf dem Stack erzeugt, aber die 
paar Bytes sollte der µC mit 6 kB RAM schon packen.
Evtl. geht hier was schief wenn das temporäre SPISettings benutzt werden 
soll? 
https://github.com/arduino/ArduinoCore-megaavr/blob/5717c2a3ac8ecc6e5f382715b7f6225e1c809007/libraries/SPI/src/SPI.h#L69

Und dann bleibt schon die Frage, warum kommt eine ältere gcc damit klar 
und eine neuere nicht?

noch ein Edit:
geht die Zeile im letzten Link nicht ins Leere? Im Konstruktor aus 
SPISettings& wird der SPISettingsMegaAVR(,,) aufgerufen, aber damit wird 
ja nix gemacht. Liegt auf dem Stack und wird wieder abgeräumt, und der 
Konstruktor liefert ein leeres Objekt, also genau das was der TO 
beobachtet.
Damit hätten die älteren gcc eher zufällig den initialisierten Stack 
benutzt, bei anderem Speicherläyout geht es damit korrekterweise schief.

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Johannes S. schrieb:
> Arduino ist nicht meine bevorzugte Umgebung, aber ich kann das Internet
> bedienen und kann dem Problem folgen.

Was niemandem einer Lösung näher bringt.

Johannes S. schrieb:
> Und dann bleibt schon die Frage, warum kommt eine ältere gcc damit klar
> und eine neuere nicht?

Selbst das ist doch eine reine Behauptung, die bisher noch gar nicht 
nachgewiesen wurde.

Und ohne dem TO allzu nahe treten zu wollen, ist der gezeigte Code in 
allen Belangen so weit weg von "solide" und "verstanden", daß es reiner 
Zufall ist, ob da was funktioniert oder nicht.

Oliver

: Bearbeitet durch User
von Johannes S. (jojos)


Lesenswert?

Oliver S. schrieb:
> Was niemandem einer Lösung näher bringt.

ich habe nicht gelabert und genörgelt wie die anderen hier, ich habe die 
Zeile mit dem Fehler lokalisiert.

also nochmal:
https://github.com/arduino/ArduinoCore-megaavr/blob/5717c2a3ac8ecc6e5f382715b7f6225e1c809007/libraries/SPI/src/SPI.h#L69

ist nicht korrekt. Projekt forken, branch  mit fix erstellen, PR an den 
Autor, das überlasse ich dem TO. So geht das, das ist ein OSS Community 
Projekt und ob es gefällt oder nicht, es ist populär und so haben sich 
Arduino und andere weiterentwickelt.

von Oliver S. (oliverso)


Lesenswert?

Johannes S. schrieb:
> ich habe nicht gelabert und genörgelt wie die anderen hier, ich habe die
> Zeile mit dem Fehler lokalisiert.

Ok, dein Edit hatte ich übersehen. Da sollte dann jemand das Thema 
"delegating constructors" nochmals nachlesen.

Bedeutet das jetzt, daß alle Compiler vor gcc 11 fehlerhaft waren?

Oliver

: Bearbeitet durch User
von Johannes S. (jojos)


Lesenswert?

ich würde eher sagen es war Zufall das etwas funktioniert hat, das ist 
ja einfach ein nicht initialsiertes Objekt auf dem Stack.

von Wilhelm M. (wimalopaan)


Lesenswert?

Johannes S. schrieb:
> noch ein Edit:
> geht die Zeile im letzten Link nicht ins Leere? Im Konstruktor aus
> SPISettings& wird der SPISettingsMegaAVR(,,) aufgerufen, aber damit wird
> ja nix gemacht. Liegt auf dem Stack und wird wieder abgeräumt, und der
> Konstruktor liefert ein leeres Objekt, also genau das was der TO
> beobachtet.
> Damit hätten die älteren gcc eher zufällig den initialisierten Stack
> benutzt, bei anderem Speicherläyout geht es damit korrekterweise schief.

Oh wei, wieder eine Bestätigung dafür, dass die Code-Qualität der 
Arduino-Sachen nicht die beste ist.

Ich hatte da schon nach dieser Zeile aufgehört zu lesen:

https://github.com/arduino/ArduinoCore-megaavr/blob/5717c2a3ac8ecc6e5f382715b7f6225e1c809007/libraries/SPI/src/SPI.cpp#L27


Glückwunsch an Johannes.

von Oliver S. (oliverso)


Lesenswert?

Johannes S. schrieb:
> ich würde eher sagen es war Zufall das etwas funktioniert hat,

Oliver S. schrieb:
> Und ohne dem TO allzu nahe treten zu wollen, ist der gezeigte Code in
> allen Belangen so weit weg von "solide" und "verstanden", daß es reiner
> Zufall ist, ob da was funktioniert oder nicht.

Tja, ein Leben ohne Arduino ist nicht nur möglich, sondern tatsächlich 
sinnvoll.

Oliver

von Veit D. (devil-elec)


Lesenswert?

Hallo,

wenn ich die Antworten hier lese weiß ich nicht mehr was ich sagen soll. 
Das Beste ist, ich wundere mich einfach nur darüber. Alles andere führt 
zu nichts.

Ein Einziger hat es richtig gemacht. Das ist Johannes. Aus der Kalten 
heraus mitgemacht, umfangreichen fremden Code gelesen, ohne Theater 
Problem analysiert und auf den Punkt gezeigt. Vor solchen Leuten ziehe 
ich meinen Hut. Du hast meinen allertiefsten Respekt. Das kann ich dir 
sagen.

Jetzt machen meine Beobachtungen auch Sinn, wenn man die Member ctrla, 
cltrb selbst initialisiert, dann sieht man das genau die Werte in den 
Registern landen. Ohne Initialisierung landen Zufallswerte (non static 
Member) in den Registern, weil das mit dem Kontruktor selbst bzw. 
überladen schief läuft. Soweit mein Verständnis zum Problem im Nachgang.

Einen konkreten Vorwurf an die Arduino Programmierer kann man auch nicht 
machen. Ich jedenfalls nicht. Erstens wird die IDE "nur" mit avr-gcc 
7.3.0 ausgeliefert und Zweitens kann man diesen Fehler ja nur finden 
wenn ihn auch entdeckt. Wenn der Fehler bis 10.3.0 nicht auftaucht, weil 
der gcc bis dahin scheinbar fehlertoleranter ist, tja dann kann man ihn 
nicht finden. Codefehler findet man sicherlich nicht nur bei Arduino. Es 
hat ja seinen Grund das gcc bzw. C++  weiterentwicklet wird und immer 
strenger wird. Hier in dem Fall hätte ich mir irgendeine Warnung seitens 
gcc gewünscht. Falls das überhaupt möglich ist. Wunschdenken.  :-)

Diese Erkenntnis nehme ich mit ins Arduino Forum und dann kann das 
sicherlich von "Arduino" gefixt werden. Ich werde auf den Thread 
verweisen, vielleicht können von denen auch paar Leute deutsch falls 
erforderlich.

Nochmals vielen Dank Johannes. Schön das es solche Menschen noch gibt.

von Oliver S. (oliverso)


Lesenswert?

Veit D. schrieb:
> Wenn der Fehler bis 10.3.0 nicht auftaucht, weil
> der gcc bis dahin scheinbar fehlertoleranter ist, tja dann kann man ihn
> nicht finden.

Das hat mit Fehlertoleranz im Compiler nichts zu tun (die gibt es acuh 
nicht). Das ist ein so grundlegender Fehler im Code, da müssen schon 
sehr viele Zufälle zusammenkommen, daß das so aussieht, als ob es 
funktioniert.

Das ist bisher nicht aufgefallen, weil es noch niemand ernsthaft benutzt 
hat.

Oliver

: Bearbeitet durch User
von So schön ruhig (Gast)


Lesenswert?

Nanu, wo sind denn die Maulhelden, allen voran "Wilhelm", abgeblieben? 
War wohl nichts -den TO für unfähig erklären, aber selbst nicht in der 
Lage sein, das Problem auch nur im Ansatz zu erfassen.

von erarre humanum est (Gast)


Lesenswert?

So schön ruhig schrieb:
> den TO für unfähig erklären, aber selbst nicht in der
> Lage sein, das Problem auch nur im Ansatz zu erfassen

Bist du dir da sicher?
Das der TO unfähig ist, steht ja außer Frage - nur ein, sagen wir mal 
höflich -untalentierter und suboptimal mit der Anlage zur Selbstkritik 
Beschenkter- erklärt seine individuelle 'Programmierschnitzer' (wie 
Verwendung unitialisierter Objekte) mit mangelnder 'Fehlertoleranz des 
Compilers'.

Und möglicherweise liegt das angemoserte Ausbleiben einer 'Warning' 
vielleicht auch am Unvermögen, die Generierung derselben einzuschalten 
('-Wall').

von mh (Gast)


Lesenswert?

So schön ruhig schrieb:
> Nanu, wo sind denn die Maulhelden, allen voran "Wilhelm", abgeblieben?
> War wohl nichts -den TO für unfähig erklären, aber selbst nicht in der
> Lage sein, das Problem auch nur im Ansatz zu erfassen.

Zwischen "in der Lage sein" und "keine Lust den Haufen S****** 
durchzuarbeiten" besteht ein großer Unterschied. Und anders kann man das 
was da auf github verlinkt ist nicht nennen. Schön für den TO, dass er 
jemanden gefunden hat, der die Arbeit für ihn übernimmt. Allerdings hat 
der TO nicht wirklich etwas gelernt und wird beim nächsten Mal 
vermutlich auch nicht in der Lage sein den Fehler selbst zu finden. Und 
wie sich herausgestellt hat, lagen alle Maulhelden im Recht. Denn der 
gcc ist nicht defekt.

von So schön ruhig (Gast)


Lesenswert?

mh schrieb:
> Schön für den TO, dass er
> jemanden gefunden hat, der die Arbeit für ihn übernimmt.

Das ist jemand (Johannes), der mit dem Wort "helfen" etwas anzufangen 
weiß.
Alle Achtung von mir dafür.

> Allerdings hat
> der TO nicht wirklich etwas gelernt und wird beim nächsten Mal
> vermutlich auch nicht in der Lage sein den Fehler selbst zu finden.

Der TO hat beschrieben, was er daraus gelernt hat.

> Und
> wie sich herausgestellt hat, lagen alle Maulhelden im Recht. Denn der
> gcc ist nicht defekt.

Wenn eine Version des Programmes nicht mehr das tut, was die 
Vorgängerverion noch tat -woran liegt das dann?

Ich halte mich von diesem Zeug so fern, wie nur irgend möglich, denn es 
hat sich (nicht nur hier und jetzt) gezeigt, daß das Programmieren damit 
einem Würfelspiel gleicht.

von erarre humanum est (Gast)


Lesenswert?

So schön ruhig schrieb:

> Wenn eine Version des Programmes nicht mehr das tut, was die
> Vorgängerverion noch tat -woran liegt das dann?

Am Zufall aka undefined Behaviour.

Das ist so als wenn deine Jetzige Vormundschaftstussi achselzuckend 
deinen Raum verlässt, obwohl Ihre Vormundschaftsvorgängerin auf die 
selbe Aufforderung "Liess mir meine Wünschen von meinen geschlossenen 
Lippen ab" wortlos den Fernseher einschaltete und eine Tüte Aldi-Popcorn 
in die Blumenvase schüttete.

von So schön ruhig (Gast)


Lesenswert?

erarre humanum est schrieb:

> Das ist so als wenn deine Jetzige Vormundschaftstussi achselzuckend
> deinen Raum verlässt, obwohl Ihre Vormundschaftsvorgängerin auf die
> selbe Aufforderung "Liess mir meine Wünschen von meinen geschlossenen
> Lippen ab" wortlos den Fernseher einschaltete und eine Tüte Aldi-Popcorn
> in die Blumenvase schüttete.

Findest Du das wirklich lustig? Dann wundert mich Deine Verteidigung 
unbrauchbaren Mistes so gar nicht.

von Wilhelm M. (wimalopaan)


Lesenswert?

So schön ruhig schrieb:
> Nanu, wo sind denn die Maulhelden, allen voran "Wilhelm", abgeblieben?
> War wohl nichts -den TO für unfähig erklären, aber selbst nicht in der
> Lage sein, das Problem auch nur im Ansatz zu erfassen.

Dann habe ich wohl Deinen sachdienlichen Hinweis überlesen? Hätte ich 
gerne mal gesehen, "Gast".

So schön ruhig schrieb:
> Der TO hat beschrieben, was er daraus gelernt hat.

In der Tat: der TO hat wie ein kleines Kind gelernt, dass man seinen 
Mist nur anderen, sehr sehr netten Leuten vorwerfen muss, ohne sich auch 
nur ein kleines bisschen Mühe zu geben. Mehr hat er leider nicht 
gelernt!

In finde es auch toll, dass Johannes sich die Mühe gemacht hat - und 
finde es eben aus o.g. Grund gleichzeitig auch schade, dass er es 
gemacht hat.

Zu seiner Lösung habe ich ihm gratuliert, weil er sich durch diesen 
Misthaufen durchgelesen hat.
Ja, das habe ich nicht getan, und werde es in Zukunft auch nicht tun, 
wenn der Code bestimmte Merkmale aufweist und andere eben nicht 
aufweist.

Warum ich mir den Code nicht weiter angesehen habe, steht weiter oben. 
Wenn ich so etwas lese, ist es für mich nur Zeitverschwendung, die 
tatsächliche Problemstelle zu suchen.
Stattdessen habe ich ganz oben begonnen, den TO auf mögliche Ursachen 
hinzuweisen. Natürlich kann auch ein Compiler wie gcc oder clang Fehler 
aufweisen, doch auch habe ich ganz oben begründet meine Zweifel daran 
sofort geäußert. Stattdessen habe ich dem TO versucht Methodiken 
aufzuzeigen, mit denen er selbst zum Ziel kommt - etwas ein MCVE zu 
erstellen. Das ist übliche Praxis. Dazu war der TO nicht willens bzw. in 
der Lage.

Sorry, aber dieser TO neigt dazu, alles das, was er nicht versteht, erst 
einmal als unnötig oder falsch zu bezeichnen. Auch da haben wir hier ein 
Beispiel: seine Beobachterfunktion. In seinen Augen ist 
const-correctness unnötig. Das hatten wir in einem anderen Beitrag. Und 
siehe da: wieder nichts gelernt.
Das nächste Beispiel ist die Unfähigkeit, die beiden Elemente ctrla / 
ctrlb einfach mal auszugeben. Sorry, das ist C++ Grundschule. Kriegt er 
nicht hin. Stattdessen murkst er da irgendwas mit Zugriff auf 
nicht-existierende statische Elemente zurecht.

So nett Johannes auch war, es wird rein gar nichts helfen.

von So schön ruhig (Gast)


Lesenswert?

Was bin ich froh, auf solche "Helfer" wie Dich, Wilhelm nicht angewiesen 
zu sein. 3 Kreuze mache ich dafür...

Es sind ja nicht die ersten Beiträge aus Deiner Feder, die mir sauer 
aufstoßen, denn ALLE folgen dem gleichen Schema: Ich bin der Größte, 
aber so abgehoben, daß ich mich nicht in die Niederungen von Quelltexten 
anderer Leute begebe. Dafür spare ich dann nicht an wohlfeilen 
Ratschlägen, die meterweit am Ziel vorbeigehen.

Braucht kein Mensch.

von Wilhelm M. (wimalopaan)


Lesenswert?

So schön ruhig schrieb:
> Was bin ich froh, auf solche "Helfer" wie Dich, Wilhelm nicht angewiesen
> zu sein. 3 Kreuze mache ich dafür...

Ja, dann ist es ja gut so.

BTW: was war nochmal Dein substantieller Beitrag für die Problemlösung 
hier. Oder gibt Du nur Allgemeinplätze ab?

von mh (Gast)


Lesenswert?

So schön ruhig schrieb:
> Was bin ich froh, auf solche "Helfer" wie Dich, Wilhelm nicht angewiesen
> zu sein. 3 Kreuze mache ich dafür...

Ich bin zwar nicht immer seiner Meinung, aber wenn es um Antworten auf 
konkrete fachliche Fragen geht, kann man Wilhelm nicht wirklich etwas 
vorwerfen.

von Rechtsaussen als Linksabbieger (Gast)


Lesenswert?

Wilhelm M. schrieb:
> So schön ruhig schrieb:
>> Was bin ich froh, auf solche "Helfer" wie Dich, Wilhelm nicht angewiesen
>> zu sein. 3 Kreuze mache ich dafür...
>
> Ja, dann ist es ja gut so.
>
> BTW: was war nochmal Dein substantieller Beitrag für die Problemlösung
> hier. Oder gibt Du nur Allgemeinplätze ab?

Ich sage doch: Du liest zwar, begreifst aber das Gelesene offensichtlich 
nicht. Ich zitiere mich deshalb selbst:

> Ich halte mich von diesem Zeug so fern, wie nur irgend möglich, denn es
> hat sich (nicht nur hier und jetzt) gezeigt, daß das Programmieren damit
> einem Würfelspiel gleicht.

Wie also sollte ich da einen "substanziellen Beitrag" leisten können, 
wenn das selbst solchen Spezialisten wie Dir in keiner Weise gelingt?

von Wilhelm M. (wimalopaan)


Lesenswert?

Rechtsaussen als Linksabbieger schrieb:
> Ich sage doch: Du liest zwar, begreifst aber das Gelesene offensichtlich
> nicht. Ich zitiere mich deshalb selbst:
>
>> Ich halte mich von diesem Zeug so fern, wie nur irgend möglich, denn es
>> hat sich (nicht nur hier und jetzt) gezeigt, daß das Programmieren damit
>> einem Würfelspiel gleicht.
>
> Wie also sollte ich da einen "substanziellen Beitrag" leisten können,
> wenn das selbst solchen Spezialisten wie Dir in keiner Weise gelingt?

Jetzt auch von Versteckspiel??? Traurig!

von Veit D. (devil-elec)


Lesenswert?

Hallo,

naja Wilhelm. Du musst schon zugeben das du so getan hast den SPI Lib 
Code gelesen zu haben, mich von oben herab belehrend zu allen möglichen 
behandelt hast, also wie immer und dich dann aber mit der Frage zur 
config Methode blamiert hast. Denn in der begin Methode ist klar 
ersichtlich womit die Register beschrieben werden um dann von der 
Problem Methode config falsch überschrieben zu werden. Du hast demnach 
nicht einmal den Code gelesen, bist aber immer schön brav darauf 
rumgeritten. Mir aber keine angebliche Lesebereitschaft vorwerfen. Das 
ist mehr als nur arrogant. Wie gesagt drehst du dir alles zurecht damit 
alle anderen immer blöd aussehen. Das habe ich schon lange durchschaut. 
Lesekompetenz und Pädagogik sieht anders aus. Wie man dich auf Studenten 
loslassen kann verstehe ich bis heute nicht. Du magst in deiner eigenen 
Programmierwelt bestens zurecht kommen. Aber mit fremden Code tust du 
dich genauso schwer wie viele andere auch. Alles was nicht gefällt wird 
als inkompetent abgestempelt.

Bei allen anderen Vorwürfen gegen mich kann ich nur sagen. Steck ich 
weg. Ich weiß was ich kann und ich weiß was ich nicht kann. Und es 
sollte sich jeder einmal Fragen wofür ein Forum da ist wenn man keine 
Fragen zu Problemen stellen darf? Auch wenn es im nachhinein zu einem 
unerwartenden Ergebnis führt. Das ist eben so. Die Vorarbeit habe ich 
geleistet, Johannes hat es aufgegriffen und verstanden und wie gesagt 
dankend das eigentliche Problem gezeigt. Hat von allen anderen ja auch 
niemand fertig gebracht. Für seine Hilfsbereitschaft und unkomplizierte 
Hilfe wird er jetzt noch angegangen. Also das kann es ja nun auch nicht 
sein. Wirklich nicht.

Der Rest hier folgt wie immer dem gleichen Schema. Wenn das Problem 
geklärt ist melden sich plötzlich alle zu Wort die es schon immer 
gewusst haben.

Auch das Arduino Programmierer hier generell für blöd gehalten werden 
darüber kann ich nur lachen. Da sind durchaus fähige Leute dabei. 
Vorallendingen haben "wir" nicht das große Maul. Das muss ich auch 
einmal klar sagen. Außerdem will ich mal jemanden sehen der so ein 
Gesamtbauwerk wie Arduino programmiert ohne in Probleme zugeraten. Das 
ist ein ständiges abwägen zwischen Kompatibilität zu alten Code und 
Unterstützung für neue Controller. Wenn man eine gewisse Kompatibilität 
über Board wirft und paar neue Features einbaut, dann kommen von fähigen 
Arduino Programmiereren wie MCUdude und SpenceKonde (um mal 2 zu nennen) 
Boarderweiterungen heraus. Sowas würde doch hier niemand freiwillig 
machen und für alle bereit stellen. Das nennt sich Community. Wenn sich 
hier alle auf ihre Kernkompetenz konzentrieren und nicht immer blind 
austeilen würden, dann wäre das hier auch ganz dufte.

Damit beende ich den Thread für mich.

von mh (Gast)


Lesenswert?

Veit D. schrieb:
> Bei allen anderen Vorwürfen gegen mich kann ich nur sagen. Steck ich
> weg. Ich weiß was ich kann und ich weiß was ich nicht kann.
Mit wegstecken meinst du Kritik ignorieren. So kommt es jedenfalls 
rüber.
> Und es sollte sich jeder einmal Fragen wofür ein Forum da ist wenn man keine 
Fragen zu Problemen stellen darf?
Du darfst fragen was immer und wie du willst. Du musst aber auch mit den 
Antworten leben. Du solltest wirklich mal auf Stackoverflow nachlesen, 
was da die Anforderungen an den Fragenden sind. Die FAQ: 
https://meta.stackoverflow.com/questions/251225/faq-index-for-stack-overflow
Der erste Eintrag ist "What is the proper way to approach Stack Overflow 
as someone totally new to programming?"
Die akzeptierte Antwort solltest du dir wirklich einmal genau 
durchlesen.

Der zweite Eintrag ist "How much research effort is expected of Stack 
Overflow users?"
Die Akzeptierte Antwort fängt an mit "A lot. Asking a question on Stack 
Overflow should be the last step in your process for finding an 
answer—if the information that you need already exists, then you should 
be able to find it before asking."

> Auch wenn es im nachhinein zu einem unerwartenden Ergebnis führt. Das ist eben 
so.
Das sollte aber nicht so sein. Warum hast du ein erwartetes Ergebnis? 
Weißt du die Antwort oder hast du ein Vorurteil?

> Die Vorarbeit habe ich geleistet
Nein! Du hast ETWAS Vorarbeit geleistet, aber nicht genug und nicht die 
richtige.

>Johannes hat es aufgegriffen und verstanden und wie gesagt dankend das > 
eigentliche Problem gezeigt. Hat von allen anderen ja auch niemand fertig 
gebracht.
Es sollte dir zu denken geben, dass dir nur EINE Person geholfen hat. 
Hat das nur etwas mit uns zu tun oder hat das vielleicht doch etwas mit 
dir zu tun? Warum haben wir all diese Beiträge geschrieben?
> Für seine Hilfsbereitschaft und unkomplizierte Hilfe wird er jetzt noch > 
angegangen. Also das kann es ja nun auch nicht sein. Wirklich nicht.
Wo wird er angegangen? Beziehst du dich auf den Beitrag von Wilhelm?
Wilhelm M. schrieb:
> In finde es auch toll, dass Johannes sich die Mühe gemacht hat - und
> finde es eben aus o.g. Grund gleichzeitig auch schade, dass er es
> gemacht hat.
Da hat dich kritisiert und nicht Johannes ...

von Fpgakuechle K. (fpgakuechle) Benutzerseite


Lesenswert?

IMHO wird hier auch ein konzeptuelles Problem sichtbar, das 
SPI-Peripheral wird nicht übern einen Treiber angesprochen (als mit dem 
Treiberfunktionen Config, read,write) sondern wie ein Speicherobjekt 
über Con- und Destruktoren.

Ein sauber geschriebener Treiber testet beim config ab, ob überhaupt die 
kompatible Hardware vorliegt (HardwareID o.ä. auslesen) und meldet das 
Ergebnis der Prüfung mit einem Returnwert zurück.

PS:
@Moderator: Da es offensichtlich kein Compiler-Problem war, sollt man 
diesen Thread in die passende Gruppe: 
https://www.mikrocontroller.net/forum/mikrocontroller-elektronik 
verschieben

von Wilhelm M. (wimalopaan)


Lesenswert?

Fpgakuechle K. schrieb:
> IMHO wird hier auch ein konzeptuelles Problem sichtbar, das
> SPI-Peripheral wird nicht übern einen Treiber angesprochen (als mit dem
> Treiberfunktionen Config, read,write) sondern wie ein Speicherobjekt
> über Con- und Destruktoren.

Das Problem liegt m.E. auch an anderer Stelle wie schon oft hier gesagt: 
werden Laufzeitobjekte benutzt für HW-Abstraktionen, müssten sie alle 
als Monostate geschrieben werden. Fehler können erst zur Laufzeit 
entdeckt werden.

Fast alle Abstraktionen von Peripherie sollte m.E. durch statische 
Instanziierung (in C++ aka template-Instanziierung) durchgeführt werden. 
So können alle Prüfungen bzgl. der HW schon zur Compilezeit ausgeführt 
werden. Dies ist m.E. beim Arduino-SW-Framework im Ansatz falsch.

> Ein sauber geschriebener Treiber testet beim config ab, ob überhaupt die
> kompatible Hardware vorliegt (HardwareID o.ä. auslesen) und meldet das
> Ergebnis der Prüfung mit einem Returnwert zurück.

Genau, und das bitte zur Compilezeit. Das geht in C++ durch 
Meta-Funktionen bzw. durch immediate-functions zur Compilezeit. Damit 
spart man sich sehr(!) viel Debugging auf der Zielplattform.

von Johannes S. (jojos)


Lesenswert?

das ist schon traurig hier das man sich rechtfertigen muss geholfen zu 
haben.
Wenn man zu einem Thema nicht helfen will oder kann, dann einfach mal 
die Fresse halten, frei nach Nuhr. Das macht die Threads übersichtlicher 
als wenn jeder schreibt das er etwas nicht will oder kann.
Die Diskussion um das Arduino API ist da genauso müssig, das ist 
mittlerweile über 10 Jahre alt. Es ist einfach gestrickt und aus 
Processing entstanden das bewusst auf OO verzichtet hatte. Es ist auf 
viele Plattformen portiert worden, also benutzen 'as is' oder nicht.
Die Konfiguration der SPI halte ich auch für kompliziert gelöst, das 
könnte der Autor dieses Arduino Core vielleicht etwas vereinfachen, da 
hänge ich mich aber nicht rein. Es ging nur darum zu sehen ob es ein gcc 
oder Code Problem war, das ist ja nun geklärt. Mit dem Testcode und den 
verwendeten Versionen hatte der TO alle Informationen geliefert um das 
Problem nachzuvollziehen. Sogar mit dem Tablet auf der Couch beim 
Fußball gucken.

: Bearbeitet durch User
von mh (Gast)


Lesenswert?

Johannes S. schrieb:
> das ist schon traurig hier das man sich rechtfertigen muss geholfen zu
> haben.
Du kannst das gerne weiterhin behaupten, dadurch wird es nicht wahr. 
Johannes muss sich nicht rechtfertigen und wurde nicht kritisiert. Es 
sieht langsam so aus, als würdest du alle Kritik auf ihn ablenken wollen 
;-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ich frag mich ja auch, wie das geforderte Minimalbeispiel hätte aussehen 
sollen. Problem war ja, dass bestimmte SFRs nicht initialisiert 
wurden, und egal wieviel und welchen Code man auch entfernt, wird sich 
daran nix ändern. Das Minimalbeispiel wäre also einfach ein leeres 
Programm gewesen...

von Oliver S. (oliverso)


Lesenswert?

Nicht ganz. Das Problem ist, daß die älteren Compiler Code erzeugen, der 
nicht ganz zufälligen Werten in die Register schreibt, der aktuelle aber 
nicht.

Oliver

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Was aber nix dran ändert, dass es kein sinnvolles Minimalbeispiel gibt.

von mh (Gast)


Lesenswert?

Johann L. schrieb:
> Ich frag mich ja auch, wie das geforderte Minimalbeispiel hätte aussehen
> sollen. Problem war ja, dass bestimmte SFRs nicht initialisiert
> wurden, und egal wieviel und welchen Code man auch entfernt, wird sich
> daran nix ändern. Das Minimalbeispiel wäre also einfach ein leeres
> Programm gewesen...

Das Minimalbeispiel ist der Konstruktoraufruf, der das Register nicht 
setzt, das er setzen sollte.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Man muss den Fehler also schon kennen, um das "Minimalbeispiel" zu 
konstruieren.

von mh (Gast)


Lesenswert?

Johann L. schrieb:
> Man muss den Fehler also schon kennen, um das "Minimalbeispiel" zu
> konstruieren.

Nein, man erreicht diesen Punkt, wenn man den existierenden Code 
rediziert. Der TO wusste schon im ursprünglichen Beitrag, dass die 
SPI-Register nicht wie erwartet gesetzt werden wie erwartet. Der erste 
Schritt sollte also sein alles rauszuwerfen, was nicht "Register setzen" 
ist. In diesem Fall ist dazu wohl der Aufruf dieses Konstruktors nötig.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

ich melde mich doch nochmal zu Wort.

> Der erste Schritt sollte also sein alles rauszuwerfen, was nicht "Register
> setzen" ist. In diesem Fall ist dazu wohl der Aufruf dieses Konstruktors
> nötig.

Genau das hatte ich gemacht indem ich die config() Methode nicht 
aufgerufen habe innerhalb der begin() Methode. Ohne config() passte 
alles. Das Problem hatte also mit der config() Methode und der Klasse 
SPISettingsMegaAVR zu tun. Hatte ich beschrieben. Und genau ab dem Punkt 
kam ich nicht weiter. Tja und dann muss es ja erlaubt sein im Forum zu 
fragen.

Hätte ich einfach geschrieben "Geht nicht, wer kümmert sich darum?" 
hätte ich die Aufregung verstanden. Aber so war es ja nicht.

mh ich empfehle dir einfach mal weniger aufplustern. Man muss nicht 
immer perfekt sein.

von Nop (Gast)


Lesenswert?

Wilhelm M. schrieb:
> Fpgakuechle K. schrieb:

>> Ein sauber geschriebener Treiber testet beim config ab, ob überhaupt die
>> kompatible Hardware vorliegt (HardwareID o.ä. auslesen) und meldet das
>> Ergebnis der Prüfung mit einem Returnwert zurück.
>
> Genau, und das bitte zur Compilezeit. Das geht in C++

Wenn der Code diese Information erst zur Laufzeit erhält, also welche 
Chips physisch verbaut sind, liegt das zur Compilezeit nichtmal vor. Für 
eine funktionierende Glaskugel wären die Lottozahlen von nächster Woche 
die naheliegendere Anwendung.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

ne ne, dass ist schon zur Compilezeit möglich, da muss ich Wilhelm und 
Fpgakuechle schon recht geben. Nur muss man das für sich selbst 
schreiben. Arduino wird das nicht mehr bei sich ändern. Dafür ist das 
Gesamtbauwerk schon zu weit fortgeschritten über die Jahre. Das würde 
einer kompletten Neuprogrammierung gleichkommen. Mit dem Rattenschwanz 
der da dranhängt.

: Bearbeitet durch User
von Nop (Gast)


Lesenswert?

Veit D. schrieb:

> ne ne, dass ist schon zur Compilezeit möglich

Hardware-ID auslesen ist zur Compilezeit nicht möglich, weil die 
Information nicht vorliegt. Genau das ist aber der Sinn eines Treibers 
mit so einer Fähigkeit.

Was man natürlich machen kann, ist die Firmware für die 
unterschiedlichen Versionen des PCB zu bauen und dann mehrere Hexfiles 
zu haben.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

okay, ich hatte beim lesen HardwareID schon mit Controller define für 
mich korrigiert. Das wäre zur Compilezeit möglich. Eine echte HardwareID 
Auswertung ist natürlich nur zur Laufzeit möglich. Da muss ich dir 
wiederum zustimmen.

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]
  • [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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.