Ich würde gerne wissen, was passieren würde, wenn ein serielles Terminal eine große Datenmenge an einen PIC / AVR senden würde, beispielsweise über einen USART-Interrupt, der dann durch einen Interrupt mit höherer Priorität wie einen Timer unterbrochen würde, der die Daten verschieben würde überweisen. Würden die Daten verloren gehen? Oder hat das serielle Terminal vor dem Senden einen Puffer und hält die Daten fest, bis wir zum Empfangsinterrupt zurückkehren?
Zum Beispiel verwende ich einen atxmega128a1 und verwende diesen Interrupt, um Bytes zu empfangen:
//interrupt to receive a byte
ISR(USARTC0_RXC_vect){ //ISR for when receive flag is set
if(FIFO_Put(&RxFIFO, USARTC0_DATA)){ //put data into receive FIFO
USARTC0_STATUS |= USART_RXCIF_bm; //write 1 to clear bit
}
}
Wenn ich eine große Menge Bytes gleichzeitig über ein serielles Terminal sende, wird dieser Interrupt viele Male ausgelöst, um jedes Byte zu empfangen.
Ich habe auch einen Timer-Interrupt mit höherer Priorität, der lange dauern kann:
ISR(TCC0_OVF_vect){
AXISid n = X;
static BOOL cycle;
TimerAxisInterrupt(n, &cycle);
}
Um es noch einmal zu wiederholen, meine Frage lautet: Wenn der Interrupt mit höherer Priorität während einer großen Datenempfangsübertragung auftritt, gehen Daten verloren?
Falls relevant: Ich sende die USART-Daten über RS232 mit einem max3232-Logikkonverter. Ich habe die Handshaking-Leitungen und die RTS-CTS-Leitungen so geloopt, dass ich nur die Rx- und Tx-Leitungen verwende.
Unter der Annahme, dass kein Handshaking durchgeführt wird, verlieren Sie keine Daten, wenn der UART-Interrupt oft genug bedient wird, um zu verhindern, dass der Hardwarepuffer überläuft. Normalerweise ist das mindestens ein Zeichen, aber je nach Chip können es viele Zeichen sein (leistungsstärkere Chips haben tendenziell mehr Bytes Puffer).
Meiner Erfahrung nach können Sie sich nicht auf XON/XOFF-Handshaking verlassen, wenn die Puffergröße klein ist und der Absender ein PC ist – es kann einige Zeichen senden, bevor es dazu kommt, den Fluss zu unterbrechen.
Wenn also die Puffertiefe ein Zeichen beträgt und die Baudrate so ist, dass ein Zeichen 1 ms dauert, dürfen Sie in Ihrem Interrupt mit höherer Priorität nicht mehr als 1 ms wegnehmen, da Sie sonst Daten verlieren könnten (etwas weniger, weil Sie dies berücksichtigen müssen). Zeit in der UART ISR, um zu antworten und das eingehende Zeichen aus dem Puffer zu pflücken, und Sie sollten auch die Situation berücksichtigen, in der der UART-Interrupt ausgeführt wird, wenn er unterbrochen wird (sehen Sie sich an, wie er kurz vor und unmittelbar nach dem Lesen des eingehenden Zeichens auftritt).
Es gibt verschiedene Möglichkeiten, mit der Situation umzugehen, in der Sie zwei Interrupts mit schneller Antwort haben müssen. Ein Weg (normalerweise der beste Weg) wäre, nicht so viel in Ihrem Timer-Interrupt zu tun - Interrupt-Service-Routinen werden am besten verwendet, um schnell ein- und auszusteigen). Eine andere wäre, einen Puffer im Speicher zu implementieren und Ihren UART-Interrupt auf die höchste Priorität zu setzen (stecken Sie einfach das empfangene Zeichen in eine kreisförmige Warteschlange, erhöhen Sie die Modulo-Puffergröße des Schreibzeigers und kehren Sie zurück - Sie können die Gleichheit überprüfen, wenn Lese- und Schreibzeiger auf sehen, ob die Warteschlange leer ist). Abhängig von den Anforderungen und dem Prozessor gibt es noch andere Ansätze - vielleicht brauchen Sie die Timer-Routine nicht mit so hoher Priorität, oder vielleicht ändern Sie die Priorität dynamisch, sobald sie die kritischen Dinge erledigt hat, und ändern sie dann wieder auf hohe Priorität ,
Leistungsstärkere Prozessoren haben größere Puffer oder DMA, die es dem Prozessor ermöglichen, für sehr viele Zeichen herumzulaufen, bevor Datenverlust auftritt.
TL;DR Sie können dies vorhersagen, indem Sie Ihren Timer-Interrupt- und ISR-Interrupt-Code profilieren, um die maximale Ausführungszeit zu finden und mit der minimalen Zeit zum Füllen des Puffers (bei maximaler Baudrate) zu vergleichen.
AlphaGoku
Spehro Pefhany
AlphaGoku
Sam Bucca
Spehro Pefhany
Superkatze