Konstante Zeiger (Memory mapped Peripherie)



  • ArmDran schrieb:

    Wie gebe ich denn eine Adresse wie 0xFooFoo als Adresse an?

    Dachte an

    template< typename T, T* address > struct reference
    

    oder sowas
    mit

    reference<int,reinterpret_cast<int*>(0xfoofoo)>
    


  • Das ergibt jetzt folgendes bei mir:

    D:\Projekte\testworspace\chibios_test\include/stm/util.hpp:45:9: error: '3758153752u' is not a valid template argument for 'volatile unsigned int*' because it is not the address of a variable
      struct reference : public reference2< T, reinterpret_cast<T*>(address) > {
    

  • Mod

    @volkard: Das kann nicht funktionieren. Laut Standard ist reinterpret_cast<int*>(0xfoofoo) kein konstanter Ausdruck. [expr.const]/2:

    A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression (3.2)[…]:

    — a reinterpret_cast (5.2.10);

    ArmDran schrieb:

    Wie gebe ich denn eine Adresse wie 0xFooFoo als Adresse an?

    Indem du den Template-Parameter den richtigen Typ haben lässt. Gezeigt hat Volki das ja schon[.



  • Arcoth:
    Erst sagst Du das kann so nicht gehen, und dann sagst Du ich soll es so machen? Ich bin verwirrt. Was ich machen will ist klar, oder? Ich will eine Referenz auf einen Hardware-Register haben, dessen Addresse ich dem Referenzhandbuch der Hardware entnehme.



  • Arcoth schrieb:

    Laut Standard ist reinterpret_cast<int*>(0xfoofoo) kein konstanter Ausdruck.

    Mhhm, das finde ich ein wenig kleinlich. 😞

    Arcoth schrieb:

    Indem du den Template-Parameter den richtigen Typ haben lässt. Gezeigt hat Volki das ja schon[.

    Ich vermute, da lebt noch kein Objekt. Sowas wie der Bildschirmspeicher unter DOS bei Adresse 0xa000:0000. Mir scheint, er teilt sich per memory mapping dort ein Objekt über mehrere Prozesse.


  • Mod

    Erst sagst Du das kann so nicht gehen, und dann sagst Du ich soll es so machen?

    Nein. Das:

    template <typename T, T*>
    struct foo;
    

    ist Ok. Du gibst dann die Adresse eines deklarierten T 's an das Template.

    Ich will eine Referenz auf einen Hardware-Register haben, dessen Addresse ich dem Referenzhandbuch der Hardware entnehme.

    Es ist schlichtweg unmöglich eine constexpr -Referenz auf ein Hardware-Register zu haben. Du wirst dich mit static const zufrieden geben müssen.



  • Das ist doch offen gesagt beschissen! 4.8 hat doch gezeigt, wie gut das ginge! Wer macht da eigentlich den Standard?


  • Mod

    Sauber wäre, Symbole (Variablen) für die entsprechenden Speicherstellen zu deklarieren, und dann dem Linker mitzuteilen, auf welche Adressen diese Symbole verweisen sollen.



  • Der Gedanke wurde verworfen, weil es auch irgendewelche Compiler-Erweiterungen benötigt (declspec .section blabla) und dann gleich an zwei Stellen rumgedoktort werden muss. Ich sehe da dann den Vorteil in der Praxis nicht.


  • Mod

    ArmDran schrieb:

    Der Gedanke wurde verworfen, weil es auch irgendewelche Compiler-Erweiterungen benötigt (declspec .section blabla) und dann gleich an zwei Stellen rumgedoktort werden muss. Ich sehe da dann den Vorteil in der Praxis nicht.

    So kompliziert muss es gar nicht sein.

    z.B.

    extern "C" int hardware_reg;
    
    int main()
    {
        hardware_reg = 42;
    }
    

    kompiliert mit

    g++ test.cpp -Wl,-defsym,hardware_reg=0
    

    (führt nat. zu Segfault).
    Kann man einfach im Makefile ergänzen.

    Wenn es viele Symbole sind, erstellt man einmalig einen Header und ein Symbolfile für den Linker (ersetzt das Objektfile der Übersetzungseinheit mit den Variablendefinitionen, die man sonst in C++ hätte). Damit sind dann auch diese systemabhängigen Definition zentral an einem Platz zu finden, was späteres Portieren erheblich vereinfachen sollte.
    Und die Vorteile sollten auf der Hand liegen: der C++-Code ist völlig sauber (und der Compiler kann auch bessere Fehlermeldungen geben, statt Fehler bei Instantiierung von foo<int, <magic_number>> steht dann z.B. foo<int, &hardware_reg>).



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


  • Mod

    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.


  • Mod

    Beispiel einfach erweitert
    test.cpp

    extern "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;
    

  • Mod

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


Anmelden zum Antworten