Feld aus Festwerten im Programmspeicher

Moderator Persönliche Seite #7955251
Lesenswert?

Daniel S. schrieb:

Die Frage sollte wohl auch eher lauten welcher compiler da werkelt...oder?

Nein.

Der Compiler wird in diesen Fällen eh immer GCC sein.

In C hat Johann aber __flash implementiert; damit kannst du Daten im Flash ohne weitere Umstände direkt benutzen. Der Compiler puzzelt für dich beim Zugriff aus, ob er das via LPM machen muss oder einen der anderen LP*-Befehle, ohne dass du den Zugriff in besondere Makro-Aufrufe kapseln musst.

Bei C++ gab es zumindest lange Zeit eine Tendenz, die zugrunde liegenden Prinzipien (type qualifier) nicht haben zu wollen, weshalb das dort trotz gleichen Compilers nicht implementiert ist. Ich bin mir nicht ganz sicher, ob das inzwischen sogar möglich wäre.

Persönliche Seite #7955257
Lesenswert?

Arduino F. schrieb:

Aber *.c bleiben *.c und werden auch als C kompiliert.

Nö. g++ main.c ... übersetzt als C++ weil der C++ Compiler cc1plus aufgerufen wird. Guckst du

g++ -v main.c ... | grep cc1

Damit main.c als C übersetzt wird braucht's explizit

g++ -x c main.c ...

Jörg W. schrieb:

Bei C++ gab es zumindest lange Zeit eine Tendenz, die zugrunde liegenden Prinzipien (type qualifier) nicht haben zu wollen, weshalb das dort trotz gleichen Compilers nicht implementiert ist. Ich bin mir nicht ganz sicher, ob das inzwischen sogar möglich wäre.

Möglich wäre es, GCC ist ja nur Software. Die Frage ist nur, ob 1) das jemand wirklich implementieren will und 2) ob die Maintainer das haben wollen. clang kann's ja auch: Das dortige address_space Attribut agiert nämlich wie ein Qualifier.

Wobei soweit ich weiß clang nur 16-Bit Address-Spaces hat, also weder __memx noch __flashx.

: Bearbeitet durch User
(Firma: Gast) #7955276
Lesenswert?

Johann L. schrieb:

Nö.

Einspruch!

xy.ino:

1
// total leer

main.c:

1
#include <arduino.h>
2

3
const uint8_t __flash test[2]={1,2};
4

5
int main()
6
{
7
  return test[0] + test[1];
8
}

Beide Dateien in einem Ordner, übersetzt ohne Fehler!

Der Aufruf:

1
"E:\\Programme\\arduino\\portable\\avr-gcc\\avr-gcc-15.2.0_mingw32_binutils2.45_avrLibc2.2.1\\bin\\avr-g++" -c -g -Os -w -std=gnu++23 -fno-exceptions -fpermissive -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10819 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -fmodules -Wall -Wextra -Wno-volatile -isystem "E:\\Programme\\arduino\\portable\\avr-libstdcpp2\\include" "-IE:\\Programme\\arduino\\portable\\packages\\arduino\\hardware\\avr\\1.8.6\\cores\\arduino" "-IE:\\Programme\\arduino\\portable\\packages\\arduino\\hardware\\avr\\1.8.6\\variants\\standard" "E:\\temp\\Arduino\\sketch\\main.c" -o nul

Interessant!

Natürlich sehe ich das -std=gnu++23 und auch das -x c++

Lasse ich das const in der main.c weg meldet es:

1
main.c:3:18: error: variable 'test' must be const in order to be put into read-only section by means of '__flash'
2
    3 |  uint8_t __flash test[2]={1,2};
3
      |                  ^~~~

Was auf jeden fall so richtig ist.

Ändere ich die Endung auf main.cpp kommt folgende Meldung:

1
main.cpp:3:23: error: expected initializer before 'test'
2
    3 | const uint8_t __flash test[2]={1,2};
3
      |                       ^~~~

Und jetzt du! Wie kommt es, dass in der *.c kein Fehler geworfen wird, wenn sich da ein __flash befindet. Und natürlich auch funktioniert, denn das habe ich vorher schon ein paar mal verwendet. Ich weiß es nicht.

: Bearbeitet durch User
(Firma: Gast) #7955348
Lesenswert?

Johann L. schrieb:

Und wie ist da __flash definiert / implementiert?

Gar nicht! Wird da nur für das uint8_t gebraucht. (könnte man auch anders erreichen)

Johann L. schrieb:

Wenn du avr-g++ simple.c -v 2>&1 | grep cc1

Kein linux, kein grep

Johann L. schrieb:

Keine Ahnung was Arduino da macht.

Dürfte mit Arduino nix zu tun haben. Der Compiler ist nachträglich eingebunden. Arduino dümpelt noch bei GCC 7.3 oder so, und C++11 Ich nutze Gcc 15.2 mit C++23 mit der IDE

Die gezeigte Zeile ist die einzige, in der main.c vorkommt.

Johann L. schrieb:

TUs

Aha... Was ist das? Kenne mindestens 10 TU Dinger, glaube aber, du meinst was anderes.

: Bearbeitet durch User
Persönliche Seite #7955512
Lesenswert?

Arduino F. schrieb:

Johann L. schrieb:

Wenn du avr-g++ simple.c -v 2>&1 | grep cc1

Kein linux, kein grep

Dann halt

1
avr-g++ simple.c -v

und du musst eben selber nach "cc1" suchen weil du nicht danach filtern kannst.

Johann L. schrieb:

Keine Ahnung was Arduino da macht.

Dürfte mit Arduino nix zu tun haben. Der Compiler ist nachträglich eingebunden. Arduino dümpelt noch bei GCC 7.3 oder so, und C++11 Ich nutze Gcc 15.2 mit C++23 mit der IDE

GCC verhält sich konsistent; das Verhalten ändert sich ja nicht in jeder Version. GCC 5 macht das gleiche wie GCC 15:

"g++ main.c" übersetzt als C++. Um das als C zu übersetzen brauch man "gcc main.c" oder "g++ -x c main.c".

Die gezeigte Zeile ist die einzige, in der main.c vorkommt.

Das Kommando compiliert nicht sondern präprozessiert lediglich, weil -E angegeben ist!

Du hast den COMPILERaufruf für main.c also noch nicht gefunden...

(Firma: Gast) #7955526
Lesenswert?

Johann L. schrieb:

Du hast den COMPILERaufruf für main.c also noch nicht gefunden...

Noch mal nachgesehen. Du hast wahr. Ist mir gestern durch die Lappen gegangen.

1
"E:\\Programme\\arduino\\portable\\avr-gcc\\avr-gcc-15.2.0_mingw32_binutils2.45_avrLibc2.2.1\\bin\\avr-gcc" -c -g -Os -Wall -Wextra -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10819 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IE:\\Programme\\arduino\\portable\\packages\\arduino\\hardware\\avr\\1.8.6\\cores\\arduino" "-IE:\\Programme\\arduino\\portable\\packages\\arduino\\hardware\\avr\\1.8.6\\variants\\standard" "E:\\temp\\Arduino\\sketch\\main.c" -o "E:\\temp\\Arduino\\sketch\\main.c.o"

Johann L. schrieb:

Nö. g++ main.c ... übersetzt als C++ weil der C++ Compiler cc1plus aufgerufen wird.

Damit hast auch du dich geirrt.

Jörg W. schrieb:

Wenn du etwas mehr zitiert hättest, wäre dir wohl aufgefallen, dass es in diesem Zusammen nur "translation unit" heißen kann.

Ein seltsamer Vorwurf... Anständig wäre: Die erste Verwendung einer Abkürzung mit einer Erklärung versehen. Merke: Lesen und verstehen, klappt manchmal. Zitieren ist eine andere Baustelle. Dass es deine TU ist, die da fehlt, ist mit nicht in den Sinn gekommen, da ja die main.c.o Datei klar vor meinen Augen liegt. Also im Endeffekt doch eine TU vorhanden.

Persönliche Seite #7955552
Lesenswert?

Arduino F. schrieb:

Johann L. schrieb:

Nö. g++ main.c ... übersetzt als C++ weil der C++ Compiler cc1plus aufgerufen wird.

Damit hast auch du dich geirrt.

Wieso? Hast du ein Gegenbeispiel?

Noch mal nachgesehen. Du hast wahr. Ist mir gestern durch die Lappen gegangen. ...avr-gcc -c ... main.c -o ...main.c.o

Also wird gcc verwendet, nicht g++.

Und mithin nicht automatisch Arduino = C++.

: Bearbeitet durch User
(Firma: Gast) #7955625
Lesenswert?

Johann L. schrieb:

Und mithin nicht automatisch Arduino = C++.

Richtig! Viel von dem Basis Kram steckt in *.c Dateien, und wird auch so übersetzt. Weniges steckt in *.S Dateien, also Assembler. Der Rest, wie *.ino, Print, Serial und quasi alle Libraries sind C++

Aus dem 3er Pool, an Sprachen, kann man sich jeweils das raus suchen, was einem am besten schmeckt.

#7956667
Lesenswert?

Wastl schrieb:

Ist in den ersten Beiträgen besprochen worden. Bist du zu faul

Das Problem ist, dass die "Besserwisser" jede Antwort zerreden, auch wenn sie völlig richtig war.

Es hat einen guten Grund, warum Arduino weiterhin auf das PROGMEM Makro setzt: Es funktioniert auf allen von Arduino unterstützten Plattformen ebenso, da es dort komoatibel implementiert wurde.

(Firma: Gast) #7956682
Lesenswert?

Nemopuk schrieb:

"Besserwisser"

Du meinst dich?

Nemopuk schrieb:

Es funktioniert auf allen von Arduino unterstützten Plattformen ebenso, da es dort komoatibel implementiert wurde.

Es ist auf allen Plattformen völlig Sinnfrei, außer AVR.

Zu "komoatibel": Ja, man muss schon nahe am Koma sein, um Progmem auf ARM usw. nutzen zu wollen. Es ist eine reine AVR Krücke. Und selbst da gibt es mit dem __flash in C eine Abhilfe.

#7956698
Lesenswert?

Arduino F. schrieb:

In *.cpp oder *.ino nicht.

okay, also im *.ino gehts also gar nicht - okay.

Wastl schrieb:

Bist du zu faul die paar Beiträge dieses Threads zu lesen?

Ja, ich bin sehr faul.

Nemopuk schrieb:

Es funktioniert auf allen von Arduino unterstützten Plattformen

Also im *.ino dann doch?

Arduino F. schrieb:

nahe am Koma sein, um Progmem auf ARM usw. nutzen zu wollen.

Also doch nicht im *.ino?

@Wastl: merkst de wat?

Arduino F. schrieb:

Ja, man muss schon nahe am Koma sein...

Mir ist das völlig egal wie das intern gelöst ist, Hauptsache es geht - kann ich ja sowieso wohl eher nichts dran ändern...

Random .. schrieb:

Warum landet hier eigentlich "const" ohne weitere Krücken nicht automagisch im Flash? Bin das vom armcc so gewöhnt.

Das war auch zu meinen AVR-Studio Zeiten mal eine Frage von mir - fände es auch "logischer" aber der Hintergrund von const geht wohl nicht soweit - checkt nur ob es Zugriffe gibt, welche die Variable verändern, nicht wo sie wie abgelegt ist - hoffe habe das richtig ausgedrückt mit meinem eher laienhaften Wissen an der Stelle...

: Bearbeitet durch User
(Firma: Gast) #7956705
Lesenswert?

Thorsten S. schrieb:

okay, also im *.ino gehts also gar nicht - okay.

Die PROGMEM Geschichte geht, auch auf AVR Arduino in *.ino oder *.cpp die __flash Geschichte nur in *.c Dateien.

Random .. schrieb:

Warum landet hier eigentlich "const" ohne weitere Krücken nicht automagisch im Flash? Bin das vom armcc so gewöhnt.

ARM hat nur einen Adressbus. AVR hat 2 Adressbusse. Darum der "Sonderzugriff" AVR ist halt mehr Harvard als ARM https://de.wikipedia.org/wiki/Harvard-Architektur

: Bearbeitet durch User
#7956707
Lesenswert?

Arduino F. schrieb:

Die PROGMEM Geschichte geht

Danke, okay - wie muss ich denn die Headerdatei einbinden:

#include <avr/pgmspace.h>

bzw. gibt es die dort überhaupt oder heißt sie andern?

Arduino F. schrieb:

AVR ist halt mehr Harvard als ARM

Habe früher mit PICs in Assembler gearbeitet, dort wird alles mit Takt/4 betrieben. Als ich mit den AVR anfing, war ich überrascht dass sie das Hiolen von zwei Operaden, deren Addition und die Ablage des Ergebnisses in einem Haupttakt schaffen... Wahnsinn, wenn man vorher mit PICs gearbeitet hat...

: Bearbeitet durch User
#7956785
Lesenswert?

Thorsten S. schrieb:

in einem Haupttakt schaffe

Es war mir eh ein Rätsel, wie man das Holen von Operanden in einem Takt schafft, man muss ja eine Adresse auf den Bus legen, an den Speicher anlegen, der Wert der Zelle muss auch auf den Datenbus und dann in die Arbeitsregister der ALU usw... das geht ja dann alles nur mit einer Taktvervielfäligung. Wenn man also den Atmega mit einem 20 Mhz Quarz bestückt, muss er intern schon mit 80 Mhz arbeiten...

https://microcontrollerslab.com/wp-content/uploads/2017/05/pic-microocntroller-architecture-block-diagram.gif

https://www-user.tu-chemnitz.de/~heha/hs/chm/ATmegaX8.chm/7.htm

Dazu kommt das Problem, dass man beim PIC alles erstmal über das W-Register bewegen muss - im Gegensatz zum AVR noch ein gravierender Leistungsnachteil... warum auch immer man das beim PIC so macht/gemacht hat - eine Zeile Assembler im AVR entspricht damit nochmals schnell min. vier Zeilen Assembler beim PIC...

Aber das ist ein anderes Thema...

: Bearbeitet durch User
#7956799
Lesenswert?

Thorsten S. schrieb:

Es war mir eh ein Rätsel, wie man das Holen von Operanden in einem Takt schafft, man muss ja eine Adresse auf den Bus legen, an den Speicher anlegen, der Wert der Zelle muss auch auf den Datenbus und dann in die Arbeitsregister der ALU usw... das geht ja dann alles nur mit einer Taktvervielfäligung.

Sieh Dir mal einen 6502 an. Der kann in einem Takt ein Operand aus dem Speicher in ein Register laden. In der ersten Hälfte des Takts wird die Adresse auf den Bus gelegt und in der zweiten Hälfte des Takts der vom Speicherbaustein an den Datenleitungen angelegte Wert übernommen.

Da braucht es keine Taktvervielfältigung.

Und das ist der Grund, warum ein mit 1 MHz getakteter 6502 geschwindigkeitsmäßig mit einem mit 4 MHz getaktetem Z80 vergleichbar war - letzterer zerlegte einen Buszyklus in mehrere Takte.

Persönliche Seite #7956817
Lesenswert?

Thorsten S. schrieb:

Es war mir eh ein Rätsel, wie man das Holen von Operanden in einem Takt schafft, man muss ja eine Adresse auf den Bus legen, an den Speicher anlegen, der Wert der Zelle muss auch auf den Datenbus und dann in die Arbeitsregister der ALU usw... das geht ja dann alles nur mit einer Taktvervielfäligung. Wenn man also den Atmega mit einem 20 Mhz Quarz bestückt, muss er intern schon mit 80 Mhz arbeiten...

AVRs haben eine 2-stufige Pipeline. In Stage 1 geschieht Instruction-Fetch, in Stage 2 Execute

1
Takt1  Takt2  Takt3 ...
2
Fetch1 Exec1
3
       Fetch2 Exec2  ...
4
              Fetch3 ...
#7956832
Lesenswert?

Johann L. schrieb:

In Stage 1 geschieht Instruction-Fetch, in Stage 2 Execute

Ach so geht das... jau, daran habe ich gar nicht gedacht...wieder was gelernt.

Aber auch die mehrfachen Arbeitsregister und das diese direkt für beide Eingänge der ALU greifbar sind, sind ein wesentlicher Vorteil...

Die Anordnung im PIC ist dagegen eine echte Krücke... wie ich finde.

Gibt es für diese internen Strukturen eigentlich irgendeine Art Fachbezeichung?

Stimmt das so:

Ein-Adress-Architektur / PIC Zwei-Adress-Architektur Drei-Adress-Architektur / AVR

: Bearbeitet durch User
#7956995
Lesenswert?

Thorsten S. schrieb:

Wenn man also den Atmega mit einem 20 Mhz Quarz bestückt, muss er intern schon mit 80 Mhz arbeiten...

Johann L. schrieb:

AVRs haben eine 2-stufige Pipeline. In Stage 1 geschieht Instruction-Fetch, in Stage 2 Execute

Dazu kommt, das der Programmspeicher 16 Bit breit ist. Ein "Fetch" liest zwei Byte am Stück.

Eeil der AVR zwei interne Busse hat, kann zudem gleichzeitig einen Operanden aus dem RAM Laden und den nächsten Befehl aus dem Flash.

: Bearbeitet durch User
#7956999
Lesenswert?

Nemopuk schrieb:

Aber er hat halt zwei Busse

Jau, Harvard, das hat der PIC auch.

Nemopuk schrieb:

und der Programmspeicher ist zudem auch noch 16 Bit breit.

Der Mikrocode wäre interessant... aber damit geht sicher kein Hersteller hausieren...

Nemopuk schrieb:

Eeil der AVR zwei interne Busse hat, kann zudem gleichzeitig einen Operanden aus dem RAM Laden und den nächsten Befehl aus dem Flash.

Heiße Kiste

: Bearbeitet durch User
#7957023
Lesenswert?

Nemopuk schrieb:

Ich bezweifle, das AVR Mikroconde haben

Mikrocode = Befehldekoder...

Johann L. schrieb:

Vielleicht hilft ja FPGA Soft Core: AVR.

Eine witzige Idee - aber FPGAs sind nicht mein Fachgebiet, leider nie programmiert, genutzt.

In der Darstellung:

https://www-user.tu-chemnitz.de/~heha/hs/chm/ATmegaX8.chm/7.htm

Fehlt irgendwie das Pipelining, ist wohl ebenso Teil der Befehlsdekodierung...

Es müssen ja immer zwei Befehle zeitgleich dekodiert werden, da müssten dann eigentlich zwei Dekoder sein, und ggf. gibt es ja Befehle die nicht zeitgleich ausgeführt werden können, vielleicht so etwas wie eine Addition und ein Shift...da steckt richtig Schmalz in der Logik... total interessant...

Da bin ich wirklich froh, dass man diese Technik auf dem heutigen Niveau einfach für 3€ kaufen und direkt nutzen kann...auch wenn die allgemeine Ehrfurcht sicher sehr darunter leidet...

: Bearbeitet durch User
#7957025
Lesenswert?

Thorsten S. schrieb:

Mikrocode = Befehldekoder...

Nee. Microcode, wenn vorhanden, übernimmt die Aufgabe des Befehlsdecoders, aber ein Befehlsdecoder ist kein Microcode, sondern normalerweise einfach ein Gattergrab. Sieh Dir den 6502 an - der besteht aus gerade mal 4500 Transistoren ...

Microcode kann nach der Herstellung der CPU verändert werden (wie die bei Intel-CPUs mittlerweile üblichen Microcodeupdates deutlich zeigen), das Gattergrab klassischer Befehlsdecoder hingegen nicht.

Persönliche Seite #7957172
Lesenswert?

Arduino F. schrieb:

Thorsten S. schrieb:

okay, also im *.ino gehts also gar nicht - okay.

Die PROGMEM Geschichte geht, auch auf AVR Arduino in *.ino oder *.cpp die __flash Geschichte nur in *.c Dateien.

Random .. schrieb:

Warum landet hier eigentlich "const" ohne weitere Krücken nicht automagisch im Flash? Bin das vom armcc so gewöhnt.

ARM hat nur einen Adressbus. AVR hat 2 Adressbusse. Darum der "Sonderzugriff" AVR ist halt mehr Harvard als ARM https://de.wikipedia.org/wiki/Harvard-Architektur

Klar, nur sollte das nicht im Compiler lösbar sein?

#7957185
Lesenswert?

Random .. schrieb:

Klar, nur sollte das nicht im Compiler lösbar sein?

Nicht in C. Ich nehme mal wieder puts() als Beispiel.

Die puts() Funktion erwartet die Adresse des Strings im RAM, denn so ist die Funktion im C Standard spezifiziert. Um stattdessen auf FLASH zuzugreifen hat man folgende Möglichkeiten:

a) RAM und Flash lassen sich anhand unterschiedlicher Adressbereiche unterscheiden. Das haben wir bei ARM Cortex-M Controllern.

b) Man führt einen zusätzliches Funktions-argument zur Unterscheidung ein. Innerhalb der Funktion könnte dann ein if/else je nach Parameter auf RAM oder FLASH zugreifen. Dann ist es aber nicht mehr zum Standard kompatibel.

c) Man bietet eine zweite Variante der Funktion an, die auf den FLASH Speicher zugreift. Diesen Weg geht die AVR Libc: puts_P()

In C++ haben wir eine Möglichkeit mehr:

d) Wir stellen mehrere Varianten der Funktion/Methode bereit, und der Compiler wählt die passende anhand des Typs des Zeigers aus. Diesen Weg geht Arduino.

: Bearbeitet durch User
Moderator Persönliche Seite #7957195
Lesenswert?

Nemopuk schrieb:

Random .. schrieb:

Klar, nur sollte das nicht im Compiler lösbar sein?

Nicht in C.

Geht auch in C, kostet dann aber: "generic pointers", d. h. jeder Zeiger wird extra so verändert, damit er den Adressraum, zu dem er gehört, noch mit transportieren kann. Überall da, wo über den Zeiger zugegriffen wird, muss dann als erstes eine Fallunterscheidung gemacht werden.

Da sich AVR mittlerweile angesichts der Konkurrenz der 32bitter eher auf kleinere Controller konzentriert, gibt es dort dann auch tatsächlich wieder einen unified address space, mit dem es ohne weitere Umstände möglich wäre, mit nur einer einzigen Art 16-bit-Zeiger auszukommen. Aber das war historisch eben anders.

#7957230
Lesenswert?

Jörg W. schrieb:

Da sich AVR mittlerweile angesichts der Konkurrenz der 32bitter eher auf kleinere Controller konzentriert, gibt es dort dann auch tatsächlich wieder einen unified address space, mit dem es ohne weitere Umstände möglich wäre, mit nur einer einzigen Art 16-bit-Zeiger auszukommen.

Wie ist "gibt es" zu verstehen? Gibt es neue AVRs, die das so machen? Oder meintest Du "könnte es geben"?

Moderator Persönliche Seite #7957262
Lesenswert?

Harald K. schrieb:

Gibt es neue AVRs, die das so machen?

Ja, gibt es. Schau dich einfach mal um. Schon ATtiny817 und Verwandte können das, auch ATmega4809 (hier passt jeweils der komplette Flash in den Adressraum). Bei den neueren AVR-Serien (DA, DB und wie sie alle heißen) hängt es von der Flash-Größe ab: nur maximal 32 KiB Flash lassen sich in den normalen Adressraum abbilden, alles darüber hinaus ist nur traditionell zugreifbar.

Persönliche Seite #7957271
Lesenswert?

Harald K. schrieb:

Gibt es neue AVRs, die das so machen?

Ja. Siehe zum Beispiel die Tabelle in

https://avrdudes.github.io/avr-libc/avr-libc-user-manual-2.3.0/FAQ.html#faq_flashstrings

Die AVR Tools unterstüzten 97 Devices mit 100% linearem Adressraum, d.h. der komplette Programmspeicher ist per LDD/LDS erreichbar.

Außerdem werden 36 Devices unterstützt, die lediglich 32 KiB des Programmspeichers im LDD/LDS-Adressraum sehen. Auf diesen Devices liegt rodata im Flash, ist aber auf 32 KiB limitiert. (Es sei denn man verwendet -mrodata-in-ram, was rodata ins RAM lokatiert wie auf den alten Devices. In diesem Fall ist rodata nicht auf 32 KiB limitiert, und rodata kann 32 KiB Segmentgrenzen überschreiten, was mit rotata-in-flash nicht möglich ist.)

AVRs mit linearem Adressraum gibe es seit ca. 2016 mit Release der AVRrc (Reduced Core).

: Bearbeitet durch User
Persönliche Seite #7957299
Lesenswert?

Arduino F. schrieb:

Random .. schrieb:

Klar, nur sollte das nicht im Compiler lösbar sein?

Der Gcc tuts für Unmengen an Prozessoren, jeglicher Größe. AVR ist da eher ein unwichtiger Sonderfall, welcher weder vom C als auch vom C++ Standard abgehandelt wird

Die aktuelle AVR Implementation des GCC für AVR (ohne GNU-Erweiterungen) entspricht dem C/C++ Sprachstandard. (Ok, es gibt Ausnahmen die Exceptions, STL, 32-Bit double etc.)

Und die möglichen, aber nicht gewählten Implementationen, die Jörg erwähnte, wären ebenfalls kompatibel mit dem C/C++ Standard.

C/C++ spezifizeren eine abstrakte Maschine, die auf mehr als eine Weise implementiert werden kann, und dass der tatsächlich beschrittene Weg "weder vom C noch vom C++ Standard abgehandelt" wird, ist Käse.

Persönliche Seite #7957323
Lesenswert?

Harald K. schrieb:

Das bedeutet, daß auf denen der ganze "pgmspace.h"-Kram restlos entfallen kann, oder könnte.

Ja. Wobei das von den Tools unterstützt werden muss. Für die x-Series Devices zum Beispiel ab GCC 8, also seit ca. 2018. Für die Devices, die nur einen Teil des Flashs im LD-Adressraum sehen, braucht man https://sourceware.org/PR31124, also Binutils 2.42 oder neuer.

Der vom Compiler erzeugte Code ist wie gesagt der selbe.

Zum Vergleich PROGMEM vs. open-coded C/C++ ist anzumerken:

  • Mit PROGMEM / __flash muss das Z-Register verwendet werden, ohne PROGMEM hat der Compiler mehr Adressregister und -modi zur Verfügung, was sich positiv auf die Codedichte auswirken kann. Z.B. kann Indirek+Offset Adressierung verwendet werden; mit PROGMEM / __flash geht das nicht.

  • PROGMEM ist nicht transparent, open-coded C/C++ hingegen schon.

  • Teilweise ist der Code /ohne/ PROGMEM schlechter, etwa wenn man per __flash eine 64-Bit Variable liest. Das ist der Grund, warum es in der AVR-LibC Funktionen wie flash_read_u64() gibt: https://avrdudes.github.io/avr-libc/avr-libc-user-manual-2.3.0/group__avr__flash.html#ga368f51c58ca62b924e33046666512d92

(AVR-LibC 2.3 ist noch nicht released)

Arduino F. schrieb:

Johann L. schrieb:

"weder vom C noch vom C++ Standard abgehandelt" wird, ist Käse.

C als auch C++ gehen von einem linear adressierten Speicher aus.

Und das ist genau das, was die AVR Tools implementieren. Nicht optimal, aber Optimalität ist keine C/C++ Anforderung.

: Bearbeitet durch User

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren