Forum: Compiler & IDEs __flash Äquivalent fürs EEPROM


von bal (Gast)


Lesenswert?

Hallo,

Seit 4.7.0 kennt avr-gcc ja das Schlüsselwort "__flash", was den Umgang 
mit Daten im Flash stark vereinfacht.
Davor musste man ja den Zugriff über verschiedene Funktionen regeln.

Ich habe auf die schnelle nichts dazu gefunden.
Gibt es so ein Äquivalent eigentlich auch für Daten im EEPROM?

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


Lesenswert?

bal schrieb:
> Gibt es so ein Äquivalent eigentlich auch für Daten im EEPROM?

Scheint Johann nicht implementiert zu haben.  Da das Framework für
die named address spaces jetzt da ist, wäre das ja vielleicht mal
eine Übung für einen Compiler-Einsteiger. :-)

von bal (Gast)


Lesenswert?

Ok, hab ich mir gedacht, aber ist ja auch nicht so tragisch :-)

Noch eine Frage zu EEMEM:
dadurch landet die Variable ja im EEPROM. Der Zugriff darauf erfolgt 
allerdings durch Funktionen.

Angenommen ich ändere jetzt recht viel im Programm, sprich: neue 
c-Dateien kommen hinzu, die wiederum EEMEM-Werte beinhalten.

Kann es denn vorkommen, dass sich die Adressen im EEPROM ändern? Nach 
einer großen Änderung und einem BUILD-ALL kann ja der Linker nicht mehr 
wissen,
wo er eine Variable beim letzten Compilerlauf hingelegt hat.

Wenn ich danach mein Programm flashe (ohne eep-Datei) dann kann es doch 
zu Inkonsistenzen kommen, weil vielleicht "foo" dort liegt wo letztesmal 
noch "bar" lag.

Oder wird das irgendwie verhindert?

von Karl H. (kbuchegg)


Lesenswert?

bal schrieb:

> Kann es denn vorkommen, dass sich die Adressen im EEPROM ändern?

Ja, kann.

> Nach
> einer großen Änderung und einem BUILD-ALL kann ja der Linker nicht mehr
> wissen,
> wo er eine Variable beim letzten Compilerlauf hingelegt hat.

Du sagst es.

> Oder wird das irgendwie verhindert?

Nö.
Ist dein Bier.

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


Lesenswert?

Karl Heinz Buchegger schrieb:
> Ist dein Bier.

Kann man dadurch umgehen, dass man genau eine große struct anlegt
im EEPROM, in der man alles ablegt.  Wenn man diese später am Ende
erweitert, bleiben die bereits existierenden Daten an Ort und Stelle.

von bal (Gast)


Lesenswert?

Ja so kenn ichs auch, bzw hab ich schonmal auf einer anderen Plattform 
so gehandhabt.

Da war das EEPROM aber über SPI angebunden, also eh komplett "am 
Compiler vorbei", deswegen war ich mir hier nicht sicher.

Danke!

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

Entweder du kümmerst dich selber darum, wie und wo die Daten im EPROM 
abgelegt werden oder lässt es den Compiler machen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> bal schrieb:
>> Gibt es so ein Äquivalent eigentlich auch für Daten im EEPROM?
>
> Scheint Johann nicht implementiert zu haben.

Das gehört m.E. auch nicht in den Compiler, denn es würde viel zu viel 
explizites Wissen über das Derivat erfordern.  Oder eine weitere 
Verzahnung mit der AVR-LibC, was pronzipiell nicht wünschenswert ist.

Momentan sind Address Spaces (ISO/IEC TR 18037 Annex B.1.2) nicht 
vollständig im GCC umgesetzt, es fehlen nämlich die User Defined AS 
mit denen aus Applikationsebene neue AS eingeführt werden. Die 
Zugriffsfunktionen implementiert dabei ebenfalls die Anwendung.

Diese User Defined AS in GCC einzubauen ist allerdings keine 
Anfängerübung...

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


Lesenswert?

Johann L. schrieb:
> Das gehört m.E. auch nicht in den Compiler, denn es würde viel zu viel
> explizites Wissen über das Derivat erfordern.  Oder eine weitere
> Verzahnung mit der AVR-LibC, was pronzipiell nicht wünschenswert ist.

Naja, man könnte sich auf Funktionen wie __avr_eeprom_read_byte und
__avr_eeprom_write_byte stützen, dies so dokumentieren und es dann
dem Endanwender überlassen, auf welchem Wege er diese bereitstellt.

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

Wärs nicht möglich, das mit den user-defined AS dem Compiler 
beizubringen und __eeprom dann darüber, aber in der avr-libc, zu lösen?

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


Lesenswert?

Nils S. schrieb:
> Wärs nicht möglich, das mit den user-defined AS dem Compiler
> beizubringen

Sicherlich wäre es.  Ist halt nur eine Frage des Aufwands.  Eine
grundlegende Abschätzung diesbezüglich hat Johann ja implizit oben
gegeben. ;-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ok, also doch eine Fingerübung für GCC Einsteiger...

Freiwillige vor!

von Malte S. (maltest)


Lesenswert?

Gibt es eigentlich eine Aussicht auf Erbschaft der AS in Richtung g++?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Nein, noch nichma trübe Aussichten.

Mit Bordmitteln von C++ lässt sich das doch bestimmt abbilden, genauso 
wie die Fixed-Point Arithmetik von Embedded-C.

Ansonsten hat C++ m.E. versagt.

Die Hauptarbeit in GCC sind momentan:

- Neue Sprachfeatures wie C++11 und C++14.
- Support für Transactional Memory
- Bessere (Auto-)Vectorisierung

Am "unteren" Ende in Richting Resource-beschränker Handware wird 
eigentlich nix mehr gearbeitet; die ENtwicklung geht komplett in 
Richtung der Boliden...

von Karl H. (kbuchegg)


Lesenswert?

Johann L. schrieb:
> Nein, noch nichma trübe Aussichten.
>
> Mit Bordmitteln von C++ lässt sich das doch bestimmt abbilden, genauso
> wie die Fixed-Point Arithmetik von Embedded-C.

Müsste gehen.
Eine Klasse FlashPointer machen. Der dann den Dereferenzierungsoperator 
abbilden und was man sonst noch so an Konstruktoren braucht und man 
sollte damit im Rennen sein.

(Arduino hats ja meines Wissens vorgemacht)

> Am "unteren" Ende in Richting Resource-beschränker Handware wird
> eigentlich nix mehr gearbeitet; die ENtwicklung geht komplett in
> Richtung der Boliden...

Wie üblich. Die Kleinen können sehen, wo sie bleiben.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> Johann L. schrieb:
>> Nein, noch nichma trübe Aussichten.
>>
>> Mit Bordmitteln von C++ lässt sich das doch bestimmt abbilden, genauso
>> wie die Fixed-Point Arithmetik von Embedded-C.
>
> Müsste gehen.
> Eine Klasse FlashPointer machen. Der dann den Dereferenzierungsoperator
> abbilden und was man sonst noch so an Konstruktoren braucht und man
> sollte damit im Rennen sein.
>
> (Arduino hats ja meines Wissens vorgemacht)

Mit nicht-POD ist man aber aus dem Rennen, weil eine nicht-POD Klasse im 
RAM angelegt wird.  Da schießt sich C++ dann selbst ins Knie.

>> Am "unteren" Ende in Richting Resource-beschränker Handware wird
>> eigentlich nix mehr gearbeitet; die Entwicklung geht komplett in
>> Richtung der Boliden...
>
> Wie üblich. Die Kleinen können sehen, wo sie bleiben.

Die Kleinen sind aber selbst schuld.  Wer nicht mitarbeitet, braucht 
auch nicht zu erwarten, daß die ENtwiklung in die gewünschte Richtung 
geht und plötzlich Manna vom Himmel fällt :-/

Warum sollte z.B. Google oder IBM oder ARM Contributions machen, die µCs 
helfen mit ein paar k Flash und noch weniger RAM?

von Malte S. (maltest)


Lesenswert?

Johann L. schrieb:
> Mit Bordmitteln von C++ lässt sich das doch bestimmt abbilden, genauso
> wie die Fixed-Point Arithmetik von Embedded-C.

Auch wieder wahr. Zumindest solange __flash nicht allgemein Einzug in 
alle möglichen Header findet. Okay, die Gefahr ist vermutlich noch lange 
eine theoretische.

Karl Heinz Buchegger schrieb:
>> Am "unteren" Ende in Richting Resource-beschränker Handware wird
>> eigentlich nix mehr gearbeitet; die ENtwicklung geht komplett in
>> Richtung der Boliden...
>
> Wie üblich. Die Kleinen können sehen, wo sie bleiben.

Ein nicht unwesentlicher Grund, warum ich immer wieder gerne die kleinen 
Dinger nehme. Schöner Ausgleich zum sich den ganzen Tag mit den 
Produkten der Speicher-kost-ja-nix-Generation rumärgern, deren Hello 
World auf einem System mit 64 GiB RAM noch den OOM-Killer 
vollbeschäftigt kriegt :/

von Bastler (Gast)


Lesenswert?

Hab schon mal versucht __eeprom in den GCC zu bekommen.
Das es erkannt wird ist kein Problem, aber leider unterscheidet die 
aktuelle Implementierung an diversen Stellen nur "Standard" oder "irgend 
eine Art von Flash". Ich hätte mir da jeweils was case-artiges 
gewünscht, bei dem ich dann einfach "case EEPROM" ergänzen kann.
So wird nun für alle nicht-RAM Zugriffe einfach FLASH Zugriff erzeugt.
Leider reichen meine Fähigkeiten/Erfahrung nicht aus, die über die ganze 
AVR Code-Generierung verteilten Stellen erfolgreich anzupassen (Hut ab 
vor Gjlayde).
Es müßte ja auch nicht unbedingt R/W sein, Lesen aus Eeprom ohne 
Funktions-Aufruf wäre ja auch schon ganz nett.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Bastler schrieb:
> Hab schon mal versucht __eeprom in den GCC zu bekommen.
> Das es erkannt wird ist kein Problem, aber leider unterscheidet die
> aktuelle Implementierung an diversen Stellen nur "Standard" oder "irgend
> eine Art von Flash". Ich hätte mir da jeweils was case-artiges
> gewünscht, bei dem ich dann einfach "case EEPROM" ergänzen kann.
> So wird nun für alle nicht-RAM Zugriffe einfach FLASH Zugriff erzeugt.

Hier sind wohl die Funktionen

avr_decl_flash_p (tree decl)
avr_decl_memx_p (tree decl)
avr_mem_flash_p (rtx x)
avr_mem_memx_p (rtx x)
avr_progmem_p (tree decl, tree attributes)
avr_nonconst_pointer_addrspace (tree typ)

aus avr.c zu erweitern, bzw. deren Caller.

> Es müßte ja auch nicht unbedingt R/W sein, Lesen aus Eeprom ohne
> Funktions-Aufruf wäre ja auch schon ganz nett.

__eeprom zu unterstützen ohne die zugrundeliegenden Funktionen zu 
implementieren halte ich irgendwie für witzlos. Zumal die Funktion nicht 
in C stehen darf weil der Compiler von einem bestimmten ABI ausgehen 
muss.

Alle call-clobbererd Register als zerstört anzusehen wäre der Overkill 
und zudem ein sekundärer Reload.  Weiters ist auch movmem anzupassen, 
d.h. Struct- und Union-Zuweisungen.

von Bastler (Gast)


Lesenswert?

daß das Ganze nur Sinn macht, wenn ALLES Notwendige Implementiert ist, 
war mir auch klar ;-)
Zudem ist hoffenlich aus meinem Text zu entnehmen, daß ich das nicht als 
trivial ansehe und eigentlich nur beschreiben wollte, woran ich schon 
früh gescheitert bin.
Wesentlich Erkenntnis war auch, daß das AVR-Backend offenbar anderst 
aufgebaut ist, als es für eine einfache Erweiterung notwendig wäre.
(Völlig neutral betrachtet und ohne irgendeinen Vorwurf)
Ich werde mir nochmal die genannten Stellen anschauen ;-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Bastler schrieb:

> Zudem ist hoffenlich aus meinem Text zu entnehmen, daß ich das nicht als
> trivial ansehe und eigentlich nur beschreiben wollte, woran ich schon
> früh gescheitert bin.

Bei Tage betrachtet und bei Licht, ist nichts im GCC trivial...

Falls du ernsthaft was zum GCC beitragen willst und nicht nur ein 
bisschen Rumspielen, ist m.E. was einfacheres angesagt.  Genauso wie man 
bei einem µC nicht gleich mit ner eigenen Quadcopter-Steuerung anfängt 
sondern mit ner Binky-LED.  Biespiel: PR57506

Das schwierigste beim Einstieg in die GCC-Entwicklung ist nämlich, die 
Änderung überhaupt in die Codebasis hinein zu bekommen, mal abgesehen 
vom Testing.  Wie man __eeprom testen würde weiß ich auch nicht, denn 
der verwendete Simulator avrtest ist ein reiner Core-Simulator ohne 
Simulation der (internen) I/O.

> Wesentlich Erkenntnis war auch, daß das AVR-Backend offenbar anderst
> aufgebaut ist, als es für eine einfache Erweiterung notwendig wäre.

Viele neurern Änderungen sind no-Op Änderungen, haben also keinen 
Einfluß auf die Codeerzeugung: Bessere Dokumentation, Build-Warnings 
beseitigen, Code aufräumen und besser strukturieren und kommentieren, 
etc.  Da gibt's bestimmt noch viele verbesserungswürdige Stellen.

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


Lesenswert?

Johann L. schrieb:
> denn der verwendete Simulator avrtest ist ein reiner Core-Simulator ohne
> Simulation der (internen) I/O

Wobei es sicher die Übung zum Warmwerden ist, ihm ein simples
EEPROM-Handling noch beizubiegen. ;-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> Johann L. schrieb:
>> denn der verwendete Simulator avrtest ist ein reiner Core-Simulator ohne
>> Simulation der (internen) I/O
>
> Wobei es sicher die Übung zum Warmwerden ist, ihm ein simples
> EEPROM-Handling noch beizubiegen. ;-)

Ist jetztz nicht dein Ernst.  Simulation von 200 unterschiedlichen 
EE-SFRs der Myriaden von AVR-Derivaten?  Ich klopp das da nicht rein.

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


Lesenswert?

Johann L. schrieb:
> Simulation von 200 unterschiedlichen EE-SFRs der Myriaden von
> AVR-Derivaten?

Xmega müsste ich nachgucken (macht der avrsim das überhaupt schon?),
aber bei normalen AVRs gibt's praktisch nur zwei verschiedene
Implementierungen.  Die ältere benutzt die Register auf 0x1c, 0x1d,
0x1e/0x1f für EECR, EEDR und EEAR, die neuere benutzt 0x1f, 0x20,
0x21/0x22.  Hatten wir früher auch in der avr-libc so abstrahiert,
aber dann hat mal jemand einen Heisenbug der Tatsache zugeordnet,
dass damit auf sehr kleinen AVRs das dort undefinierte Register
EEARH beschrieben wird und dass das ja wohl nicht gut sei, und dann
wurde mit aller Gewalt eine per-device-Implementierung reingehämmert.
Find' ich bis heute noch nicht gut so.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> Johann L. schrieb:
>> Simulation von 200 unterschiedlichen EE-SFRs der Myriaden von
>> AVR-Derivaten?
>
> Xmega müsste ich nachgucken (macht der avrsim das überhaupt schon?),

avrsim sagt mir nix; avr-gcc verwendet avrtest. Und ja, er kann XMEGA.

http://sourceforge.net/p/winavr/code/HEAD/tree/trunk/avrtest/

> aber bei normalen AVRs gibt's praktisch nur zwei verschiedene
> Implementierungen.  Die ältere benutzt die Register auf 0x1c, 0x1d,
> 0x1e/0x1f für EECR, EEDR und EEAR, die neuere benutzt 0x1f, 0x20,
> 0x21/0x22.  Hatten wir früher auch in der avr-libc so abstrahiert,
> aber dann hat mal jemand einen Heisenbug der Tatsache zugeordnet,

Heisenbug lol, der ist gut! :-))

> dass damit auf sehr kleinen AVRs das dort undefinierte Register
> EEARH beschrieben wird und dass das ja wohl nicht gut sei, und dann
> wurde mit aller Gewalt eine per-device-Implementierung reingehämmert.

Vorteil von avrtest ist, daß er schnell ist.  Die gesamte Testsuite mit 
über 100.000 Tests durchzunudeln braucht auf einem Single-Core deutlich 
weniger als 1 Stunde.

Bevor man exotoische Sachen wie EEPROM einbaut, sollten vielleicht erst 
mal IRQs unterstützt werden, etwa mit per Option vorgegebener IRQ-Last.

Momentan ist avrtest noch schön einfach und schnell; i.w. eine C-Datei.

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


Lesenswert?

Johann L. schrieb:

> avrsim sagt mir nix; avr-gcc verwendet avrtest. Und ja, er kann XMEGA.

Ja, avrtest meinte ich natürlich.

Ich habe bei Xmega noch nichts mit EEPROM gemacht.  Wenn ich das
richtig lese, kann man wohl dort im memory-mapped-Modus sogar den
EEPROM wie SRAM beschreiben. Das wäre ja super einfach.

> Heisenbug lol, der ist gut! :-))

Wenn du hinguckst, isser weg. :)  Naja, das war völlig ominös,
keiner hat das Verhalten jemals irgendwo nachvollziehen können,
was da berichtet worden ist, aber es musste dann ganz plötzlich
der undefinierte Zugriff auf EEARH schuld gewesen sein.

> Vorteil von avrtest ist, daß er schnell ist.

Gut, aber das würde der Sache ja keinen Abbruch tun.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:

> Ich habe bei Xmega noch nichts mit EEPROM gemacht.  Wenn ich das
> richtig lese, kann man wohl dort im memory-mapped-Modus sogar den
> EEPROM wie SRAM beschreiben. Das wäre ja super einfach.

Trifft das nicht auch auf den Flash zu? Damit käme man komplett ogne 
pgm_read und progmem und __flash aus -- zumindest auf den kleineren 
Derivaten, wo das genze Speicher-Geraffel in 64k passt.  Einzig ein 
anderes Linkerscript, das .rodata richtig legt, wäre nötig.

>> Vorteil von avrtest ist, daß er schnell ist.
>
> Gut, aber das würde der Sache ja keinen Abbruch tun.

Doch, schon. Bei /jedem Speicherzugriff muss getestet werden, ob die 
Adresse vielleicht EECR ist. Oder EEDR. Oder EEAR.  Teilweise gibt's 
auch Magie in den SFRs, nämlich für 4 Ticks IRQs sperren oder so, was 
weitere Zeit kostet -- und in 99.9% der Fälle nicht zutrifft.

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


Lesenswert?

Johann L. schrieb:

> Trifft das nicht auch auf den Flash zu?

Nein, denn der muss immer seitenweise gelöscht und neu beschrieben
werden.

>>> Vorteil von avrtest ist, daß er schnell ist.
>>
>> Gut, aber das würde der Sache ja keinen Abbruch tun.
>
> Doch, schon. Bei jedem Speicherzugriff muss getestet werden, ob die
> Adresse vielleicht EECR ist.

Da aber bereits andere SFRs emuliert sein müssen (SREG, SPL, SPH),
sollte die Einführung weiterer keine zusätzlichen Performanceeinbußen
bringen. So groß ist ja der SRAM eines AVRs nicht, man könnte also
auch gleich für jede Adresse eine Zugriffsfunktion schreiben und
dann ein Array von 64 Ki Einträgen damit füllen. ;-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> Johann L. schrieb:
>
>> Trifft das nicht auch auf den Flash zu?
>
> Nein, denn der muss immer seitenweise gelöscht und neu beschrieben
> werden.

Meine Frage bezog sich auf den readonly-Teil.  Wenn geschrieben wird, 
hätte das keinen Effekt.

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


Lesenswert?

Johann L. schrieb:
> Meine Frage bezog sich auf den readonly-Teil.

Meine Aussage oben jedoch auf das Schreiben des EEPROMs.

Aber auf deine Frage: nein, der Flash muss aufgrund der
Harvard-Architektur immer über gesonderte Befehle gelesen werden.
Er lässt sich auch nicht auf den SRAM-Bereich abbilden.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Johann L. schrieb:
> Jörg Wunsch schrieb:
>
>> Ich habe bei Xmega noch nichts mit EEPROM gemacht.  Wenn ich das
>> richtig lese, kann man wohl dort im memory-mapped-Modus sogar den
>> EEPROM wie SRAM beschreiben. Das wäre ja super einfach.
>
> Trifft das nicht auch auf den Flash zu?

Jörg Wunsch schrieb:
> Johann L. schrieb:
>
>> Trifft das nicht auch auf den Flash zu?
>
> Nein, denn der muss immer seitenweise gelöscht und neu beschrieben
> werden.

Gerade im AVR Instruction Set gelesen:

> LDS (16-bit) – Load Direct from Data Space
>
> Description: [...] For parts without SRAM, the data space
> consists of the register file only. In some parts the Flash
> memory has been mapped to the data space and can be read
> using this command.

Verstehe ich da was falsch? Analog für's Schreiben:

> STS (16-bit) – Store Direct to Data Space
> Description: [...] For parts without SRAM, the data space
> consists of the Register File only. In some parts the Flash
> memory has been mapped to the data space and can be written
> using this command.

Allerdings erlauben diese Instruktionen nur ein 7-Bit Argument für die 
zu lesende / schreibende Adresse, so daß abzüglich des I/O-Bereichs kaum 
was an via LDS / STS lesbarem / schreibbarem Flash übrig bleibt.

Für GCC und Binutils ist das insoweit irrelevant als da keine 16-Bit LDS 
oder STS unterstützt werden, die gibt's ja nut bei den 
Register-kastrierten Tinys...

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


Lesenswert?

Johann L. schrieb:
> Für GCC und Binutils ist das insoweit irrelevant als da keine 16-Bit LDS
> oder STS unterstützt werden, die gibt's ja nut bei den
> Register-kastrierten Tinys...

Und gerade bei denen sind mir bislang nur welchen über den Weg
gelaufen, deren Flash man gar nicht zur Laufzeit beschreiben
kann (nur während der Programmierung, und dann auch nur mit Vcc = 5 V).

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.