Forum: Mikrocontroller und Digitale Elektronik Feld aus Festwerten im Programmspeicher


von Daniel S. (supernova01)


Lesenswert?

Nabend,

wie war noch die Formulierung wenn ich ein Feld aus Festwerten nicht im 
RAM beim Atmega haben möchte sondern im Programmspeicher?

uint8_t Feld[10];

Finde das gerade so ad hoc nicht.

Danke

: Bearbeitet durch User
von Georg M. (g_m)


Lesenswert?


von Daniel S. (supernova01)


Lesenswert?

PROGMEM - genau, so wars. Danke.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Daniel S. schrieb:
> Finde das gerade so ad hoc nicht.

C, oder C++?

Wenn C, dann: __flash
uint8_t __flash Feld[10];

Ist bequemer, als der Alte, bzw. der C++ Weg über PROGMEM.

von Daniel S. (supernova01)


Lesenswert?

c

bin aber gerade aufm arduino am rödeln...

von Harald K. (kirnbichler)


Lesenswert?

Daniel S. schrieb:
> bin aber gerade aufm arduino am rödeln

Arduino ist C++, nicht C.

von Daniel S. (supernova01)


Lesenswert?

jo,  Ich programmiere in c aufm arduino.

von Harald K. (kirnbichler)


Lesenswert?

Daniel S. schrieb:
> jo,  Ich programmiere in c aufm arduino.

Sicher? Nutzt Du die Arduino-IDE und das ganze zugehörige Zeug? Dann 
glaubst Du nur, in C zu programmieren.

von Daniel S. (supernova01)


Lesenswert?

Ja, ich glaube es nur. Die Frage sollte wohl auch eher lauten welcher 
compiler da werkelt...oder?

Arduino F. schrieb:
> Wenn C, dann: __flash

Das

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

geht in der IDE jedenfalls nicht. Ist ja aber auch die Arduino IDE.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Daniel S. schrieb:
> Ist ja aber auch die Arduino IDE.

Die setzt auf C++ auf, auch wenn es manchmal nicht danach aussieht.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Harald K. schrieb:
> Sicher? Nutzt Du die Arduino-IDE und das ganze zugehörige Zeug? Dann
> glaubst Du nur, in C zu programmieren.
*.ino Dateien werden zu *.cpp umgebaut.
Aber *.c bleiben *.c und werden auch als C kompiliert.

Daniel S. schrieb:
> geht in der IDE jedenfalls nicht.
Doch geht, wenn man will.
Spätestens nach einem Compiler update.

von Johann L. (gjlayde) Benutzerseite


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
von Arduino F. (Firma: Gast) (arduinof)


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
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Arduino F. schrieb:
> #include <arduino.h>

Und wie ist da __flash definiert / implementiert?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Arduino F. schrieb:
> Der Aufruf:

Da wird doch garnichts übersetzt, d.h. da sind keine TUs angegeben?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Keine Ahnung was Arduino da macht.

Wenn du
1
avr-g++ simple.c -v 2>&1 | grep cc1
Ist die Ausgabe:
1
$prefix/bin/../libexec/gcc/$target/$version/cc1plus -quiet -v -iprefix $prefix/../lib/gcc/$target/$version/ simple.c ...
Oder kommt bei dir cc1 statt cc1plus?

von Arduino F. (Firma: Gast) (arduinof)


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
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Arduino F. schrieb:
>> TUs
>
> Aha...
> Was ist das?

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

von Rainer W. (rawi)


Lesenswert?

Was hat diese Compiler- und IDE Diskussion mit Mikrocontrollern zu tun?

Bitte verschieben!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Rainer W. schrieb:
> Was hat diese Compiler- und IDE Diskussion mit Mikrocontrollern zu tun?

Dass named address spaces (um diese geht es letztlich) vorrangig etwas 
für den Anwendungsfall "Mikrocontroller" sind.  Bei einem Compiler für 
einen PC braucht man das nicht.

: Bearbeitet durch Moderator
von Johann L. (gjlayde) Benutzerseite


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

von Arduino F. (Firma: Gast) (arduinof)


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.

von Johann L. (gjlayde) Benutzerseite


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
von Arduino F. (Firma: Gast) (arduinof)


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.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Johann L. schrieb:
> Arduino F. schrieb:
>> Aber *.c bleiben *.c und werden auch als C kompiliert.
>
> Nö.

Johann L. schrieb:
> Wieso? Hast du ein Gegenbeispiel?
Das "Nö" ist an der Stelle falsch.
Ein Gegenbeispiel habe ich geliefert, wenn auch etwas holperig.

von Thorsten S. (whitejack)


Lesenswert?

Hallo,

wie ist das denn nun auf dem Arduino zu machen, das wäre auch für mich 
mal interessant, oder geht es dort gar nicht?

Ich stecke in diesem speziellen Thema kaum drin, und verstehe hier nur 
sehr wenig von der Materie - arbeite aber ab und an auch mit dem Arduino 
Zeug ...

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Thorsten S. schrieb:
> wie ist das denn nun auf dem Arduino zu machen,

In *.c Dateien, ja.
In *.cpp oder *.ino nicht.

Thorsten S. schrieb:
> oder geht es dort gar nicht?

Den Beweis, dass es geht habe ich geliefert.

: Bearbeitet durch User
von Wastl (hartundweichware)


Lesenswert?

Thorsten S. schrieb:
> wie ist das denn nun auf dem Arduino zu machen

Ist in den ersten Beiträgen besprochen worden. Bist du zu
faul die paar Beiträge dieses Threads zu lesen?

von Nemopuk (nemopuk)


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.

von Arduino F. (Firma: Gast) (arduinof)


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.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

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

von Thorsten S. (whitejack)


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
von Arduino F. (Firma: Gast) (arduinof)


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
von Thorsten S. (whitejack)


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
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Thorsten S. schrieb:
> bzw. gibt es die dort überhaupt oder heißt sie andern?

Was soll die Frage?
Über welchen µC redest du da?

von Nemopuk (nemopuk)


Lesenswert?

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

Weil man mit anderen Befehlen auf den Flash zugreifen muss. puts() kann 
z.B. nur Strings aus dem RAM ausgeben.

von Nemopuk (nemopuk)


Lesenswert?

Thorsten S. schrieb:
> #include <avr/pgmspace.h>
> bzw. gibt es die dort überhaupt oder heißt sie andern?

Mal ein ganz schräger Vorschlag: Lies die Doku von Arduino!

https://docs.arduino.cc/language-reference/de/variablen/utilities/PROGMEM/

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Random .. schrieb:
> Warum landet hier eigentlich "const" ohne weitere Krücken nicht
> automagisch im Flash?

Eine Erklärung fundes sich zum Beispiel in der AVR-LibC FAQ:

Why do all my string literals eat up the SRAM?

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

von Thorsten S. (whitejack)


Lesenswert?

Arduino F. schrieb:
> Was soll die Frage?

Es ging nicht, ich hatte immer eine Fehlermeldung das "Progmem" 
unbekannt ist, dachte ich.

Nemopuk schrieb:
> Mal ein ganz schräger Vorschlag: Lies die Doku von Arduino!

Der Fehler lag zwischen meinen Ohren, dich hatte das "const" vergessen.

Danke Euch, für die Geduld.

von Thorsten S. (whitejack)


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
von Harald K. (kirnbichler)


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.

von Johann L. (gjlayde) Benutzerseite


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

von Thorsten S. (whitejack)


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
von Nemopuk (nemopuk)


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
von Thorsten S. (whitejack)


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
von Nemopuk (nemopuk)


Lesenswert?

Thorsten S. schrieb:
> Der Mikrocode wäre interessant..

Ich bezweifle, das AVR Mikroconde haben. Wenn sie welchen haben, dann 
höchstens für das Beschrieben des Flash Speichers.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Thorsten S. schrieb:
> Der Mikrocode wäre interessant...

Vielleicht hilft ja FPGA Soft Core: AVR.  Ist aber immer noch die 
Frage, ob eine FPGA-Implementierung analog zu einem echten AVR ist.

von Thorsten S. (whitejack)


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
von Harald K. (kirnbichler)


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.

von Random .. (thorstendb) Benutzerseite


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?

von Nemopuk (nemopuk)


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
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Harald K. (kirnbichler)


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"?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Johann L. (gjlayde) Benutzerseite


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
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Nemopuk schrieb:
> 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.

Naja, braucht dann aber Inline Asm; in C++ die einzige Möglichkeit, ein 
LPM zu bekommen.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Random .. schrieb:
> Klar, nur sollte das nicht im Compiler lösbar sein?

Wunsch und Realität gehen manchmal auseinander.
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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Arduino F. schrieb:
> welcher weder vom C als auch vom C++ Standard abgehandelt wird

Ich glaube mich zu erinnern, dass named address spaces in C zumindest 
vorgeschlagen wurden (N3723). Hab's aber nicht verfolgt. Autor ist (wen 
wundert's :) Philip Klaus Krause, Maintainer des SDCC.

von Johann L. (gjlayde) Benutzerseite


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.

von Harald K. (kirnbichler)


Lesenswert?

Jörg W. schrieb:
> Ja, gibt es. Schau dich einfach mal um.

Johann L. schrieb:
> Ja. Siehe zum Beispiel die Tabelle ...

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

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

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.
Die AVR spezifische Flash Abhandlung ist nicht im Sprachstandard 
behandelt.

von Johann L. (gjlayde) Benutzerseite


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
von Harald K. (kirnbichler)


Lesenswert?

Danke für die weiteren Hintergrundinformationen.

Johann L. schrieb:
> open-coded

?

Meinst Du damit "ganz normal"?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Harald K. schrieb:
> Meinst Du damit "ganz normal"?

Ja.

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.