Hallo,
ich verwende bei meinem STM32F767 mehrere UARTS. Bei einem nutze ich den
Callback für empfangene Daten (jeweils 1 Byte). Nach dem Auswerten des
Bytes wird der Empfang des nächsten Bytes gleich wieder angestoßen.
Ca. 1 Mal in der Woche bleibt das Ganze hängen (es werden ca. 600.000
Telegramme pro Woche empfangen). Den Grund habe ich nun gefunden, denn
HAL_UART_Receive_IT liefert BUSY zurück. Aber warum? Was kann dazu
führen, daß er busy ist? Es wurde ja zuvor nur 1 Byte empfangen und bis
er das ausgewertet hat, sollte doch ein weiteres Freischalten gehen?
Kenne mich mit der HAL von ST nicht aus, aber könnte es sein dass in
diesem Zustand irgendwelche Fehlerbits in den Registern gesetzt sind.
Also Parity-, Frame-, Overrunerror oder ähnliches?
Edit:Typo
/* Check that a Rx process is not already ongoing */
4
if(huart->RxState==HAL_UART_STATE_READY)
5
{
6
....//diverse Befehle
7
returnHAL_OK;
8
}
9
else
10
{
11
returnHAL_BUSY;
12
}
13
}
Also ist "huart->RxState == HAL_UART_STATE_READY" nicht erfüllt. Aber
warum? Welche Register könnte ich im Fehlerfall in meinem Fehlerspeicher
sichern, um den Fehler einzugrenzen?
Wie ist das eigentlich, wenn zu diesem Zeitpunkt ein Interrupt einer
höher priorisierten Schnittstelle kommt? Kann das dazu führen, daß dann
busy kommt?
Georg schrieb:> Ich nehme an das Interrupt Flag wird in der ISR sofort> zurück gestzt? Dann würde ich die Interrupt Priorität erhöhen und> schauen ob das was bringt ...
Das dumme ist, daß sich der Fehler erst nach einigen Tagen bemerkbar
macht. Kann auch mal 2-3 Wochen laufen. Daher ist die Fehlereingrenzung
schwierig.
Du kannst in der IDE suchen, wo huart->RxState überall gesetzt wird.
Mit STRG+H gibst du die gesuchte Variable ein und klickst auf search.
Ich habe ein Bild angehängt.
Nach dem Empfang eines Bytes wird RxState in der Funktion
UART_RxISR_8BIT wieder zurück auf STATE_READY gesetzt. Des Weiteren
werden die Interruptflags dort zurückgesetzt.
Erst danach wird deine Callback-Funktion aufgerufen.
-> Sehr merkwürdig das ganze.
Mich hats gestern übrigens total geärgert, dass man den RX-Interrupt
durch die Funktion TRANSMIT_IT jedesmal anstoßen muss.
Danke, jetzt habe ich es auch gefunden:
huart->RxState = HAL_UART_STATE_READY; // Ready setzen
HAL_UART_RxCpltCallback(huart); // Callback aufrufen
Der Callback wird ja erst aufgerufen, wenn State Ready ist. warum das
dann ab und zu schief läuft, ist mir ein Rätsel.
Du schreibst ja, daß du mehrere UARTs verwendest. Kannst du sicher
ausschliessen, daß du nicht an irgendeiner Stelle versehentlich das
falsche UART-Handle übergibts?
Das würde zumindest dieses Verhalten erklären.
Vielleicht nochmal als Inspiration:
Bei meinem UART-Code habe ich sowas noch nie beobachten können.
Beitrag "[STM32/HAL] simples U(S)ART-Library"
Harry L. schrieb:> Du schreibst ja, daß du mehrere UARTs verwendest. Kannst du sicher> ausschliessen, daß du nicht an irgendeiner Stelle versehentlich das> falsche UART-Handle übergibts?> Das würde zumindest dieses Verhalten erklären.
huart7 bzw. huart_knx wird für den Empfang nur an 2 Stellen verwendet:
- beim Initialisieren des Programms
- nach dem Empfang der einzelnen Bytes
Micha schrieb:> Harry L. schrieb:>> Du schreibst ja, daß du mehrere UARTs verwendest. Kannst du sicher>> ausschliessen, daß du nicht an irgendeiner Stelle versehentlich das>> falsche UART-Handle übergibts?>> Das würde zumindest dieses Verhalten erklären.>> huart7 bzw. huart_knx wird für den Empfang nur an 2 Stellen verwendet:> - beim Initialisieren des Programms> - nach dem Empfang der einzelnen Bytes
Und du bist dir ganz sicher, dass diese Instanz nicht woanders noch
verwendet wird?
Kannst ja mal per STRG+H prüfen, ob du es ausversehen noch woanders
verwendest :)
Ali K. schrieb:> Und du bist dir ganz sicher, dass diese Instanz nicht woanders noch> verwendet wird?> Kannst ja mal per STRG+H prüfen, ob du es ausversehen noch woanders> verwendest :)
Anbei ein Bild, wo Interrupt-gesteuerter Empfang angestoßen wird.
Einziger Unterschied ist, daß ich einmal huart7 und huart_knx
geschrieben habe. Ist aber durch defines identisch:
#define huart_knx huart7
#define UART_KNX UART7
Hmm...
also mir gehen die Ideen aus.
Du könntest höchstens noch die Variable huart->RxState abfragen bzw.
tracen, wenn ein HAL_BUSY zurückgegeben wird.
Hab mir jetzt nur den vom TE geposteten Code angeschaut. Könnte es sein,
dass das Empfangen per Interrupt in der HAL nicht mehr vorgesehen ist,
wenn das nächste Byte bereits angekommen ist?
In HAL_UART_Receive_IT(...) heißt es (siehe Kommentar) ja:
1
/* Check that a Rx process is not already ongoing */
2
if(huart->RxState==HAL_UART_STATE_READY)
"already ongoing" verstehe ich so, dass das nächste Byte schon da ist.
Vielleicht ist auch nur ein kurzer Zeitraum "gesperrt" zwischen Empfang
in der HAL und Verarbeitung* durch die HAL. *Es scheint ja so, dass man
nicht nur einzelne Byte abholen kann.
Thorsten M. schrieb:> Es scheint ja so, dass man nicht nur einzelne Byte abholen kann
Die Anzahl der Bytes wird beim Aufruf angegeben. Ich verwende 1, da die
Länge von der jeweiligen Nachricht abhängig ist.
Blos wie macht die HAL das mit mehreren Bytes wenn angegeben? Wenn mit
DMA, dann wird es problematisch sein, wenn bereits ein Byte im
Empfangsbuffer liegt. Das Busy-Flag könnte das absichern. Meine
Vermutung war eben, dass deine Verarbeitung (des Bytes) sporadisch zu
lange dauert und dann das nächste schon angekommen ist, was dann ein
Busy signalisiert.
Thorsten M. schrieb:> Meine> Vermutung war eben, dass deine Verarbeitung (des Bytes) sporadisch zu> lange dauert und dann das nächste schon angekommen ist, was dann ein> Busy signalisiert.
Da musst du bei einem F7 aber schon ne Menge Radau machen, damit sowas
passiert.
Das einschieben in einen FiFo wird dazu sicher nicht reichen.
Und wenn man sich bei der Vergabe der Interrupt-Prioritäten nicht allzu
dusselig anstellt werden auch Unterbrechungen durch andere Interrupts
sicher nicht zum Problem - erst recht nicht bei einem doch recht lahmen
UART.
Thorsten M. schrieb:> "already ongoing" verstehe ich so, dass das nächste Byte schon da ist.> Vielleicht ist auch nur ein kurzer Zeitraum "gesperrt" zwischen Empfang> in der HAL und Verarbeitung* durch die HAL. *Es scheint ja so, dass man> nicht nur einzelne Byte abholen kann.
Ich vermute, daß dann die Bytes verloren gehen, wenn man zu spät wieder
freigibt. Busy kann er eigentlich nicht sein, denn wenn kein Empfang für
ein neues Byte freigegeben wurde, kann er auch nicht damit beschäftigt
sein.
Ich denke, bis ich das erste Byte in der Initialisierung freigebe, sind
schon ein paar Byte von der Schnittstelle vom KNX gekommen. Wenn dann
schon busy kommen würde, hätte ich da ja schon das Problem und er würde
nie was empfangen. Wenn nicht freigeschaltet, werden alle Bytes
ignoriert- so meine Vermutung. Baudrate ist übrigens 19200, sollte daher
kein Problem machen.
Ich werde morgen mal schauen, daß ich die neusten STM-HAL´s drauf
spiele. IDE (Segger) ist auch noch eine ältere Version (5.50d). Mal
sehen, ob das Problem dann weg ist. Kurios ist, daß ich das Problem nur
bei UART 7 habe. Bei einem anderen UART hängt eine Wetterstation dran,
die jede Sekunde Daten sendet. Da hatte ich noch nie ein derartiges
Problem. Hat ebenfalls 19200 Baud.