Hallo an alle,
ich habe hier ein STM32F4 Discovery Board, auf dem seit einiger Zeit
FreeRTOS läuft. Funktioniert soweit alles super, doch seitdem ich
Interrupts in Kombination mit dem Betriebssystem benutzen möchte, klappt
das alles nicht mehr so richtig.
Es geht dabei speziell um USART Empfangsinterrupts. Im Interrupt wird
unter bestimmten Umständen ein Semaphor gesendet, der dann von einem
Task bearbeitet werden soll. Unabhängig davon laufen auf einem anderen
USART Debuggingausgaben, die zuvor mit printf-ähnlichen Funktionen
formatiert werden.
Damit der Semaphor aus dem Interrupt gesendet werden kann, muss die
Interruptpriorität so gesetzt werden:
1
// wichtig!, sonst stimmt nichts überein mit den neuen ST Libs (ab Version 3.1.0)
2
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
3
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
4
5
// entspricht 11-15, 11 ist das höchst mögliche, sonst gibt es Probleme mit dem OS
(siehe auch Beitrag "STM32 Prioritäten")
Die Semaphore kann nun problemlos vom Task empfangen werden.
Allerdings funktioniert nun die Debuggingausgabe nicht. Die relevante
Funktion sieht so aus:
Nach unterschiedlicher Zeit bleibt das ganze System hängen, sobald das
USART Interrupt Daten empfängt, also ausgeführt wird. Wenn ich die
FreeRTOS Makros (*_CRITICAL) da rausnehme, funktioniert alles -
natürlich unterbrechen sich dann Debuggingausgaben aus unterschiedlichen
Tasks gegenseitig...
Wenn ich die Interruptpriorität (NVIC_IRQChannelPreemptionPriority) auf
0 setze, stürzt das System nicht mehr ab, aber der Semaphor funktioniert
dann nicht mehr...
Wo liegt das Problem? Ich schätze mal, das hat etwas mit den Prioritäten
zu tun, aber wie muss ich die sonst wählen?
Danke schonmal und Grüße
Jan
so einen ähnlichen Hänger hatte ich auch mal, hast du den Debugger dran?
Bei mir kam ich über den Callstack nach vListInsert in list.c, und da
ist ein Kommentar mit den möglichen Fehlerursachen.
Ich hatte auch eine zu hohe Interrupt Priorität, in der default config
dürfen die nicht höher als 4 sein (also >=5), siehe auch
FreeRTOSConfig.h:
1
/* Priorities passed to NVIC_SetPriority() do not require shifting as the
2
function does the shifting itself. Note these priorities need to be equal to
3
or lower than configMAX_SYSCALL_INTERRUPT_PRIORITY - therefore the numeric
4
value needs to be equal to or greater than 5 (on the Cortex-M3 the lower the
5
numeric value the higher the interrupt priority). */
Jan B. schrieb:> Nach unterschiedlicher Zeit bleibt das ganze System hängen, sobald das> USART Interrupt Daten empfängt, also ausgeführt wird. Wenn ich die> FreeRTOS Makros (*_CRITICAL) da rausnehme, funktioniert alles -> natürlich unterbrechen sich dann Debuggingausgaben aus unterschiedlichen> Tasks gegenseitig...
Wie lange sind denn die Zeilen die da ausgespuckt werden?
Du sperrst ja dein OS so lange eine Zeile ausgegeben wird. Wenn in der
Zeit irgendwelche Daten empfangen werden, kann es u.U sein, dass ein
Zeichen verloren geht, weil der PRozessor noch in der Ausgabe-funktion
steckt (der ja auch im Interrupt läuft :-S)
Anstatt mit Interrupts zu jonglieren, würde ich einen zusätzlichen Task
aufziehen, der die Debugging-Ausgaben aller anderen Tasks entgegen
nimmt, diese Zeilenweise puffert, und dann zum UART schickt.
[EDIT: Du sprichst von einem Semaphor. Den sehe ich in deiner obigen
Code aber nicht. Die taskENTER/EXIT_CRITICAL sind Makros die global den
RTOS Scheduler aus- und wieder einschalten :-S.
Für Semaphore brauchst du die Funktionen die in semphr.h definiert
sind.]
Jojo S. schrieb:> so einen ähnlichen Hänger hatte ich auch mal, hast du den Debugger> dran?> Bei mir kam ich über den Callstack nach vListInsert in list.c, und da> ist ein Kommentar mit den möglichen Fehlerursachen.> Ich hatte auch eine zu hohe Interrupt Priorität, in der default config> dürfen die nicht höher als 4 sein (also >=5), siehe auch> FreeRTOSConfig.h:> /* Priorities passed to NVIC_SetPriority() do not require shifting as> the> function does the shifting itself. Note these priorities need to be> equal to> or lower than configMAX_SYSCALL_INTERRUPT_PRIORITY - therefore the> numeric> value needs to be equal to or greater than 5 (on the Cortex-M3 the lower> the> numeric value the higher the interrupt priority). */> #define configTIMER0_INTERRUPT_PRIORITY 5
Einen richtigen Debugger habe ich gerade nicht, aber wahrscheinlich
komme ich da nicht drumrum... Hab’s schon mehrmals in Eclipse versucht
einzurichten, aber das finde ich insgesamt sehr umständlich. Naja, mal
gucken, was ich da machen kann.
Diesen Kommentar finde ich bei mir gar nicht (ich benutze FreeRTOS
v8.0.0 RC2). Bei mir sieht das in der FreeRTOSConfig.h so aus:
1
/* The highest interrupt priority that can be used by any interrupt service
2
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
3
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
4
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
Ich sehe gerade, dass in meinem oberen Beitrag im ersten Codeausschnitt
NVIC_IRQChannelPreemptionPriority auf 0 gesetzt ist, aber das, was da
auskommentiert ist, ist normalerweise nicht auskommentiert, von daher
sollte das so passen.
Eric B. schrieb:> Wie lange sind denn die Zeilen die da ausgespuckt werden?> Du sperrst ja dein OS so lange eine Zeile ausgegeben wird. Wenn in der> Zeit irgendwelche Daten empfangen werden, kann es u.U sein, dass ein> Zeichen verloren geht, weil der PRozessor noch in der Ausgabe-funktion> steckt (der ja auch im Interrupt läuft :-S)>> Anstatt mit Interrupts zu jonglieren, würde ich einen zusätzlichen Task> aufziehen, der die Debugging-Ausgaben aller anderen Tasks entgegen> nimmt, diese Zeilenweise puffert, und dann zum UART schickt.>> [EDIT: Du sprichst von einem Semaphor. Den sehe ich in deiner obigen> Code aber nicht. Die taskENTER/EXIT_CRITICAL sind Makros die global den> RTOS Scheduler aus- und wieder einschalten :-S.> Für Semaphore brauchst du die Funktionen die in semphr.h definiert> sind.]
Die Zeilen sind unterschiedlich lang, aber diese Schnittstelle soll auch
zum Streamen von sehr großen Datenmengen (konkret eine Karte, quasi ein
Bild) genutzt werden. Normalerweise dann maximal 200 chars auf einmal
(Übertragung zeilenweise). Dass das so nicht optimal ist, weiß ich
(eventuell soll das, wenn es so (langsam) funktioniert mit DMA gemacht
werden), aber solange es diesen Fehler gibt, kann er ja generell überall
im Programm wieder auftreten, das möchte ich vermeiden.
Vielleicht hast Du aber recht und ich sollte das doch jetzt schon
umstrukturieren.
Der Semaphor befindet sich in der Interruptroutine, hat aber nicht
direkt etwas mit dem Problem zu tun - wenn ich den Teil komplett
auskommentiere, ändert das nichts daran. Der Semaphor war allerdings die
Voraussetzung, dass die Priorität des Interrupts geändert werden musste,
was weitere Probleme verursacht hat.
So ganz nebenbei... sollte man sich von printf() Geschichten auf
embedded Systemen eh loesen. Die sind unter anderem auch nicht
reentrant.
Weshalb kann man nicht eine Zahl digit fuer digit seriell rauslassen?
Weshalb printf()? Das absolut Duemmste auf kleinen Systemen
Ich verwend jeweils IntToHex, was mit einer sehr kleinen Anzahl
Statements auskommt.
Jan B. schrieb:> Dass das so nicht optimal ist, weiß ich> (eventuell soll das, wenn es so (langsam) funktioniert mit DMA gemacht> werden), aber solange es diesen Fehler gibt, kann er ja generell überall> im Programm wieder auftreten, das möchte ich vermeiden.
Umsomehr Grund dies anders zu lösen als mit Prio's und
ENTER/EXIT_CRITICAL :-)
> Vielleicht hast Du aber recht und ich sollte das doch jetzt schon> umstrukturieren.vehement bejaht :-)
> Der Semaphor [...] hat aber nicht direkt etwas mit dem Problem zu tun
Ok, verstehe.
benutze, habe ich doch zwei Problem:
1) Diese Schleife kann doch nun trotzdem von einer Debugausgabe in einem
anderen Task unterbrochen werden. Kann ich irgendwie den gesamten String
auf einmal, ohne die Schleife, senden, oder muss ich hier dann doch
wieder die ENTER/EXIT_CRITICAL Makros nutzen?
2) Es werden keine Ausgaben gemacht, solange das System nicht komplett
hochgefahren ist (ist vielleicht nicht ganz so schlimm, aber nicht so
schön)...
Ich vermute fast, ich habe Deinen Lösungsvorschlag falsch verstanden.
Wie würdest Du das umsetzen?