Bin dabei, unter FreeRTOS auf einem STM32F103C8T6 (blue pill) eine
Anwendung zu schreiben, die neben einigen Analogeeinlesefunktionen auch
zwei UARTs betreiben soll. Habe dazu eine Verständnisfrage zum UART
global Interrupt. Versuche gerade, erst mal ein einfaches echo-Programm
zum Laufen zu kriegen, was Zeichen vom UART Rx über eine ISR einliest
und in einen Ringpuffer schreibt. Eine FreeRTOS Task schaut nach, ob im
Input-Ringbuffer etwas drin ist. Wenn ja, schreibt sie das Zeichen in
einen Output-Ringbuffer. Und eine zweite Task schaut nach, ob im
Outputringbuffer etwas steht, was dann rausgeschrieben werden soll. Auch
Interrupt gesteuert.
Jetzt gibt es ja den UART Global Interrupt, den man einschalten kann in
der MX-Konfiguration.
Nun meine Frage zum Verständnis: ist es so, daß sich Rx und Tx den
Interrupt teilen und man nachgucken muß, wer den Interrupt verursacht
hat?
/* RXNE flag will be cleared by reading of DR register (done in call) */
7
/* Call function in charge of handling Character reception */
8
USART_CharReception_Callback();
9
}
Wenn ich RxData auslese, wird doch das IR-Flag gelöscht? TxEmpty müßte
doch auch einen Interrupt auslösen, oder? Ich benutze das LL-Interface.
Im Moment kriege ich es nicht mal mehr hin, daß ich im Callback auf
einen Breakpoint laufen kann, wenn ich ein Zeichen tippe.
Christoph K. schrieb:> Nun meine Frage zum Verständnis: ist es so, daß sich Rx und Tx den> Interrupt teilen und man nachgucken muß, wer den Interrupt verursacht> hat?
Ja, denn es gibt (vermutlich wegen langsamkeit der Schnittstelle)
nur den global Interrupt für je einen UART. Der soll alles tun.
>> LL_USART_IsEnabledIT_RXNE(USART1)
kannst du dir sparen.
Christoph K. schrieb:> Wenn ich RxData auslese, wird doch das IR-Flag gelöscht? TxEmpty müßte> doch auch einen Interrupt auslösen, oder?
Ja genau so ist es. Aber nur das Rx-Flag wird gelöscht.
Christoph K. schrieb:> Im Moment kriege ich es nicht mal mehr hin, daß ich im Callback auf> einen Breakpoint laufen kann, wenn ich ein Zeichen tippe.
Bei mir gibt es zur Initialisierung noch die kleine Zusatz-
Funktion im USART-Code (vielleicht musst du das auch tun?):
Analog dazu würde man auch den TX-Interrupt aktivieren wenn
man das braucht.
Dann gibt es noch die Möglichkeit dass dein Code vom Compiler so
optimiert ist dass das Setzen eines Breakpoints nicht möglich ist.
Schau dir meinen Code mal an!
Beitrag "[STM32/HAL] simples U(S)ART-Library"
Die Interrupts haben erstmal nicht viel mit FreeRTOS zu tun, solange du
die nicht zu hoch priorisierst.
Mein Demo (mit Echo wie gewünscht) startest du einfach am Anfang deines
default-Task.
"huart2" musst du natürlich durch das Handle deines genutzten Uart
ersetzen.
Harry L. schrieb:> Die Interrupts haben erstmal nicht viel mit FreeRTOS zu tun
Offensichtlich schon, sonst würde ja nicht dies auftreten:
Christoph K. schrieb:> Wenn ich alles FreeRTOS Spezifische auskommentiere, kann ich den> Interrupt abfangen.
// End of Line Char (valid in string- and data-mode
10
11
// in raw-mode the callback is fired after any received byte.
Du hast die Bindestrich-Krankheit. In der englischen Sprache wird
der Bindestrich nur in (sehr) besonderen Fällen verwendet.
Beispiel: state-of-the-art programming
Da du englischsprachige Texte schreibst nehme ich an dass du dich
an englischsprachiche User wenden möchtest. Dann bitte keine
Deppen-Bindestriche.
Wastl schrieb:> Da du englischsprachige Texte schreibst nehme ich an dass du dich> an englischsprachiche User wenden möchtest. Dann bitte keine> Deppen-Bindestriche.
Wenn du sonst keine Probleme hast...
Christoph K. schrieb:> Wenn ich alles FreeRTOS Spezifische auskommentiere, kann ich den> Interrupt abfangen.
Dein Fehler liegt wo anders.
Ich nutze Interrupts ganz normal auch in Kombination mit FreeRTOS.
Wastl schrieb:> Habe keine Erfahrung mit FreeRTOSWastl schrieb:> Harry L. schrieb:>> Die Interrupts haben erstmal nicht viel mit FreeRTOS zu tun>> Offensichtlich schon, sonst würde ja nicht dies auftreten:
Und warum schreibst du dann sowas?
Kommt es dir nicht in den Sinn, daß das Problem an ganz anderer Stelle
liegen könnte?
Harry L. schrieb:> Kommt es dir nicht in den Sinn, daß das Problem an ganz anderer Stelle> liegen könnte?
Mehr Details an Zusammenhängen wurden vom TO nicht bekannt
gegeben. Wenn du die Lösung des Problems kennst dann scheue
dich nicht davor zurück sie uns mitzuteilen.
Danke an Harry für den Verweis auf seine Routinen. Bevor ich das Faß
aufmache, würde ich lieber die selbst produzierten Phänomene verstehen.
Ich habe jetzt wieder den Zusatnd mit einer FreeRTOS Task, in der ich
nur gucke, ob ein Zeichen in der input Queue abgelegt wurde.
Außerdem habe ich noch mal einen vollen Build gemacht. Und da geht es
plötzlich reproduzierbar, mehrmals hintereinander, daß ich den receive
interrupt abfangen kann. Möglicherweise komme ich jetzt weiter.
Danke erstmal für's Mitdenken.
Google (Bsp. für F4xx):
HAL STM32F4xx Usermanual
Erstes Ergebnis.
Warum glaubst du, die LL-Funktionen zu benötigen?
Die brauchst du nur, wenn du ein paar Byte Flash sparen musst, oder
Funktionalitäten abbilden musst, die mit der HAL sonst nicht erreichbar
wären.
Normale UART-Funktionalität geht mit HAL genauso gut und ohne
Performance-Einbussen.
Harry L. schrieb:> Christoph K. schrieb:>> Schnell noch nachgeschoben, die Frage: wo finde ich eine vollständige>> Beschreibung der LL-Funktionen? Z.B.:
...
> Google (Bsp. für F4xx):> HAL STM32F4xx Usermanual
HAL Manual habe ich.
>> Erstes Ergebnis.>> Warum glaubst du, die LL-Funktionen zu benötigen?> Die brauchst du nur, wenn du ein paar Byte Flash sparen musst, oder> Funktionalitäten abbilden musst, die mit der HAL sonst nicht erreichbar> wären.
HAL hatte mich zuletzt genervt. Jemand schreibt auch im Rtos Forum, HAL
und FreeRTOS zusammen sei keine gute Idee.
Christoph K. schrieb:> Jemand schreibt auch im Rtos Forum, HAL> und FreeRTOS zusammen sei keine gute Idee.
Dann hat "jemand" wohl nur sehr wenig Erfahrung und/oder keine Ahnung...
Im Internet steht viel Blödsinn, und oft sogar unwidersprochen.
Wastl schrieb:>>> LL_USART_IsEnabledIT_RXNE(USART1)>> kannst du dir sparen.
Darf man das als Beratungsresistenz einstufen dass du das immer
noch benutzt?
Christoph K. schrieb:> Schnell noch nachgeschoben, die Frage: wo finde ich eine vollständige> Beschreibung der LL-Funktionen?
Ganz einfach in <stm32f1xx_ll_usart.c> und <stm32f1xx_ll_usart.h>
Alle Makros und Funktionen haben einen erklärenden Header. z.B.:
1
/**
2
* @brief Initialize USART registers according to the specified
3
* parameters in USART_InitStruct.
4
* @note As some bits in USART configuration registers can only be written when the USART is disabled (USART_CR1_UE bit =0),
5
* USART IP should be in disabled state prior calling this function. Otherwise, ERROR result will be returned.
6
* @note Baud rate value stored in USART_InitStruct BaudRate field, should be valid (different from 0).
7
* @param USARTx USART Instance
8
* @param USART_InitStruct pointer to a LL_USART_InitTypeDef structure
9
* that contains the configuration information for the specified USART peripheral.
10
* @retval An ErrorStatus enumeration value:
11
* - SUCCESS: USART registers are initialized according to USART_InitStruct content
12
* - ERROR: Problem occurred during USART Registers initialization
Wastl schrieb:> Wastl schrieb:>>>> LL_USART_IsEnabledIT_RXNE(USART1)>>>> kannst du dir sparen.>> Darf man das als Beratungsresistenz einstufen dass du das immer> noch benutzt?> [/c]
Den Code habe ich mir nicht selber ausgedacht. Der wurde vom MX
generiert. Hielt ich jetzt erst mal nicht für so vorrangig wichtig, den
wegzulassen,
da ich ja zunächst das Problem mit dem garnicht abfangbaren IR hatte.
Letztlich bin ich noch nicht viel weiter in meiner Erkenntnis, daß ich
nämlich den Einstieg in den USART1_IRQHandler mit einem in STM32CubeIDE
gesetzten Breakpoint nicht abfangen kann (wenn FreeRTOS im Spiel ist).
Setze ich dort einen festverdrahteten BKPT ( __asm("bkpt"); ), so wird
dieser getroffen.
Es könnte ja etwas mit BMP und GDB zu tun haben. Ob ich es mal mit einem
echten STLINK-V2 versuchen sollte?
EDIT: bis auf weiteres hilft momentan, LL_USART_EnableIT_RXNE(USART1);
in den Anfang der Task1 zu verlegen.
Christoph K. schrieb:> Letztlich bin ich noch nicht viel weiter in meiner Erkenntnis, daß ich> nämlich den Einstieg in den USART1_IRQHandler mit einem in STM32CubeIDE> gesetzten Breakpoint nicht abfangen kann
Für mich ergibt sich daraus einfach folgende Logik: Wenn man im
(von CubeMX generierten) IRQ Handler einen IRQ nicht abfangen kann
dann tritt der IRQ schlichtweg nicht auf. Das kann zwei Gründe haben:
1) Der IRQ wurde gar nicht aktiviert.
2) Der IRQ tritt nicht auf da das passende Ereignis nicht eingetreten
ist
Der Dritte Grund ist nach wie vor (ich hatte das früher schon
erwähnt) dass der Code-Bereich vom Compiler so optimiert worden
ist dass ein Break dort nicht möglich ist.
Wastl schrieb:> Das kann zwei Gründe haben:
Etwas ganz perverses ist mir noch eingefallen. Es könnte sein
dass irgendeine Instanz den Vektor auf den IRQ Handler umbiegt
und auf seine eigene Handler-Funktion zeigen lässt. Dies liesse
sich herausfinden indem man die IRQ-Tabelle im Falle des
Nicht-Abfangen-Könnens anschaut, dort muss man sehen können wo
der RXNE-Handler angesprungen wird.
Christoph K. schrieb:> Den Überlegungen steht entgegen, daß ich in die ISR einen __asm(bkpt)> einbauen kann und der immer getroffen wird.
Dann ist es ja ein Effekt der Code-Optimierung der dich sonst
behindert.