Systemnahe operierung



  • Also die höchste Ebene ist doch Mainboard, CPU und BIOS?
    CPU hat einen eigenen Adressraum sowie das BIOS und gegebenfalls vorhandene Controller auf dem Mainboard?

    Ich möchte nun diese Adressen auf der höchsten Ebene sozusagen scannen. Ist das mit C machbar oder benötige ich dazu doch eine andere Programmiersprache?



  • Mit einem Compiler der dir 16 Bit Code erzeugt kannst du natürlich auch mit C bootbaren Code erzeugen und deine Adressen abfragen.



  • Tobiking2 schrieb:

    Mit einem Compiler der dir 16 Bit Code erzeugt kannst du natürlich auch mit C bootbaren Code erzeugen und deine Adressen abfragen.

    Leider kenne ich sowas nur mit Assembler. Mit welchen Compiler kann man das mit C machen? Und wird bei so einem Compiler der Bootcode selbst erstellt, gegebenfalls je nach Einstellung, oder scheibt man das auch mit C? Ich habe auch noch nie mit C auf Hardware Adressen direkt zugegriffen. Wird das bei C auch da trotzdem nicht direkt gemacht und doch nur wieder über einen Header (bib)?



  • Imperator schrieb:

    Also ich suche z.B. ein Tutorial in dem gezeigt wird wie man mit C auf die Adressen zugreifen kann bzw. die existierenden Adressen sichtbar machen kann.

    Das geht sehr einfach:

    uint32_t *some_reg = (uint32_t*) 0xdeadbeef;
    

    Für meinen Mikrokernel habe ich folgenden Makro geschrieben:

    /* include/pros/pxa/registers.h */
    
    #define __REG(x)    (*((volatile uint32_t *) x))
    
    ...
    
    /* I2C bus registers */
    #define IBMR  __REG(0x40301680)  /* I2C Bus Monitor Register */
    #define IDBR  __REG(0x40301688)  /* I2C Data Buffer Register */
    #define ICR   __REG(0x40301690)  /* I2C Control Register */
    #define ISR   __REG(0x40301698)  /* I2C Status register */
    #define ISAR  __REG(0x403016a0)  /* I2C Slave Address Register */
    
    /* I2C Registers bits */
    
    #define IBMR_SCLS   (1 << 2)    /* SCL Status bit (serial clock line signal) */
    #define IBMR_SDAS   (1 << 1)    /* SDA Status bit (serial data/address signal) */
    
    #define IDBR_IDB    (0xff)      /* I2C Data Buffer (7 bit buffer for send/rec) */
    #define ICR_FM      (1 << 15)   /* ICR:15 Fast Mode */
    #define ICR_UR      (1 << 14)   /* ICR:14 Unit Reset */
    #define ICR_SADIE   (1 << 13)   /* ICR:13 Slave Address Detected Interrupt Enable */
    #define ICR_ALDIE   (1 << 12)   /* ICR:12 Arbitration Loss Detected Interrupt Enable */
    #define ICR_SSDIE   (1 << 11)   /* ICR:11 Slave STOP Detected Interrupt Enable */
    #define ICR_BEIE    (1 << 10)   /* ICR:10 Bus Error Interrupt Enable */
    #define ICR_IRFIE   (1 << 9)    /* ICR:9  IDBR Receive Full Interrupt Enable */
    #define ICR_ITEIE   (1 << 8)    /* ICR:8  IDBR Transmit Empty Interrupt Enable */
    #define ICR_GCD     (1 << 7)    /* ICR:7  General Call Disable */
    #define ICR_IUE     (1 << 6)    /* ICR:6  I2C Unit Enable */
    #define ICR_SCLE    (1 << 5)    /* ICR:5  SCL Enable */
    #define ICR_MA      (1 << 4)    /* ICR:4  Master Abort */
    #define ICR_TB      (1 << 3)    /* ICR:3  Transfer Byte */
    #define ICR_ACKNAK  (1 << 2)    /* ICR:2  ACK/Nak Control */
    #define ICR_STOP    (1 << 1)    /* ICR:1  STOP */
    #define ICR_START   (1 << 0)    /* ICR:0  START */
    
    #define ISR_BED     (1 << 10)   /* ISR:10 Bus Error Detected */
    #define ISR_SAD     (1 << 9)    /* ISR:9  Slave Adress Detected */
    #define ISR_GCAD    (1 << 8)    /* ISR:8  General Call Address Detected */
    #define ISR_IRF     (1 << 7)    /* ISR:7  IDBR Receive Full */
    #define ISR_ITE     (1 << 6)    /* ISR:6  IDBR Transfer Empty */
    #define ISR_ALD     (1 << 5)    /* ISR:5  Arbitration Loss Detected */
    #define ISR_SSD     (1 << 4)    /* ISR:4  Slave STOP Detected */
    #define ISR_IBB     (1 << 3)    /* ISR:3  I2C Bus Busy */
    #define ISR_UB      (1 << 2)    /* ISR:2  Unit Busy */
    #define ISR_ACKNAK  (1 << 1)    /* ISR:1  ACK/NAK Status */
    #define ISR_RWM     (1 << 0)    /* ISR:0  Read/Write Mode */
    
    #define ISAR_ISA    (0x7f)      /* ISAR:6:0 I2C Slave Address */
    ...
    

    Um den I²C zu initialisren mache ich nur:

    int pxa_i2c_reset(uint8_t addr, int baudrate)
    {
        int baudrate_mask;
    
        /* baudrate_mask == 0 ==> ICR &= ~ICR_FM
         * else ICR |= ICR_FM
         */
    
        CKEN &= ~CKEN_I2C; /* bringing down I2C clock */
        CKEN |= CKEN_I2C; /* bringing up I2C clock */
    
        if(baudrate == 100)
            baudrate_mask = 0;
        else if(baudrate == 400)
            baudrate_mask = 1;
        else
            return PANIC_CONF;
    
        /* resetting core, see pages 9-21, 9-22 from
         * Intel PXA255 developer's manual */
    
        /* setting reset bit */
        ICR |= ICR_UR;
    
        /* clear the ISR register */
        ISR = 0;
    
        /* setting the address */
        ISAR = ISAR_ISA & addr;
    
        /* enabling the i2c controller */
        ICR |= ICR_IUE;
    
        /* enablind the SCL line */
        ICR |= ICR_SCLE;
    
        /* setting the baudrate */
        if(baudrate_mask)
            ICR |= ICR_FM;
        else
            ICR &= ~ICR_FM;
    
        /* clear reset in he ICR */
        ICR &= ~ICR_UR;
    
        ICR |= ICR_BEIE | ICR_IRFIE | ICR_ITEIE;
    
        return 0;
    }
    

    Assembler braucht man für die wenigsten Sachen, mit C kann man sich das Leben wunderbar einfacher machen.

    Die Adressen udn Werte habe ich natürlich aus der Hardware Doku bekommen.

    Ich habe auch noch nie mit C auf Hardware Adressen direkt zugegriffen. Wird das bei C auch da trotzdem nicht direkt gemacht und doch nur wieder über einen Header (bib)?

    natürlich kannst du in C direkt auf jede beliebige (adressierbare) Adresse zugreifen (ob du Lesen/Schreiben darfst, ist eine andere Geschichte). Ob man direkt macht (wie ich oben) oder über eine Bib (die Kernel-Syscalls verwendet) hängt vom Kontext ab. Wenn dein Code im Kernel-Space läuft, dann wird er wahrscheinlich überall (sofern vom Memory-Controller erlaubt) zugreifen können. Im User-Space eher nicht, da der Kern bzw. der memory-Controller dich daran hindert (dafür sind Treiber eben da).



  • supertux schrieb:

    Imperator schrieb:

    Also ich suche z.B. ein Tutorial in dem gezeigt wird wie man mit C auf die Adressen zugreifen kann bzw. die existierenden Adressen sichtbar machen kann.

    Das geht sehr einfach:

    uint32_t *some_reg = (uint32_t*) 0xdeadbeef;
    

    die Adressen liest du aus der Prozessor/Hardware-Dokumentation.

    Ist der Hexadezimalwert die Adresse oder der Wert der in die Adresse soll? uint32_t ist nur eine Variable und kein Funktionsaufruf? Also damit hätte ich dann nur einen Wert nach der Adressnorm gespeichert? Warum 32? Ich dachte das geht nur mit 16 Bit.

    Was passiert wenn ich was auf eine Adresse schreiben will oder eine reservieren will die aber gar nicht exiztiert? Kann man so einen fehler aufangen oder anhand eines Rückgabewertes identifizieren?



  • Ich hab meinen voherigen Post editiert. Lies ihn mal durch.

    Ob du 32- oder- 16 oder 8-bit Register hast, musst du selber wissen und dementsprechen den Code anpassend. Mein Code sagt nicht anders als:

    die nächsten Vier Bytes beginnend auf Adresse 0xdeadbeef gehören zusammen. Über some_reg kann man dann auf diese 4 bytes zugreifen. Ob du es darfst oder nicht, ist wie gesagt, eine andere Frage.

    Ich verstehe nicht, was du mit Funktionaufruf meinst. Klar ist es nur eine Variable. Wenn eine Funktion den Wert eines Registers lesen soll, dann übergibst du der Fkt entweder den Wert oder die Adresse des Registers.

    Was passiert wenn ich was auf eine Adresse schreiben will oder eine reservieren will die aber gar nicht exiztiert?

    Das wahrscheinlichste ist, dass du eine Exception bekommst der Art "data abort exception" (im Falle der ARM Architektur). Das ist aber Architektur-abhängig und steht in deinem Handbuch.



  • OK. Und mit welchem Compiler compiliert man das dann? Oder muss man immer einen spezielen Compiler nehmen, der auf den CPU des Zielsystem gerichtet ist?



  • Mit einem C Compiler.

    Ich schlage vor, du kaufst dir ein Buch über Betriebssysteme bzw. Hardwarearchitektur. Ohne dieses Wissen, wirst du nichts auf die Reihe kriegen. Einen Systemkern vom scratch zu schreiben ist nicht einfach und erfordert, dass du weißt, was du tust, was offensichtlich bei dir nicht der Fall ist.

    Kauf dir ein Gumstix Board. Sie sind billig, klein, leistungsfähig und verwenden die wunderschöne ARM-Architektur.

    Diese Buch
    ARM System Developer's Guide | ISBN: 1558608745
    ist super gut, da man nicht nur mehr über die ARM-Arch erfährt sondern auch über genau diese Dinge, die du wissen und machen willst. Leider ist das Buch etwas teuer aber es lohnt sich auf jeden Fall.



  • supertux schrieb:

    Mit einem C Compiler.

    Ich schlage vor, du kaufst dir ein Buch über Betriebssysteme bzw. Hardwarearchitektur. Ohne dieses Wissen, wirst du nichts auf die Reihe kriegen. Einen Systemkern vom scratch zu schreiben ist nicht einfach und erfordert, dass du weißt, was du tust, was offensichtlich bei dir nicht der Fall ist.

    Kauf dir ein Gumstix Board. Sie sind billig, klein, leistungsfähig und verwenden die wunderschöne ARM-Architektur.

    Diese Buch
    ARM System Developer's Guide | ISBN: 1558608745
    ist super gut, da man nicht nur mehr über die ARM-Arch erfährt sondern auch über genau diese Dinge, die du wissen und machen willst. Leider ist das Buch etwas teuer aber es lohnt sich auf jeden Fall.

    Momentmal! Es gibt doch verschiedenste Arten von CPUs! Wie kann es da sein, dass ein C Compiler den Code einfach für irgend einen CPU in passenden Maschienencode wandeln kann? Bevor ich was kaufe muss ich das schon genau wissen!!!



  • Weil es für jede Architektur einen C Compiler gibt. [1]

    Es gibt C Compiler für x86, arm, powerpc, sparc, usw. Du musst, wenn du einen Kern schreibst, am wahrscheinlichsten einen Cross-Compiler verwenden.

    Ich verwende den GNU-GCC und musste mir den arm-xscale-linux-gnu-gcc bauen, um auf einem Linux-x86 Code für den intel-xscale Prozessor bauen zu können.

    [1] wahrscheinlich gibt es Exoten für die es keinen C Compiler gibt.



  • supertux schrieb:

    Weil es für jede Architektur einen C Compiler gibt. [1]

    Es gibt C Compiler für x86, arm, powerpc, sparc, usw. Du musst, wenn du einen Kern schreibst, am wahrscheinlichsten einen Cross-Compiler verwenden.

    Ich verwende den GNU-GCC und musste mir den arm-xscale-linux-gnu-gcc bauen, um auf einem Linux-x86 Code für den intel-xscale Prozessor bauen zu können.

    [1] wahrscheinlich gibt es Exoten für die es keinen C Compiler gibt.

    Weil es für jede Architektur eine C Compiler Version gibt meintest Du?

    Gibt es eine C Compiler Version die Intel und AMD CPUs von PCs unterstützt? Also Sockel 775, AM1, AM2 usw. Eine gewisse Kompilibität muss ich ja schon haben. Zumindest die Boot Datei. Dann könnte ja die Boot Datei die entsprechende Version meines Programms, was passend für den CPU ist, laden. Wie ist das eigentlich mit der Boot Datei bei den C Compilern? Auch selber schreiben und ist das eine extra Datei, die dann nur eine Spiegelung von den Bootsektoren ist?



  • was hat der Sockel mit der internen Architektur zu tun? Die von dir genannten CPUs gehören zur x86 Familie und jeder Compiler, der x86 Code produziert, produziert auch ausführbaren Code für diese CPUs.

    Mit CPU meine ich nicht ein bestimmtes Model sondern die darunter liegende Architektur.

    Und die heuten Compiler können auch die Besonderheiten der diversen CPU-Typen berücksichtigen, auch wenn sie die selbe Architektur besitzen. Beim GNU GCC gibt es z.b. die -mcpu, -march, usw. Optionen.

    Deshalb sag ich dir, besorg die ein Buch über Hardwarearchitektur, du scheint viele Wissenslücken im Bereich zu haben.



  • supertux schrieb:

    was hat der Sockel mit der internen Architektur zu tun? Die von dir genannten CPUs gehören zur x86 Familie und jeder Compiler, der x86 Code produziert, produziert auch ausführbaren Code für diese CPUs.

    Mit CPU meine ich nicht ein bestimmtes Model sondern die darunter liegende Architektur.

    Und die heuten Compiler können auch die Besonderheiten der diversen CPU-Typen berücksichtigen, auch wenn sie die selbe Architektur besitzen. Beim GNU GCC gibt es z.b. die -mcpu, -march, usw. Optionen.

    Deshalb sag ich dir, besorg die ein Buch über Hardwarearchitektur, du scheint viele Wissenslücken im Bereich zu haben.

    Naja ich glaube ich weiß jetzt was ich wissen muss für mein vorhaben. zumindest was ich mir an Informationen holen muss. Die ganze boot und IO geschichte habe ich schon gelernt. Geht dann wohl nur wieder um das nerfige, wie man das bootfile in die bootsektoren schreibt. Aber werde das sehr wahrscheinlich so machen, das ich es auf ein Floppy Image schreibe und dieses dann von einer Box starten lasse. Darüber hinaus muss ich aber dann wohl doch auch mit C überhaupt ersteinmal den bootcode schreiben um überhaupt mit C die Adressanfragen machen zu können.
    Denke ich werde da bei openbook findig. Kann ich eigentlich Eclipse dafür nehmen?



  • Imperator schrieb:

    Kann ich eigentlich Eclipse dafür nehmen?

    was hat die IDE/Text-Editor damit zu tun? Nimm ein Program, mit dem du Code schreiben kannst.



  • supertux schrieb:

    Imperator schrieb:

    Kann ich eigentlich Eclipse dafür nehmen?

    was hat die IDE/Text-Editor damit zu tun? Nimm ein Program, mit dem du Code schreiben kannst.

    Naja Eclipse bietet ja Syntaxhervorhebung an und ist ja dann C. Und compiliert werden muss es dann auch mit einem Compiler. Und das ist ja sinn der sache der IDE. Codden und dann per ein-klick compilieren. Muss halt wohl wahrscheinlich den Compiler als externe angeben.


Anmelden zum Antworten