Autor Thema: Ports und Index  (Gelesen 7350 mal)

Paula

  • Gast
Gespeichert
« am: 08. May 2014, 16:25 »
Hallo,
ich möchte am Port 0x3D4 das Regster 0x00 ansprechen.
Mit den Ports hab ich das so:
inline unsigned oput(unsigned port1, unsigned val1)
{
    __asm__ volatile {
    ldi r16, (val1)
    out (port1),r16
    };
}

inline void iput(unsigned port2, unsigned val2)
{
    __asm__ volatile {
    in (val2), (port2)
    ldi r17, (val2)
    };

    return val2;
}

nun muss ich aber irgendwie die Index Nummer noch dazu packen, wie macht man das am besten?

LG

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 08. May 2014, 16:52 »
Derartigen Code habe ich noch nie gesehen. Für welche CPU und welchen Compiler soll das sein?

Ansonsten zur Frage, falls sich das auf CGA bezieht: Es können nach Spezifikation nur Indizes 14 bis 17 gelesen werden. Register 0 ist nicht lesbar. Möglicherweise gibt es zwar Adapter, die das ermöglichen, aber warum willst du die Register überhaupt auslesen?
Dieser Text wird unter jedem Beitrag angezeigt.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 08. May 2014, 17:03 »
Der Index ermöglicht es, mit wenig Adressen viele Register anzusteuern und funktioniert im Prinzip überall ähnlich.

Dazu definiert man eine Adresse für das Auswahlregister (Indexregister) und eine weitere Adresse für das eigentliche Register (Datenregister). Um von einem Register zu lesen (schreiben), schreibt man den Index in das Indexregister und liest (schreibt) dann das Datenregister.

Für CGA ist 0x3D4 das Indexregister, 0x3D5 das Datenregister.

Wenn du ein Register nicht lesen kannst, weil die Hardware das nicht ermöglicht, kriegst du keine Fehlermeldung und niemand wird dich darüber informieren. Du bekommst einfach nur ungültige Werte.

YoshiX650

  • Gast
Gespeichert
« Antwort #3 am: 09. May 2014, 17:05 »
@Jidder
Das sieht so aus als ob ldi r16, (val1) das Register r16 mit dem Wert von der C++-Variable val1 gefüllt wird.
Hier out (port1),r16 wird dann der Wert von r16 in den Port (gesetzt durch die C++-Variable port1) ausgegeben wird.

    in (val2), (port2)
    ldi r17, (val2)
Schätzte einfach: in val2 Wert von port2 speichern, der dann ins Register r17 geladen wird

CPU: Denke x86
Compiler: Da C oder C++ Code denke ich hier gcc oder g++

Funktioniert das überhaupt? Ist das nicht AVR Programmierung?

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 09. May 2014, 17:37 »
Funktioniert das überhaupt? Ist das nicht AVR Programmierung?
Tjahaa ^^
Dieser Text wird unter jedem Beitrag angezeigt.

Martin Erhardt

  • Beiträge: 165
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 09. May 2014, 18:31 »
CPU: Denke x86 (...) Ist das nicht AVR Programmierung?
1. Du wiedersprichst dich, oder meinst du mit x86 nur die Entwicklungsumgebung.

2. Ist das eigentlich doch gar kein syntaktisch korrekter inline Assembler. Denn das Assembler kommt doch in anführungszeichen und in klammern und der austausch mit C Variablen funktioniert über die Doppelpunktschreibweise.

Also bei mir sehen INB und OUTB als Makros so aus https://github.com/MartinErhardt/Lizarx/blob/master/src/kernel/inc/HAL/x86/asm_inline.h ,was auch funktioniert , wobei ich da aber auch besser inline Funktionen draus machen sollte, wegen den Datentypen:
#define OUTB( PORT, DATA) asm volatile ("outb %0, %1" : : "a" ((uint8_t)DATA), "Nd" ((uint16_t)PORT));
#define INB( PORT,DATA ) asm ("inb %1, %0" : "=a" (DATA) : "Nd" (PORT));
« Letzte Änderung: 09. May 2014, 19:42 von Martin Erhardt »

Paula

  • Gast
Gespeichert
« Antwort #6 am: 09. May 2014, 18:54 »
1. Meinte eine 32-Bit CPU
2. Gibt es nicht viele unterschiedliche Methoden um Inline-Assembler zu nutzten?

EDIT: Wo wir grade bei Ports und I/O sind ...
... kann so was funktionieren?:

io.cpp
#define OUT    asm volatile("out (port1),(wert1)");
#define IUT    asm volatile("in (wert2),(port2)");

inline void out(unsigned port1, unsigned wert1)
{

   OUT;

}

inline void iut(unsigned port2, unsigned wert2)
{

    IUT;

    return wert2;

}

io.h
extern inline void out(unsigned port1, unsigned wert1);
extern inline void iut(unsigned port2, unsigned wert2);

« Letzte Änderung: 09. May 2014, 19:25 von Paula »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 09. May 2014, 19:45 »
2. Gibt es nicht viele unterschiedliche Methoden um Inline-Assembler zu nutzten?
Du musst trotzdem die richtige Methode verwenden, die im Handbuch des Compilers dokumentiert ist. Ich weiß nicht, wo du das mit den runden Klammern her hast, aber der erste Versuch sah ein wenig wie Code vom Microsoft Compiler aus. Ich nehme aber an, dass du GCC nutzt, und du musst dich deswegen an dessen Regeln halten.

EDIT: Wo wir grade bei Ports und I/O sind ...
... kann so was funktionieren?:
Nope.

Wenn du Martins Makros verwenden willst, und du deine Aufteilung in .cpp und .h behalten willst, muss deine io.cpp so aussehen:

// Beachte, dass ich das einfach aus seinem Post kopiert habe.
#define OUTB( PORT, DATA) asm volatile ("outb %0, %1" : : "a" ((uint8_t)DATA), "Nd" ((uint16_t)PORT));
#define INB( PORT,DATA ) asm ("inb %1, %0" : "=a" (DATA) : "Nd" (PORT));

// Beachte: Nicht inline!
void out(unsigned port1, unsigned wert1)
{
    return OUTB(port2, wert2);
}

void iut(unsigned port2, unsigned wert2)
{
    return INB(port2, wert2);
}

Das kryptische Zeug aus dem Inline Assembler ist hier dokumentiert: http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html und hier nochmal ein bisschen erläutert: http://www.lowlevel.eu/wiki/Inline-Assembler_mit_GCC

In die io.h kommt dann:

extern void out(unsigned port1, unsigned wert1);
extern void iut(unsigned port2, unsigned wert2);

Beachte, dass die Funktionen auch hier nicht inline sind.

Oder du kopierst einfach die beiden Zeilen von ihm in deine io.h und benennst die Makros um, wenn die unbedingt out und iut heißen sollen:

#define out( PORT, DATA) asm volatile ("outb %0, %1" : : "a" ((uint8_t)DATA), "Nd" ((uint16_t)PORT));
#define iut( PORT,DATA ) asm ("inb %1, %0" : "=a" (DATA) : "Nd" (PORT));

In die io.cpp kommt dann nichts bzw. die löscht du dann halt.

Und wenn es doch unbedingt inline-Funktionen sein soll, dann kannst du dir beispielsweise das hier mal durchlesen: http://openbook.galileocomputing.de/c_von_a_bis_z/009_c_funktionen_021.htm#mj333c4b82169d962e6176638f6644e310
« Letzte Änderung: 09. May 2014, 19:48 von Jidder »
Dieser Text wird unter jedem Beitrag angezeigt.

 

Einloggen