Konstante Zeiger (Memory mapped Peripherie)
-
ArmDran schrieb:
Hrmm, ich weiß jetzt nicht genau, was Du mit Symbolfile meinst, das würde ich gerne nachlesen - aber ich meine einsehen zu können, dass ich dann auf der Linker-Seite mit dekorierten Namen zu tun hätte oder aber den globalen namespace verseuche?
Selbstverständlich kannst du die Variablen auch in irgendeinem Namensraum deklarieren. Mit Namens-Mangling würde ich mich allerdings nicht herumplagen wollen, extern "C" ist also schon sinnvoll. Der Namensraum ist bei C-Bindung nicht Bestandteil des Namens (und folglich deklarieren extern "C" Deklarationen mit dem gleichen Namen in unterschiedlichen Namensräumen die gleiche Entität - der Standard sagt das sogar explizit).
-
Okay, ich würde mit dem Gedanken zumindest gerne einmal herumspielen. In Deinem Beispiel schriebst Du "hardware_reg=0" in die Kommandozeile und erwähntest gleich im Anschluss, dass man solcherart Definitionen in einen Symbol-File auslagern kann. Ist das eine spezielle Art von Datei oder ein normaler Linker-Skript mit dieser Semantik im Hinterkopf? Ich finde unter "Symbol-File" oder ähnlichen Ausdrücken auf Anhieb nichts, das mich anspringt.
-
Beispiel einfach erweitert
test.cppextern "C" int reg1; extern "C" int reg2; int main() { reg1 = 0; reg2 = 0; }test.x (ein extrem simples Linker Script)
reg1 = 0; reg2 = 1;Kompilieren mit
g++ test.cpp -Wl,-R,test.x
-
Hallo camper,
ersteinmal Danke, so habe ich's jetzt zum Laufen bekommen:extern "C" reg_detail::syst_csr __core_syst_csr; static auto& syst_csr = __core_syst_csr; extern "C" volatile uint32 __core_syst_rvr; static auto& syst_rvr = __core_syst_rvr; extern "C" volatile uint32 __core_syst_cvr; static auto& syst_cvr = __core_syst_cvr; extern "C" volatile uint32 __core_syst_calib; static auto& syst_calib = __core_syst_calib;__rcc_regs = 0x40023800; __flash_regs = 0x40023C00; __core_syst_csr = 0xE000E010; __core_syst_rvr = 0xE000E014; __core_syst_cvr = 0xE000E018; __core_syst_calib = 0xE000E01C;Also es funktioniert und tut wieder das, was es soll. Aber ich bin darüber extrem unglücklich, denn beim Entwickeln dieser Bibliothek muss ich jetzt immer an zwei Stellen rumarbeiten (eben dem Symbol-File und dem Quelltext) und verliere die Eigenschaft der Selbst-Dokumentation des Quelltexts, weil die Adressen dort jetzt nicht mehr drinstehen. Bislang konnte man sich an den Typen entlanghangeln und hat dann gesehen: aha, hier wird dieser und jeder Register benutzt, dann schlägt man das Referenzhandbuch auf und sieht aha - die Adresse stimmt überein, hier passiert ja gar nix magischen usw. usf.. Jetzt ist das alles total versteckt und ich finde ich habe damit alle Vorteile gegenüber der Makro-Wand der Hersteller-C-Header verspielt.

-
Adressen könntest Du in den Code lesbarmachen.
extern "C" reg_detail::syst_csr p0xE000E010; static auto& syst_csr = p0xE000E010;__p0xE000E010 = 0xE000E010;
-
Wozu eigentlich die Referenzen?
Und das mit den Adressen ist nicht wirklich verständlich. Der Sinn von Symbolen ist doch gerade, (u.a.) magische Zahlen wie etwa Adressen loszuwerden. Und im Zweifel kann man ja immer noch - wie volkard angemerkt hat, den Bezeichner entsprechend der Adresse benennen.
-
volkard, auch danke an Dich, ja, so könnte man wohl drumrumwuseln. Aber irgendwie hat das alles einen extrem faden Beigeschmack. C++ zog los als hardwarenahe Highlevel-Programmiersprache und dann wird einem aktiv ein Klotz vor die Füße gesetzt. Ich bin jetzt erstmal enttäuscht, habe eine Frage an die Entwickler des Arm-GCC-Ports gewendet, ob die einen Workaround haben und falle derweilen ersteinmal vom Glauben ab. Solche Dinge haben echt einen extremen Einfluss auf meine Stimmung...
-
@camper: Das habe ich nur direkt so hingeschrieben, damit ich keine Kollisionen bei den Symbolen bekomme, falls mal Register gleiche Namen besitzen oder so.
-
ArmDran schrieb:
volkard, auch danke an Dich, ja, so könnte man wohl drumrumwuseln. Aber irgendwie hat das alles einen extrem faden Beigeschmack. C++ zog los als hardwarenahe Highlevel-Programmiersprache und dann wird einem aktiv ein Klotz vor die Füße gesetzt. Ich bin jetzt erstmal enttäuscht, habe eine Frage an die Entwickler des Arm-GCC-Ports gewendet, ob die einen Workaround haben und falle derweilen ersteinmal vom Glauben ab. Solche Dinge haben echt einen extremen Einfluss auf meine Stimmung...
Ähm, wo es ist jetzt das Problem? Das, was du wolltest, war noch nie erlaubt, also ist es nicht schlechter geworden...
-
camper schrieb:
Der Sinn von Symbolen ist doch gerade, (u.a.) magische Zahlen wie etwa Adressen loszuwerden.
Ja, schon. Aber man mag sie auf C++-Ebene auch definieren können.
Ich erinnere mal ans Einstellen der zu linkenden Bibliotheken unter MSVC und bei 3000 Quellcodedateien und zig Fremdlibs war das zum Kotzen. Aber mit
#pragma comment libwar alles ok. Das kommt in den Header, der die Funktionalität der lib bereitstellt und alles geht von allein. Insbesondere kann man mit den Dateien oder Teilen davon neue Projekte starten, ohne strundenlang Linkersachen anzupassen.
Also ArmDrans Wunsch kommt mir nicht seltsam vor. Ich finde, daß ins makefile so wenig Anwendungscode wie möglich gehört. Daher auch so flach
__p0xE000E010 = 0xE000E010;
-
volkard schrieb:
camper schrieb:
Der Sinn von Symbolen ist doch gerade, (u.a.) magische Zahlen wie etwa Adressen loszuwerden.
Ja, schon. Aber man mag sie auf C++-Ebene auch definieren können.
Ich erinnere mal ans Einstellen der zu linkenden Bibliotheken unter MSVC und bei 3000 Quellcodedateien und zig Fremdlibs war das zum Kotzen. Aber mit
#pragma comment libwar alles ok. Das kommt in den Header, der die Funktionalität der lib bereitstellt und alles geht von allein. Insbesondere kann man mit den Dateien oder Teilen davon neue Projekte starten, ohne strundenlang Linkersachen anzupassen.
Also ArmDrans Wunsch kommt mir nicht seltsam vor. Ich finde, daß ins makefile so wenig Anwendungscode wie möglich gehört. Daher auch so flach
__p0xE000E010 = 0xE000E010;Wenns ein zusammenhängender Speicherbereich ist, reicht es ja auch, einfach ein Array auf diese Weise zu deklarieren, und die Zuordnung zu einzelnen Registern dann nur im C++ Code vorzunehmen.
Im Extremfall einfach ein Array für den gesamten verfügbaren Speicher
Kann man evtl. mit union verfeinern, um mit verschiedenen Datentypen umgehen zu können.
-
Alternativ könnte man auch einfach zulassen, was offenbar so natürlich ist, dass es GCC bis Version 4.8 unterstützt hat, bis dessen Entwickler dann mal im Standard nachgeblättert haben. Vor allem, dass ausgerechnet bei reinterpret_cast Sicherheit als ein Argument hergenommen wird, erschließt sich mir nicht so ganz (http://wg21.cmeerw.net/cwg/issue1384)...
-
ArmDran schrieb:
Alternativ könnte man auch einfach zulassen, was offenbar so natürlich ist, dass es GCC bis Version 4.8 unterstützt hat, bis dessen Entwickler dann mal im Standard nachgeblättert haben. Vor allem, dass ausgerechnet bei reinterpret_cast Sicherheit als ein Argument hergenommen wird, erschließt sich mir nicht so ganz (http://wg21.cmeerw.net/cwg/issue1384)...
Ich glaube nicht, dass sich das Ganze so ohne weiteres bugfrei implementieren lässt.
mit
template <typename T, T*p> struct foo { ... }; extern int bar1, bar2;wissen wir sicher, dass foo<int,&bar1> und foo<int,&bar2> verschiedene Instantiierungen sind (sogar dann, wenn die Symbole beim Linker den gleichen Wert haben...). Aber was ist, wenn eine Adresse explizit angegeben werden kann?
foo<int,reinterpret_cast<int*>(100)> ? ist das nun eine andere Instantiierung auch dann, wenn die Adresse von bar1 am Ende auch 100 ist?
Wenn nicht, dann muss der Compiler ja bereits die Adresse kennen, um z.B. is_same<...> korrekt zu instantiieren. Dabei ist die Festlegung von Adressen ja gerade typischerweise Aufgabe des Linkers oder sogar erst des Loaders.In jedem Fall ist das Forum nicht der richtige Ort für solche Beschwerden. Dafür gibt es bugzilla bei gcc.
-
Ja Du hast Recht, ich musste nur irgendwie meinem Frust freien Lauf lassen... Ich bleib erstmal bei 4.8 und wenn die Entwickler keinen Workaround parat haben, schreib ich mir nen Skript der den Quelltext nach "__placed_0xfoofoo" absucht und ne Symboldatei schreibt... Wobei ich dann auch verifizieren muss, dass da derselbe Code rauskommt als hätte der Compiler schon die letztendliche Adresse parat.