Hi,
ich beschäftige mich grad mit dem UART 16550.
http://www.national.com/ds/PC/PC16550D.pdf
Der UART unterstützt einen ReceiveLineStatus-Interrupt, der ausgelöst
wird, wenn das auszulesende Byte im FIFO einen Fehler hat,
beispielsweise einen Paritätsfehler. Der RLS-IRQ hat die höchste
Priorität (wenn freigeschalten).
Der RDA-Interrupt wird ausgelöst, wenn eine einstellbare Anzahl an Bytes
im Rx-FIFO erreicht ist. Dieser IRQ ist gedacht, um die Daten blockweise
aus dem FIFO zu holen und sich somit byteweises Auslösen der
Interrupt-Service-Routine zu sparen.
Ich stell mir grad die Frage ob es Sinn macht, den RLS-IRQ und RDA-IRQ
gemeinsam zu verwenden, bzw. ob das überhaupt möglich ist. Wenn
beispielsweise der RDA-IRQ ausgelöst wird und die Daten als Block
abgeholt werden, also in einer Schleife innerhalb der ISR, kann der
RLS-IRQ zwar auftreten, wird aber nicht bedient, weil ja der RDA-Teil
der ISR abgearbeitet wird, und das fehlerhafte Byte enthalten ist.
Das heisst dann eigentlich, dass das Handling für Paritätsfehler
etc.muss in den RDA-Teil der ISR und den RLS-IRQ kann man ignorieren.
Der RLS-IRQ macht nur Sinn, wenn man den UART so einstellt, dass er
bereits bei einem einzigen Byte im Rx-FIFO den RDA-IRQ auslöst. Oder
sehe ich etwas falsch?
Ich möcht nur sicher sein, dass ich's richtig verstanden hab und somit
die ISR klein und einfach halten kann :)
Ralf
Ralf schrieb:> Der RLS-IRQ macht nur Sinn, wenn man den UART so einstellt, dass er> bereits bei einem einzigen Byte im Rx-FIFO den RDA-IRQ auslöst. Oder> sehe ich etwas falsch?
Es ist umgekehrt. Wenn nur ein Byte kommt und das einen Fehler hat,
kommt kein FIFO Interrupt, der RLS schon.
Ich würde beide scharf schalten, und in der Service-Routine die Status
Bits abarbeiten, bis alle erledigt sind. Was man tut, wenn z.B. ein
Parityfehler aufgetreten ist, hängt von deiner Anwendung ab.
MfG Klaus
Hi Klaus,
> Es ist umgekehrt. Wenn nur ein Byte kommt und das einen Fehler hat,> kommt kein FIFO Interrupt, der RLS schon.
Okay, das stimmt. Aber wenn das Byte in einem Block enthalten ist,
bemerk ich's auch erst im RDA-Teil der ISR.
> Ich würde beide scharf schalten, und in der Service-Routine die Status> Bits abarbeiten, bis alle erledigt sind. Was man tut, wenn z.B. ein> Parityfehler aufgetreten ist, hängt von deiner Anwendung ab.
Mmmh, okay, ich glaub ich muss mir mal ein Flussdiagramm zeichnen und
schauen, was rauskommt :)
Ralf
Ralf schrieb:> Mmmh, okay, ich glaub ich muss mir mal ein Flussdiagramm zeichnen und> schauen, was rauskommt :)
Gute Idee. Bei komplexen Bausteinen, die mehrere Interruptquellen, aber
nur einen Vector haben, baue ich einen Loop über alle Statusbits und
arbeite sie ab, bis alle aus sind. Wenn man das FIFO ausgelesen hat, ist
möglicherweise schon ein neues Byte da, das kann man gleich mit
erledigen. Bei FIFOs ein Timeout nicht vergessen, sonst bleibt
möglicherweise etwas stecken, das erst bei der nächsten Übertragung raus
kommt.
MfG Klaus
Klaus schrieb:
> Bei komplexen Bausteinen, die mehrere Interruptquellen, aber> nur einen Vector haben, baue ich einen Loop über alle Statusbits und> arbeite sie ab, bis alle aus sind.
Okay, das hätte ich eben im RDA-Teil gemacht, um die Fehler zu erkennen.
> Wenn man das FIFO ausgelesen hat, ist möglicherweise schon ein neues Byte> da, das kann man gleich mit erledigen.
Meine Schleife liest den FIFO solange aus, wie das RDA-Flags des
LineStatus-Registers gesetzt ist.
> Bei FIFOs ein Timeout nicht vergessen, sonst bleibt möglicherweise etwas> stecken, das erst bei der nächsten Übertragung raus kommt.
Du meinst den CharacterTimeOut-Interrupt (CTI)?
Ralf
> Ich kenn jetzt den 16550 nicht so, aber das klingt gut.
:) Der CTI wird ausgelöst, wenn sich Daten im Rx-FIFO befinden und sich
über eine gewisse Zeit nichts mehr im FIFO getan hat, weder auslesen
noch empfangen.
Das soll dazu dienen, empfangene Blöcke die nicht dem eingestellten
Trigger-Level entsprechen, also kleiner sind, auslesen zu können.
Ralf