Forum: Mikrocontroller und Digitale Elektronik UART Receive Interrupt mit Freertos


von Eros S. (dretox)


Angehängte Dateien:

Lesenswert?

Hallo zusammen

Ich bin neu im Bereich FreeRTOS und versuche aktuell meine API 
umzustrukturieren und mit dem OS der STM32 HAL zu arbeiten. Ich benutze 
ein STM32F401RE Nucleo Board und arbeite mit der Standardkonfiguration 
des HAL aus der CubeIDE.

Nun zu meinem Problem. Ich habe einen Pin Change Interrupt sowie einen 
UART Interrupt konfiguriert. Ersterer funktioniert wunderbar, die ISR 
wird sofort aufgerufen wenn ich den Pin Change über einen Taster 
auslöse. Die UART ISR wird aber nie aufgerufen, wenn ich versuche 
Zeichen über die Schnittstelle zu empfangen. Schalte ich das OS aus, 
funktioniert die Schnittstelle einwandfrei.

Ich vermute ein Problem bzw. eine falsch konfigurierte Interrupt 
Priorität. Was mich allerdings stutzig macht: PCINT und UART Interrupt 
haben dieselbe Priorität, der Pin Change löst den Interrupt aus, die 
UART Empfangs ISR wird nie ausgelöst.

Ich hab da irgendwo eine Lücke. Woran könnte das liegen?

von Harry L. (mysth)


Lesenswert?

Schau mal hier:
Beitrag "[STM32/HAL] simples U(S)ART-Library"

Das kann auch FreeRTOS.

von Joe J. (j_955)


Lesenswert?

Na ich würde eher auf die Konfiguration ST wetten...Das einzige imho, 
das in Sachen Interrupte bei FreeRTOS sinnvoll konfigurierbar ist, ist 
der HAL Interrupt. Die Konfiguration sorgt dafür, das ein Interrupt ab 
Level X auch den Scheduler unterbrechen darf...Aber dafür darf in 
Interrupten über diesem konfigurierten Level keine FreeRTOS API 
verwendet werden.

Such mal nach:
configMAX_SYSCALL_INTERRUPT_PRIORITY

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Eros S. schrieb:
> Ich vermute ein Problem bzw. eine falsch konfigurierte Interrupt
> Priorität.

Priorität spielt keine Rolle sofern nicht ein anderer Interrupt 
permanent alles blockiert.

Unterbrich das Programm mal im Debugger in dem Moment, in dem eigentlich 
der Interrupt kommen sollte. Wenn sich das Programm nicht in einem 
Interrupt Handler befindet und außerdem BASEPRI=0 und PRIMASK=0 (in der 
Registeransicht prüfen) sind, sollte der Interrupt auslösen, unabhängig 
von der Priorität.

Wenn er dennoch nicht auslöst, liegt der Fehler im Code.

von Malte _. (malte) Benutzerseite


Lesenswert?

Die Priorität des FreeRTOS ISR darf nicht "wichtiger" als die Priorität 
irgend eines anderen ISRs sein. Sonst kommt es dazu, dass der FreeRTOS 
ISR auf den anderen ISR genested wird. Und wenn dann der FreeRTOS 
Scheduler versucht die Task zu wechseln schaltet der falsch den drunter 
liegeneden ISR Stack um. Das erkennt der Cortex-M interessanterweise in 
Hardware und wirft eine Exception ich meine ein Usage Fault. Lässt sich 
in den Status Registern auch diagnostizieren, ob das der Fall ist.

Ist ein recht mieser Fehler, da das recht lange gut läuft, solange eben 
keine zwei ISRs gleichzeig auftreten.

Möchte man den FreeRTOS Scheduler wichtier als irgend einen unwichtigen 
ISR machen, müsste man mit Subprioritäten arbeiten. Leider unterstützt 
FreeRTOS diese jedoch nicht...

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Malte _. schrieb:
> Möchte man den FreeRTOS Scheduler wichtier als irgend einen unwichtigen
> ISR machen

... würde man die ISR einfach als Task implementieren und im IRQ Handler 
den Task starten / entblockieren. Sollte schnell genug gehen um das 
wichtige FreeRTOS Zeug nicht zu stören.

von Malte _. (malte) Benutzerseite


Lesenswert?

Niklas G. schrieb:
> ... würde man die ISR einfach als Task implementieren und im IRQ Handler
> den Task starten / entblockieren. Sollte schnell genug gehen um das
> wichtige FreeRTOS Zeug nicht zu stören.

Ich gebe zu mein Anwendungfall ist eine absolute Nische.

Der Threadstarter hat vermutlich auch ein anderes Problem. Wenn er 
glaubt sein ISR wird nicht ausgeführt, sollte er mal in das passende 
UART Pending Bit im NVIC schauen.

von Joe J. (j_955)


Lesenswert?

Malte _. schrieb:
> Die Priorität des FreeRTOS ISR darf nicht "wichtiger" als die Priorität
> irgend eines anderen ISRs sein. Sonst kommt es dazu, dass der FreeRTOS
> ISR auf den anderen ISR genested wird. Und wenn dann der FreeRTOS
> Scheduler versucht die Task zu wechseln schaltet der falsch den drunter
> liegeneden ISR Stack um. Das erkennt der Cortex-M interessanterweise in
> Hardware und wirft eine Exception ich meine ein Usage Fault. Lässt sich
> in den Status Registern auch diagnostizieren, ob das der Fall ist.

Was ist denn mit Priorität freeRTOS gemeint? Der Systick? RTOS Tick darf 
sehr wohl interrupte unterbrechen. Hatte den von dir beschriebenen Fall 
so noch nie beobachtet in meinen Projekten.

von Joe J. (j_955)


Lesenswert?

Auf Cortex-M (M3/M4/M7):

Tasks laufen mit PSP (Process Stack Pointer)

ISRs laufen mit MSP (Main Stack Pointer)

Der Context Switch passiert über den PendSV-Handler (und oft SysTick für 
das Ticken).

FreeRTOS wechselt nur den PSP beim Taskwechsel, der MSP bleibt für alle 
Interrupts gleich.
Deshalb ist es völlig okay, dass PendSV innerhalb anderer Interrupts 
läuft – das ist bewusst so designt.

von Joe J. (j_955)


Lesenswert?

Joe J. schrieb:
> Was ist denn mit Priorität freeRTOS gemeint? Der Systick? RTOS Tick darf
> sehr wohl interrupte unterbrechen. Hatte den von dir beschriebenen Fall
> so noch nie beobachtet in meinen Projekten.

ok, du meinst den Scheduler kernel Interrupt.

: Bearbeitet durch User
von Eros S. (dretox)


Lesenswert?

Niklas G. schrieb:
> Eros S. schrieb:
>> Ich vermute ein Problem bzw. eine falsch konfigurierte Interrupt
>> Priorität.
>
> Priorität spielt keine Rolle sofern nicht ein anderer Interrupt
> permanent alles blockiert.
>
> Unterbrich das Programm mal im Debugger in dem Moment, in dem eigentlich
> der Interrupt kommen sollte. Wenn sich das Programm nicht in einem
> Interrupt Handler befindet und außerdem BASEPRI=0 und PRIMASK=0 (in der
> Registeransicht prüfen) sind, sollte der Interrupt auslösen, unabhängig
> von der Priorität.
>
> Wenn er dennoch nicht auslöst, liegt der Fehler im Code.

Das dürfte schwierig werden. Der Interrupt soll ja ausgelöst werden, 
wenn über die UART Schnittstelle ein Zeichen empfangen wird. Genau DANN 
das Programm zu pausieren, wenn das Zeichen vermeintlich raus ist...

Die ISR funktioniert ja grundsätzlich, wenn FreeRTOS nicht konfiguriert 
wird. Auch dass generell Interrupts ja zu funktionieren scheinen, zeigt 
der PCINT, der ja funktioniert. Ein weiteres Indiz ist aber, dass die 
PWM Ansteuerung meiner RGB LEDs nicht mehr funktioniert, sobald FreeRTOS 
eingebunden wird. Ich vermute nach wie vor ein Problem bei der 
Konfiguration. An sich funktioniert der Code ja.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Eros S. schrieb:
> Genau DANN das Programm zu pausieren, wenn das Zeichen vermeintlich raus
> ist...

Muss nicht genau dann sein, nur irgendwann danach. Der Interrupt sollte 
ja "pending" bleiben und nicht einfach "verpuffen".

Eros S. schrieb:
> Ich vermute nach wie vor ein Problem bei der Konfiguration. An sich
> funktioniert der Code ja.

Lässt sich halt so nur schwer diagnostizieren. Debuggen ist auch nötig 
um Konfigurationsfehler zu finden. Mein Vorschlag mit dem Pausieren ist 
blitzschnell geprüft.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.