UART-Polling vs. Interrupt

Ich habe zwei UARTPorts an einem MSP430, die Daten zwischen einem Host-Controller (Freescale IMX6) und potenziellen Geräten streamen müssen, die auf der anderen Seite angeschlossen werden können. Der Host-Controller kommuniziert (Lesen/Schreiben) von Daten mit MSP430(einschließlich serieller Daten von Geräten) über einen I2C-Bus.

IMX6 --writes I2C--> MSP430 --writes `UART`0--> Device 0
IMX6 <---reads I2C-- MSP430 <---reads `UART`0-- Device 0

IMX6 --writes I2C--> MSP430 --writes `UART`1--> Device 1
IMX6 <---reads I2C-- MSP430 <---reads `UART`1-- Device 1

Derzeit sind UARTEmpfangsvorgänge interruptbasiert auf der MSP430. Wenn ein Byte eintrifft, unterbricht es den MSP und wirft das Byte in einen Ringpuffer.

UARTSchreibvorgänge hingegen basieren auf Abfragen. In meiner Hauptschleife habe ich einen UART_process, der ausgeführt wird. Dabei überprüfe ich, ob der UART TXHardware-Single-Byte-Buffer für ein Byte bereit ist. Wenn ja, schreibe ich ein neues Byte ein, setze die Übertragung und verlasse die Funktion. Bei dieser Funktionalität kann es (zum Beispiel) 1 Millisekunde dauern, bis ich ein weiteres Byte an das UARTGerät sende, obwohl die MSPs UARTmöglicherweise viel früher bereit waren, ein weiteres Byte zu übertragen.

Meine Sorge ist, dass, wenn ich 2 UARTPorts verwalten muss MSP430, die beide mit 115200Baud laufen, das Schreiben eines Bytes 1ms(möglicherweise etwas mehr oder weniger) für das Gerät ausreicht? Die Baudrate wird 115,200offensichtlich noch übertragen, aber die Bytes werden langsam übertragen. Einige schnelle und grobe Berechnungen:

  • 1 Bit bei 115.200 dauert etwa 8 µs.
  • 1 Byte @ 115.200 dauert ungefähr (8 µs * 8 Bits) = 64 µs.

Wie Sie sehen, kann also ein neues Byte vom UARTTreiber übertragen werden, sagen wir alle 100 µs. Wenn ich alle 1 ms ein Byte sende, übertrage ich im Vergleich zur potenziellen Höchstgeschwindigkeit nicht sehr schnell (etwa 1/10) zum Gerät.

Ich möchte nicht UARTper Interrupt senden, weil ich befürchte, dass 2 UARTS mit beiden RXund TXInterrupt-basiert meine CPU übernehmen könnte. Ich habe andere wichtige Dinge, die ich auch auf der tue MSP430. Wie das ständige Akzeptieren von I2C-Nachrichten über Interrupts und das Handhaben eines Timer-Interrupt-basierten IR-Prozesses.

Ich habe überlegt, einen einfachen Aufgabenplaner hinzuzufügen. Aber das würde nicht viel zur Beschleunigung beitragen, da ich den Taskplaner wahrscheinlich in 1-ms-Intervallen ausführen würde. Dies würde nur UARTalle 1 ms einen Byte-Schreibvorgang garantieren (was ich sowieso oben vorgeschlagen habe). Die andere Option besteht darin, die Verwendung des DMA mit der UARTÜbertragung zu prüfen. Aber ich möchte diese Optionen nur ausloten, wenn es sein muss.

Sind Ihrer Erfahrung nach die meisten UARTGeräte/Implementierungen damit einverstanden, Bytes mit einer langsamen Rate im Vergleich zur Baudrate zu empfangen? Irgendwelche allgemeinen Vorschläge? Lassen Sie mich wissen, wenn ich mich in irgendwelchen Punkten unklar ausgedrückt habe. Danke!

Ein Byte benötigt 10 Bitzeiten mit Start- und Stoppbit.
Können Sie den Tx-Interrupt mit einer niedrigeren Priorität ausführen (ich kenne MSP430 nicht)? Warum lässt du den Tx in der Hauptschleife nur jede Millisekunde laufen?
Interrupt-Prioritäten können auf dem von mir verwendeten Chip (MSP430FR5739) nicht geändert werden. Prioritäten basieren auf der Vektoradresse. Je niedriger die Adresse, desto höher die Priorität. Ich habe den Tx in der Hauptschleife, wo er zweimal pro Hauptschleifenzyklus verarbeitet wird. Es wird wahrscheinlich die meiste Zeit etwa alle 300 us gewartet. Aber es gab Zeiten, in denen es länger gedauert hat (wenn ich eine starke Interrupt-Last von I2C und einem Infrarot-Emitter-Timer habe). Die 1 ms war irgendwie willkürlich. Ich denke, ich werde einfach zum Interrupt-basierten Senden übergehen (ermutigt von Gustavo).
Übrigens, guter Punkt über die 10 Bits pro Byte. Ich habe mir nie die Mühe gemacht, die genaue Bitanzahl für UART-Byteübertragungen nachzuschlagen!
Vielleicht ist Ihr MSP430 am Limit und Sie brauchen etwas Besseres.

Antworten (3)

Ja, die meiste Software, die Daten über einen asynchronen Kanal empfängt, ist unabhängig davon, wie schnell die Daten ankommen (bis zu dem Punkt, an dem Timeouts ins Spiel kommen). Für den Empfänger ist Ihre Situation vergleichbar mit einer Baudrate, die 1char/ms zulässt.

Dies beantwortet am direktesten meine Hauptfrage. Auch die anderen Kommentare waren sehr informativ.

Interrupt-basierte Routinen übernehmen die CPU nicht, es sei denn, Sie lassen sie zu.

Ich habe viele MSP430-uart-Treiber geschrieben, und der Weg, sich TX zu nähern, besteht darin, die ISR dazu zu bringen, die Bytes zu senden. Lösen Sie das Interrupt-Flag aus und lassen Sie dann die ISR das Senden der Bytes aus einem Puffer verwalten. Sie benötigen ein paar Variablen im Speicher, um dies zu verwalten, aber es funktioniert sehr gut.

Denken Sie daran, dass Sie es sind, der den ISR auslöst, um die Daten zu senden. Sie wissen, wie viele Bytes zu senden sind. Die ISR ist ziemlich schnell, daher gibt es keine Übernahme.

Sie verwenden Abfragen, die tatsächlich Ihre CPU-Zeit verbrauchen. Kein Grund dafür. Unterbrechungen sollten nicht gefürchtet, sondern gemeistert werden.

Sie haben nicht erwähnt, welchen MSP430 Sie verwenden, aber ich habe viele MSP430-basierte Designs mit mehreren Schnittstellen ausgeführt und hatte nie Probleme mit Interrupts, die die CPU laden. Tatsächlich waren die Kunden begeistert, dass Probleme, die sie zuvor aufgrund von Umfragen und anderen Dingen hatten, verschwunden waren, als ich sie neu gestaltete.

Sie haben RTOS erwähnt. Je nach MSP430 ist dies möglicherweise nicht praktikabel und Sie benötigen es nicht. Ein RTOS wird diese Art von Problemen nicht lösen.

Ich verwende oft Polling für die Übertragung und Interrupts für den Empfang; Ob dieser Ansatz angemessen ist, hängt davon ab, welche Art von Pufferung der UART hat und wie Ihre Abfragerate mit der Rate verglichen wird, mit der Sie tatsächlich Daten senden müssen.

Einige Chips haben einen UART, der erfordert, dass ein Byte vollständig übertragen wird, bevor der Code das nächste Byte laden kann. Die meisten Chips erlauben dem Prozessor, zusätzlich zu dem gerade ausgetakteten Byte mindestens ein Byte zu laden. Einige können dem Prozessor erlauben, 16 Bytes oder sogar mehr vorab zu laden.

Wenn Ihr Port auf 115.200 Baud eingestellt ist, Ihr UART ein Zeichen plus das zu übertragende Zeichen puffern kann und Ihr Abfrageintervall 100 us beträgt, können Sie wahrscheinlich fast, aber nicht ganz kontinuierlich übertragen, da Sie manchmal abfragen wann Der UART ist fast fertig mit der Übertragung eines Bytes, Sie laden ein Byte, und dieses Byte wird vor Ihrem nächsten Abfragevorgang vollständig gesendet. Wenn Ihr Polling-Intervall viel länger als 100 us ist und der Chip wie beschrieben ist, können Sie wahrscheinlich zwei Zeichen pro Polling-Intervall senden; ob das angemessen ist, hängt von Ihrer Anwendung ab.