Gast
#546488
Guten Abend, ich suche eine kurze Doku in deutsch, wo der UART 16550 beschrieben wird. z.B. wieviel Register, Interrupt Handler usw.
|
Anzeige
|
UART 16550
Gast
#546488
Guten Abend, ich suche eine kurze Doku in deutsch, wo der UART 16550 beschrieben wird. z.B. wieviel Register, Interrupt Handler usw. Da das die Standard-UART jedes PCs ist (ganz alte verwendeten noch den Fifo-losen Vorgänger 16450 bzw. 8250), dürfte sie in PC-Hardware-Büchern wie "Data Becker - PC Intern" beschrieben sein. Was willst Du erreichen?
Gast
#546664
Hallo, ja und zwar möchte ich das ganze Vorgehen für die ISR bzw COM Interrupt Handler beschreiben.
//
// Saved register block passed to interrupt handlers registered
// with EtsSetInterruptHandler() and EtsSetExceptionHandler().
// These fields contain the register contents at the time of the
// interrupt. The interrupt service routine can modify the
// values in the passed structure in order to change the user
// registers on return from the interrupt.
//
// Note: The FS and GS registers are neither saved nor restored
// by the interrupt handler framework. If a user interrupt handler
// wants to use either of these registers, it must preserve them itself!
//
typedef struct tagETSINTREGS
{
DWORD Ebp; // [00]
DWORD Eax; // [04]
DWORD Ebx; // [08]
DWORD Ecx; // [12]
DWORD Edx; // [16]
DWORD Esi; // [20]
DWORD Edi; // [24]
DWORD Gs; // [28]
DWORD Ds; // [32]
DWORD Es; // [36]
DWORD IntNum; // [40]
DWORD Ecode; // [44]
(Zero if int w/o error code)
DWORD Eip; // [48]
DWORD Cs; // [52]
DWORD Eflags; // [56]
} ETSINTREGS, *PETSINTREGS;
//----------------------------------------------------------------------
-------
// EtsSetInterruptHandler - Install a C function as an interrupt handler
//
// This API installs a C function as an interrupt handler
// for the specified interrupt. The handler is entered as a normal
// C function (__cdecl calling sequence) with interrupts disabled
// and receives a pointer to the saved register set on the stack
// as its argument. The saved register set includes all general
// purpose registers, DS, ES, and EFLAGS. The FS and GS registers
// are neither saved nor restored; if the handler alters them, it
// must restore them itself before returning. The handler
// is expected to process the interrupt and may modify the
// saved register set on the stack if wishes to
// alter the context of the interrupted code. When the handler
function
// returns, the saved registers are popped off the stack and
// control returns to the interrupted code.
//
// The return value from the function is TRUE if successful or
FALSE
// if an error occurs.
//
//----------------------------------------------------------------------
-------
BOOL __cdecl EtsSetInterruptHandler(unsigned IntNumber,
PETSINTHANDLER pHandler);
Ich verstehe da das genau Vorgehen nicht.
Was geschieht bei diesem Funktionsaufruf genau:
>>EtsSetInterruptHandler( UartIntVecNum, CommIntHandler);
Ist der CommIntHandler ein Zeiger auf einen bestimmten STACK?
Diese Definitionen und Funktionen haben nichts mit der UART zu tun, sondern scheinen von irgendeinem Betriebssystem zu sein - versuchst Du Dich da gerade mit dem Win32 DDK?
Gast
#546778
Das ist ein Board mit einem ELAN-SC400 Prozessor von AMD. Ich tue mich sehr schwer mit dem Beschreiben der UART und dem COM Interrupt Handler.
Gast
#546781
Ich hab mal das ganze in ein Flussdiagramm dargestellt. Dies ist die initialisierung des Interrupt Handlers für COM1. Stimmt dies so?
Gast
#546838
Nicht ganz. Ich hab da noch aus den DOS Zeiten. http://www.ibrtses.com/turbopascal/stringdriver.html
Gast
#546842
Was meinst du mit "nicht ganz"? Ich weiss nicht wie ich das ganz Beschreiben(Flussdiagramm) soll? Was auch immer das da sein soll, das hat nach wie vor nichts mit der UART zu tun. Warum im Interrupthandler der Interruptcontroller befummelt wird, entzieht sich meinem Verständnis; die übliche Vorgehensweise in einem PC-Interrupthandler (unter DOS, also praktisch ohne Betriebssystem) sieht so aus: [int] Schnittstellenstatus aus UART auslesen (Warum hat die UART den Interrupt ausgelöst?) Je nach Schnittstellenstatus zu erledigende Dinge tun (Zeichen abholen und speichern oder Zeichen aus Sendepuffer lesen und an UART übertragen oder ...) Interruptcontroller die Beendigung der Interruptroutine mitteilen [reti] Es ist nicht erforderlich, in der Interruptroutine irgendwelche Interruptvektoren zu bestimmen, denn das geschieht schon implizit durch Aufruf der richtigen Interruptroutine.
Gast
#546863
Das obige Flussdiagramm soll ja nur die Installation des Interrupt Handler grafisch darstellen. Dann darf das aber nicht mit dem Namen der Interruptroutine beschriftet sein. Im übrigen wird auf PC-Hardware (unter DOS, also ohne Betriebssystem) ein Interrupthandler dadurch installiert, daß seine Startadresse in die Interrupttabelle im Arbeitsspeicher eingetragen wird. Danach muss nur noch dem Interruptcontroller mitgeteilt werden, daß es den Interrupthandler gibt (setzen/löschen des erforderlichen Bits) und fertig. Hier mal etwas Pascal-Quelltext: Interrupthandler
Die letzte Anweisung ist hier interessant. Und hier wird der Interruptvektor gesetzt:
Hier wird dem Interruptcontroller das Vorhandensein des Handlers mitgeteilt
(sowie bei der UART der Empfangsinterrupt freigeschaltet Die eigentliche Initialisierung der UART geschieht hier:
und ist natürlich vor dem Setzen und Initialisieren des Interrupthandlers durchzuführen. Auch wenn das Turbo-Pascal-Code ist, lässt sich das recht leicht auch in C ausdrücken. Was Du da gepostet hast, hat mit irgendeinem Betriebssystem oder irgendeiner betriebssystemartigen Umgebung zu tun.
Gast
#546892
Danke für die Hilfe!!! Ich habe es jetzt mal so in Sätzen zusammengefasst: Das Senden und Empfangen von der seriellen Schnittstelle funktioniert hier Interruptgesteuert. Dazu wurde ein Interrupt Handler eingerichtet, in diesem wird das Interrupt Identifikations Register ausgelesen. Über das Interrupt Identifikations Register, erfährt der Interrupt Controller, wegen welchem Ereignis der Interrupt ausgelöst wurde. Der Interrupt Handler wird dadurch installiert, dass seine Startadresse in die Interrupttabelle im Arbeitsspeicher eingetragen wird. Danach wird noch dem Interrupt Controller mitgeteilt, dass der Interrupt Handler existiert. Sobald der UART ein Datum empfängt bzw. ein Datum an die UART übergibt, wird ein Interrupt ausgelöst, dieser veranlasst, dass der Interrupt Handler gestartet wird. (Auf dem Board läuft ein 32Bit Echtzeitbetriebssystem, dort kann man auf die Win API zugreifen) > Über das Interrupt Identifikations Register, erfährt der Interrupt > Controller, wegen welchem Ereignis der Interrupt ausgelöst wurde. Nein. Der Interrupt-Controller hat damit nichts zu tun, durch das Auslesen des IIR erfährt der Interrupt-Handler (also Deine Software), welches Ereignis den Interrupt ausgelöst hat. Wann der/die UART Interrupts auslöst, wird durch die Initialisierung festgelegt, dort lassen sich Interrupts bei Datenempfang, leerem Senderegister, Änderungen der Handshakeleitungen etc. konfigurieren. Da Du aber ein Betriebssystem verwendest, werden etliche Details anders gehandhabt werden; das Betriebssystem selbst verwaltet die Behandlung des Interruptcontrollers und auch das Einrichten eines Interrupthandlers durch entsprechende Funktionsaufrufe. Daher sind die in den von mir geposteten Pascal-Sourcen getätigten Dinge nur mit äußerster Vorsicht zu genießen. Ist das 32-Bit-Echtzeitsystem zufälligerweise OnTime RTOS-32?
Gast
#546911
Ja ist das ist ein 32-Bit-Echtzeitsystem (OnTime RTOS-32)
Gast
#546912
>Ich habe es jetzt mal so in Sätzen zusammengefasst: Schön aber was soll das? >Das Senden und Empfangen von der seriellen Schnittstelle funktioniert >hier Interruptgesteuert... Brauchst du das für einen Vortrag oder willst du irgendwas programmieren? Wie das mit den Interrupts funktioniert wissen zumindest die die dir helfen könnten. Es ist nur unklar was du eigentlich willst. >Sobald der UART ein Datum empfängt bzw. ein Datum an die UART übergibt, >wird ein Interrupt ausgelöst, dieser veranlasst, dass der Interrupt >Handler gestartet wird. nicht ganz der 16c550 kann auch erst bei einem bestimmten Füllstand Interrupts auslösen. Also wenn mehrere Daten vorhanden sind. >(Auf dem Board läuft ein 32Bit Echtzeitbetriebssystem, dort kann man auf >die Win API zugreifen) Die erste richtige Info, wie heißt das Betriebssystem und was willst du eigentlich machen?
Gast
#546913
Sorry... Ja das ist ein 32-Bit-Echtzeitsystem (OnTime RTOS-32).
Gast
#546922
Als Betriebssoftware wird die ETS - TNT Embedded ToolSuite von PharLap eingesetzt. Diese ist ein 32 bit Real-Time Operating System (RTOS), das sich durch Unterstützung eines Teils der WIN32 API leicht in Windows Systeme integrieren lässt. Ich möchte eigentlich den ganzen Vorgang von der seriellen Kommunikation (UART) dokumentieren. Mein Programm benutzt ein Interrupt Handler für die serielle Schnittstelle. 1. Beschreibung UART 2. Initialiserung UART 3. Aktivierung Interrupt für COM 4. Erstellung eines Interrupt Handlers für COM 5. Funktionsweise des Interrupt Handlers
Gast
#546924
Das ganze soll eigentlich relativ kurz gefasst werden. > Ja das ist ein 32-Bit-Echtzeitsystem (OnTime RTOS-32). > Als Betriebssoftware wird die ETS - TNT Embedded ToolSuite > von PharLap eingesetzt. Was denn nun? Das sind zwei vollkommen unterschiedliche Paar Schuhe.
Gast
#546949
Fakt ist, das ist ein ein 32 bit Real-Time Operating System (RTOS). Dieses Programmiere ich mit Visual Studio 6.0 (C++).
Gast
#546954
Ich hab nochmals meinen Text einwenig verändert: Das Senden und Empfangen von der seriellen Schnittstelle funktioniert hier Interruptgesteuert. Dazu wurde ein Interrupt Handler eingerichtet, in diesem wird das Interrupt Identifikations Register ausgelesen. Über das Auslesen des Interrupt Identifikations Registers, erfährt der Interrupt Handler, welches Ereignis den Interrupt ausgelöst hat. Der Interrupt Handler wird dadurch installiert, indem seine Startadresse in die Interrupttabelle im Arbeitsspeicher eingetragen wird. Danach wird dem Interrupt Controller mitgeteilt, dass der Interrupt Handler existiert. Sobald der UART ein Datum empfängt bzw. ein Datum an die UART übergibt, wird ein Interrupt ausgelöst, dieser veranlasst, dass der Interrupt Handler gestartet wird. (Dies soll eigentlich einfach gehalten werden) > Fakt ist, das ist ein ein 32 bit Real-Time Operating System (RTOS). > Dieses Programmiere ich mit Visual Studio 6.0 (C++). Du wirst unglaubwürdig, da Du zwei unterschiedliche Produkte aufgeführt hast. Würdest Du tatsächlich mit einem davon arbeiten, wüsstest Du, wie es heißt. Trotzreaktionen sind hier wenig hilfreich. > > Ich programmiere unter Linux. > > > Ich programmiere unter Windows. > > Was denn nun? > > > Fakt ist, das ist ein 32-Bit Betriebssystem. Erkennst Du Deine "Argumentation" wieder? Sei's drum. > Sobald der UART ein Datum empfängt bzw. ein Datum an die UART übergibt, Den Sendeinterrupt (TXEMPT) solltest Du besser anders beschreiben. Sobald der UART ein in sein Senderegister geschriebenes Zeichen (trenne Dich vom unglücklichen "Datum"!) versendet hat, wird der "transmit register empty"-Interrupt ausgelöst, um zu signalisieren, daß ein neues Zeichen versendet werden kann.
Gast
#546995
Warum unglaubwürdig? Ich programmiere unter Windows. Linux habe ich hier nie verwendet. Mir geht es um das alg. Handling mit dem ganzen geraffel. Ich habe bereits dargelegt, daß es einen ganz erheblichen Unterschied macht, worunter/wofür man einen Interrupthandler schreibt - es ist was anderes, ob man einen Interrupthandler für RTOS-32 (das ist ein Produkt! Keine generische Bezeichnung) oder für Pharlap TNT ETS schreibt. Der Windows-/Linux-Vergleich ist eine Metapher für Deine Reaktion auf die Frage, wofür Du da was zu schreiben glaubst. Das Handling des ganzen Geraffels ist eben unterschiedlich und deswegen kommt es darauf an, die Rahmenbedingungen zu kennen und auch zu nennen. Dir aber scheint es wohl nur um einen Aufsatz oder dergleichen zu gehen ...
Gast
#547007
Ich habs jetzt so geschrieben: Sobald der UART ein in seinem Senderegister geschriebenes Zeichen versendet hat, wird „transmit holding register empty“- Interrupt ausgelöst, um zu signalisieren, dass ein neues Zeichen versendet werden kann. Im umgekehrten Fall, wenn ein Zeichen im Empfangsregister vorliegt, dann wird „receive data is available“- Interrupt ausgelöst, damit wird signalisiert dass ein neues Zeichen empfangen werden kann.
Gast
#547011
Ich habe eher das Gefühl, du machst einen Teil einer Belegarbeit an der Uni, die anderen haben es programmiert und da du Probleme dabei hattest, hast du dir den Dokumentationsteil rausgesucht. Wenns wirklich so sein sollte: Schlechte Wahl, das setzt nämlich erst recht voraus, daß du alles verstehst. Deine Bezeichnungen lassen erkennen, daß du in Hardwarenaher Programmierung nicht firm bist. >Ich habs jetzt so geschrieben: >... ist etwas besser, aber deutlicher wird es mit einem Statediagram und Text >dann wird „receive data is available“- Interrupt ausgelöst, >damit wird signalisiert dass ein neues Zeichen empfangen werden kann. das ist Müll, wenn du ein Zeichen bekommst solltest du es abholen
Gast
#547543
Ich hoffe das stimmt was ich hier geschrieben habe: Das Senden und Empfangen von der seriellen Schnittstelle funktioniert hier Interruptgesteuert. Dazu wurde ein Interrupt Handler eingerichtet, in diesem wird das Interrupt Status Register ausgelesen. Über das Auslesen des Interrupt Status Registers, erfährt der Interrupt Handler, welches Ereignis den Interrupt ausgelöst hat. Der Interrupt Handler wird dadurch installiert, indem seine Startadresse in die Interrupttabelle im Arbeitsspeicher eingetragen wird. Danach wird dem Interrupt Controller mitgeteilt, dass der Interrupt Handler existiert. Sobald der UART ein in seinem Senderegister geschriebenes Zeichen versendet hat, wird „transmit holding register empty“- Interrupt ausgelöst, um zu signalisieren, dass ein neues Zeichen versendet werden kann. Im umgekehrten Fall, wenn ein Zeichen im Empfangsregister vorliegt, wird „receive data is available“- Interrupt ausgelöst, damit kann nun das Zeichen vom Empfangsregister abgeholt werden.
Gast
#547873
> Danach wird dem Interrupt Controller mitgeteilt, dass der Interrupt > Handler existiert. Ich weiß ja nicht was da für ein Interruptcontroller drauf ist aber normalerweise wird der betreffende Interrupt nur freigeschaltet.
Gast
#550150
Es ist ein 8259 Controller. Der kann doch 15 Geräte verwllten oder?
void __cdecl CommIntHandler(ETSINTREGS *pRegs);
void COM(void)
{
...
UartIntVecNum = EtsPicGetIRQIntNumber(UartIRQNum);
// --> UartIntVecNum = 0x0C
....
EtsSetInterruptHandler( UartIntVecNum, CommIntHandler); // set handler
...
}
Ich hab da noch immer Probleme damit. Ich beschreibe es mal mit meinen
eigenen Worten.
1. UartIntVecNum = EtsPicGetIRQIntNumber(UartIRQNum);
--> Nr. von der Vectortabelle auslesen, ist hier 0x0C
(Warum Vectortabelle?)
2.EtsSetInterruptHandler( UartIntVecNum, CommIntHandler); // set handler
--> Interrupt Handler einrichten: 0x0C und Adresse vom Interrupt Handler
der Funktion übergeben. Dann passiert irgendwas im Stack.
Weiss nicht so ganz obn dies hier stimmt.
Gast
#550592
Ich verstehe das genau Zusammenspiel UART, Interrupt Controller, Interrupt Handler noch nicht ganz. Kann mir einer erklären wie es im Prinzip funktioniert?
Gast
#550614
Ein 8259 kann 8 Interrupts verwalten - man kann ihn aber auch kaskadieren und bekommt dann Weitere. Wie ein Interrupt abläuft: Byte wurde empfangen -> UART akiviert die IRQ-Leitung -> IRQController prüft, ob aktiviert -> IRQController aktiviert die INT-Leitung zum Prozessor -> wenn Interrupts dort freigeschaltet sind: Prozessor macht seinen aktuellen Befehl noch fertig, schreibt die aktuelle CS:IP Adresse auf den Stack und setzt die INTA-Leitung zum IRQController -> IRQController überträgt den Vector (Vectortabelle ist ein Array mit den Anfangsaddressen der Interrupthandler-Funktionen, Vector der Index eines Eintrages in dieser Tabelle) -> CPU springt die zum Vector passende Interrupthandler-Funktion an -> Interrupthandler fragt die Hardware ab -> UART deaktiviert seine IRQ-Leitung -> Interrupthandler macht ein IRET (oder wars RETI?) -> CPU macht da weiter wo sie unterbrochen wurde.
Gast
#550617
Gilt für den Realmode, im PM kann das teilweise anders aussehen.
Gast
#558462
Guten Abend, ich habe doch noch Probleme mit dem Interrupt Handler. Und zwar es wird doch zuerst die Vectornummer von der Schnittstelle COM1 (0x3F8) ausgelesen. Dies ist hier 0x0C. Dann wirdn doch der eigentliche Interrupt Handler installiert bzw. eingerichtet. Die Funktion EtsSetInterrupt Handler erhält zwei Parameter. 1. Parameter = Vectornummer 0x0C, 2. Parameter die Adresse vom Interrupt Handler. Ist das jetzt richtig so? Ich möchte nur diesen Vorgang beschreiben. Mir ist nun nicht ganz klar ob meine Aussage so stimmt.
Das steht in der Dokumentation des von Dir nach wie vor nicht genannten Betriebssystems. Wir können das nicht wissen.
Gast
#558748
2F8 und 3F8 sind IO adressen, wo das UART montiert ist. Was soll das Ganze ? Weder unter Linux, noch unter Windows schreibt jemand einen Interrupthandler. Dort ist die Thematik eine ganz andere. Wie manoevriert man in den Tiefen des verbockten Windows, ohne das alles abschmiert. Sogar kundige Spzialisten verbraten da schnell mal 2 Monate. Vergiss es. Intel hat einen schoenen Interruptcontroller gemacht, der kann Prioritaeten zuweisen und rotieren. Trotzdem wollte Microsoft was anderes und hat oben eine Software draufgesetzt die alles vermurkst. Als Einsteigelektuere sei das iAPX86 Manual von Intel empfohlen, Dort wird auch der 8259 beschrieben, und ein paar Interrupthandler sind da auch drin. Als naechstes waere das 386 Manual mit dem Protected mode empfohlen. Dort wurden die Interrupts virtualisiert und muessen durch trap gates. Seither hat sich interruptmaessig nicht mehr sehr viel fuer den Benutzer geaendert.
Gast
#558771
Das ist ein Webserverboard von PharLap. Es nutzt ETS ein 32 bit Echtzeit Betriebssystem und kann ein Teil der WIN32 API-Funktionen. Der Prozessor ist ein AMD-ELAN Prozessor mit 66 MHZ. Programmieren tue ich das ganze unter Visual Studio 6.0 mit C++. Und, hast Du mittlerweile mal in der Dokumentation nachgesehen? Die beschreibt, was die von Dir verwendete Funktion macht bzw. machen sollte. Hättest Du Deinen Aufsatz nicht eigentlich schon längst abgeben sollen?
Gast
#558816
Ne ne das dauert noch!
Gast
#558819
Ich habe die Beschreibungen zu dem entsprechenden Funktionen gefunden.
Ich hab da Probleme das ganze hier zu verstehen.
//
// Return the interrupt vector number which corresponds to the
// specified hardware IRQ. Assumes PC/AT mapping of 08h for IRQs 0-7
// and 70h for IRQs 8-15. Source is provided in
PHAREMB/EMBCUST/PCPIC.ASM.
//
// hardwareIRQNum is the desired IRQ number
//
// Returns the interrupt vector number which corresponds to the
// specified IRQ, or -1 if the specified IRQ is out of range.
//
int __cdecl EtsPicGetIRQIntNumber(int hardwareIRQNum);
//----------------------------------------------------------------------
-------
// EtsSetInterruptHandler - Install a C function as an interrupt handler
//
// This API installs a C function as an interrupt handler
// for the specified interrupt. The handler is entered as a normal
// C function (__cdecl calling sequence) with interrupts disabled
// and receives a pointer to the saved register set on the stack
// as its argument. The saved register set includes all general
// purpose registers, DS, ES, and EFLAGS. The FS and GS registers
// are neither saved nor restored; if the handler alters them, it
// must restore them itself before returning. The handler
// is expected to process the interrupt and may modify the
// saved register set on the stack if wishes to
// alter the context of the interrupted code. When the handler
// function
// returns, the saved registers are popped off the stack and
// control returns to the interrupted code.
//
// The return value from the function is TRUE if successful or
FALSE
// if an error occurs.
//
//----------------------------------------------------------------------
-------
BOOL __cdecl EtsSetInterruptHandler(unsigned IntNumber,
PETSINTHANDLER pHandler);
//
// Saved register block passed to interrupt handlers registered
// with EtsSetInterruptHandler() and EtsSetExceptionHandler().
// These fields contain the register contents at the time of the
// interrupt. The interrupt service routine can modify the
// values in the passed structure in order to change the user
// registers on return from the interrupt.
//
// Note: The FS and GS registers are neither saved nor restored
// by the interrupt handler framework. If a user interrupt handler
// wants to use either of these registers, it must preserve them itself!
//
typedef struct tagETSINTREGS
{
DWORD Ebp; // [00]
DWORD Eax; // [04]
DWORD Ebx; // [08]
DWORD Ecx; // [12]
DWORD Edx; // [16]
DWORD Esi; // [20]
DWORD Edi; // [24]
DWORD Gs; // [28]
DWORD Ds; // [32]
DWORD Es; // [36]
DWORD IntNum; // [40]
DWORD Ecode; // [44] (Zero if int w/o error code)
DWORD Eip; // [48]
DWORD Cs; // [52]
DWORD Eflags; // [56]
} ETSINTREGS, *PETSINTREGS;
void __cdecl CommIntHandler(ETSINTREGS *pRegs);
Und? Was erwartest Du jetzt? Soll Dir das jemand ins Deutsche übersetzen? Oder soll Dir jemand dabei helfen, eine Frage zu stellen? Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|