Moin, im Anhang der problematische Ausschnitt eines Programms. Wie man vielleicht selbt erkennt, handelt es sich um einen Thread (unter KEIL MDK RTX) zum Kommunizieren über eine RS485-Schnittstelle. Eigentlich geht es nur um eine der beiden "HAL_UART_Transmit_"-Zeilen. Ich kann beliebig viele Daten empfangen, die dann von auch per MailQ an den Thread übertragen werden. Dort sollen sie entweder mit einem Parser ausgewertet werden, oder falls dieser nicht definiert ist, einfach als Echo zurückgeschickt werden. Das funktioniert ein Mal. Danach klappt der Empfang nicht mehr. Ich kann aus anderen Threads Mails schicken, deren Inhalt auch jedes Mal versandt wird. Nur wird der Empfang dann sofort blockiert. Wo liegt der Fehler? Ich hatte schon alles schrittweise ein- und wieder auskommentiert - es blieben nur die beiden Zeilen über. TXDMA "schalte" ich je nach Übertragungsmethode per STM32CubeMX ein oder aus. Vielen Dank im Voraus!
Wo ist dein Interrupt-Callback für HAL_UART_Receive_IT? Sowas macht auch keinen Sinn:
1 | while(HAL_UART_Receive_IT(usartDevice->huart, &Usart2RecvDigit, 1) == HAL_BUSY) |
Die *_IT-Funktionrn werden dir nie BUSY melden. Mir scheint, du hast das Prinzip der *_IT-Funktionen noch nicht verstanden. Ich häng dir mal ein funktionierendes Beispiel für die UART-Kommunikation an. Das kann man so auch unverändert mit RTOS nutzen (mach ich auch so)
:
Bearbeitet durch User
Harry L. schrieb: > Wo ist dein Interrupt-Callback für HAL_UART_Receive_IT? Weiter oben und funktioniert. Harry L. schrieb: > Die *_IT-Funktionrn werden dir nie BUSY melden. Dann ist die Schleife ja nur überflüssig, hat aber keinen Einfluss auf irgendwas anderes. Wenn man sich den Quellcode der HAL_UART_Receive_IT ansieht, kann sie sehr wohl HAL_BUSY zurückliefern. Übrigens zickt auch die blocking Version "HAL_UART_Transmit(...)" gleichermaßen rum. Harry L. schrieb: > Mir scheint, du hast das Prinzip der *_IT-Funktionen noch nicht > verstanden. Doch, habe ich.
So, falls sie noch jemandem fehlen sollten:
1 | void USART2RxISR(UART_HandleTypeDef *huart) |
2 | {
|
3 | // ISR wird bei vollständigem Empfang der in HAL_UART_Receive_IT() angegebenen Zeichenmenge ausgeführt
|
4 | Usart2RecvBuffer[usartRxBufferLength[uart2Index]++] = Usart2RecvDigit; |
5 | // Empfang neu starten
|
6 | HAL_UART_Receive_IT(&huart2, &Usart2RecvDigit, 1); |
7 | timeout[uart2Index] = TIMEOUTRESETVALUE; |
8 | callbackCallUsart2++; // DEBUG |
9 | }
|
1 | void USART2TxCpltCallback(UART_HandleTypeDef *huart) |
2 | {
|
3 | // ISR wird ausgeführt, wenn das TXC-Flag gesetzt wurde (der Sendepuffer wurde komplett übertragen).
|
4 | osSemaphoreRelease(Usart2SemaphoreId); |
5 | }
|
1 | HAL_UART_RegisterCallback(DeviceStruct->Interface->UsartInterface->huart, HAL_UART_TX_COMPLETE_CB_ID, USART2TxCpltCallback); |
2 | HAL_UART_RegisterCallback(DeviceStruct->Interface->UsartInterface->huart, HAL_UART_RX_COMPLETE_CB_ID, USART2RxISR); |
Vielleicht mache ich ein paar Kommentare zu viel, aber Cheffe sagt "50% des Quelltextes sind Kommentare!". ;)
:
Bearbeitet durch User
Rahul D. schrieb: > Doch, habe ich. Nein, hast du nicht vollständig! HAL_UART_RxCpltCallback und HAL_UART_TxCpltCallback sind bereits als weak-Funktion vorhanden, und weitere Callback-Funktionen zu registrieren ist vollkommen überflüssig. Wichtig ist nur, direkt am Anfang zu überprüfen, ob huart zu deinem UART passt. Siehe auch mein Sourcecode von oben.
Harry L. schrieb: > und weitere Callback-Funktionen zu registrieren > ist vollkommen überflüssig. er benutzt USE_HAL_UART_REGISTER_CALLBACKS, damit ist das ok und die neue, bessere Variante. Damit werden callbacks dem huart zugeordnet und es ist kein globaler nötig, damit auch nicht die Abfrage von welchem uart der call kommt. Sonst sieht der Code eigentlich ok aus, wenn es nicht ein blödes Timingproblem ist. Wieviele Token hat die Semaphore, und warum wird osSemaphoreWait da mehrmals direkt nacheinander aufgerufen? EventFlags sind an der Stelle sicher einfacher.
:
Bearbeitet durch User
Harry L. schrieb: > Siehe auch mein Sourcecode von oben. Auf den du wohl sehr stolz bist? Für mich sieht der aus, als wäre er "blind" von einem AVR (oder einem anderen 8-Bitter) portiert. Deine putc- und puts-Routinen würde ich bspw. umgekehrt realisieren, da man bei HAL_UART_TRANSMIT_IT einen gewissen Overhead mitschleppt, den man bei deiner puts-Routine mehrfach ausführt (und sie dadurch eigentlich den Sinn einer non-blocking Routine verliert). Ein putc wäre ein Spezialfall von puts, da nur ein Character übertragen wird. Hast du überhaupt mein Problem verstanden? J. S. schrieb: > Wieviele Token hat die Semaphore, und warum wird osSemaphoreWait da > mehrmals direkt nacheinander aufgerufen? Das ist auch nur eine Vorsichtsmaßnahme, falls aus irgendwelchen Gründen doch Semaphoren aufgelaufen sein sollten. Eigentlich sollte das überflüssig sein. > EventFlags sind an der Stelle sicher einfacher. Ja, wäre eine Möglichkeit. Dazu wäre (zumindest bei Keil-RTX) die ThreadId in der Callback nötig. Die hängt in meinem Fall aber nicht von vom Thread, sondern von der Schnittstelle ab (vielleicht habe ich da auch noch einen Knoten im Kopf). Das System funktioniert mit anderen Schnittstellen (I²C) einwandfrei. Daran liegt es also nicht. Vielleicht ist es etwas gewagt, zu sagen, dass da was am HAL-UART-Treiber was nicht ganz so stimmt, oder ich eben etwas dabei übersehen habe (Erwachsenen-ADHS lässt grüßen).
Rahul D. schrieb: > Hast du überhaupt mein Problem verstanden? Code lesen ist nicht so deins, oder, du bist zu arrogant, richtig hin zu schauen... Das "Prinzip FIFO" kennst du? Sorry, aber das wird mir hier zu hohl. Viel Spass beim "frickeln"! Im Notfall kannst du dein mangelndes Verständnis ja immer noch ST anlasten.
Harry L. schrieb: > Rahul D. schrieb: >> Hast du überhaupt mein Problem verstanden? > > Code lesen ist nicht so deins, oder, du bist zu arrogant, richtig hin zu > schauen... Tolle Antwort... Scheinst mein Problem aber trotzdem nicht verstanden zu haben. > > Das "Prinzip FIFO" kennst du? Ja. Meine Antwort war vielleicht etwas kurz-überlegt. Ich würde es halt anders machen. Mache ich ja auch, indem ich eine MailQ verwende (das ist mein FIFO). > Sorry, aber das wird mir hier zu hohl. > Viel Spass beim "frickeln"! ROFL Was hat deine "Lösung" mit meinem Problem zu tun? Vielleicht liegt das Verständnisproblem ja eher bei dir. Wenn du dich raus- / zurückhalten möchtest: Sehr gerne. > Im Notfall kannst du dein mangelndes Verständnis ja immer noch ST > anlasten. Auch ST ist nicht unfehlbar. Ich habe oben doch meiner Meinung nach ziemlich gut den Fehler und meine Suche nach dem Grund beschrieben. Das scheint dich aber nicht interessiert zu haben. Sondern Du fingst an, dass gewisse Funktionen gar nicht "HAL_BUSY" liefern würden. Komisch, wenn man sich deren Quellcode ansieht, stellt man fest, dass sie auch ein "return HAL_BUSY;" enthalten. Soviel dazu. Troll dich bitte einfach!
:
Bearbeitet durch User
Mein "Gefrickel" funktioniert. Bei einer halbduplexen Verbindung (mit einer etwas ungewöhnlichen Hardware (/RE konstant auf GND)), sollte man noch den Mode umschalten; also entweder RX oder TX enablen, wenn man die Datenrichtung umschaltet. Standardmäßig wird der Schnittstelletreiber vollduplex initialisiert. Mal wieder was schön universelles "gefrickelt": - unabhängig vom Datenprotokoll - unabhängig von der U(S)ART-Schnittstelle - (vermutlich) unabhängig vom STM-Controller dank HAL. Naja, ganz unabhängig vom Controller ist es noch nicht: Die Callbacks sind momentan leider nicht unabhängig von der Schnittstelle (das müsste aber eigentlich aufgrund der dynamischen Registrierung auch möglich sein - wird beim nächsten Projekt vielleicht umgesetzt). Zeit für die nächste Baustelle.
Rahul D. schrieb: > Eigentlich geht es nur um eine der beiden "HAL_UART_Transmit_"-Zeilen. Ach nein. Es geht bei dir ganz offensichtlich darum, daß du dich nicht mit dem eigentlichen UART befassen willst und genau deshalb mit den Funktionen aus deiner HAL herumeierst. Sowas zeigt sich auch bei solchen Verrenkungen: Rahul D. schrieb: > So, falls sie noch jemandem fehlen sollten:void > USART2RxISR(UART_HandleTypeDef *huart)... Eine ISR mit einem Argument... Du kämpfst die ganze Zeit mit den Seltsamkeiten der von dir benutzten HAL, die in Wirklichkeit keine ist, sondern lediglich eine Maßnahme, um Leute fest an ST zu binden, indem sie STM-spezifisches Zeug direkt in ihren Algorithmen verwenden. Rahul D. schrieb: > Mal wieder was schön universelles "gefrickelt": > - unabhängig vom Datenprotokoll > - unabhängig von der U(S)ART-Schnittstelle > - (vermutlich) unabhängig vom STM-Controller dank HAL. Wie kommst du auf sowas? Versuche mal, dein Zeugs auf einen PIC32 zu portieren... oder auf einen Fujitsu FR. W.S.
Fangen wir unten an: W.S. schrieb: >> - (vermutlich) unabhängig vom STM-Controller dank HAL. > > Wie kommst du auf sowas? Versuche mal, dein Zeugs auf einen PIC32 zu > portieren... oder auf einen Fujitsu FR. Diese Funktion ist vermutlich unabhängig davon, welcher STM32-Controller verwendet wird. Wenn man was falsch verstehen will, wird man schnell zumm Troll. W.S. schrieb: > Eine ISR mit einem Argument... > > Du kämpfst die ganze Zeit mit den Seltsamkeiten der von dir benutzten > HAL, die in Wirklichkeit keine ist, sondern lediglich eine Maßnahme, um > Leute fest an ST zu binden, indem sie STM-spezifisches Zeug direkt in > ihren Algorithmen verwenden. Ja, und? Warum sollten wir (als Firma) ein möglichst großes Spektrum an Herstellern verwenden, wenn die beiden, die wir derzeit verwenden, unsere Anforderungen abdecken? W.S. schrieb: > Ach nein. Es geht bei dir ganz offensichtlich darum, daß du dich nicht > mit dem eigentlichen UART befassen willst und genau deshalb mit den > Funktionen aus deiner HAL herumeierst. Warum sollte ich mit Details beschäftigen, mit denen sich andere auch nicht beschäftigen (s.o. Harry's Post)? Ich bin bei meinem Ausgangspost davon ausgegangen, dass mir jemand einen Hinweis geben kann, der sowas schon mal gemacht hat. Stattdessen kommen hier (bis auf JoJo) irgendwelche Leute, die nur rumnölen oder ihre "Lösung" als "das einzig Wahre" darstellen müssen. Jetzt habe ich bewiesen, dass dem nicht so ist. Programmiert am besten Eure arms bitte nur noch mit Mäuseklavieren und LED! Edit: Mich würde zu zu sehr interessieren, wie jemand (von den Nölis) direkt auf Registerebene eine universelle Funktion programmiert, die auf jedem 32-Bit-Controller funktioniert.
:
Bearbeitet durch User
W.S. ärgert sich nur das es mal wieder kein HAL Problem war. Das langweilt nur noch, genauso wie das HAL bashing. Rahul D. schrieb: > Naja, ganz unabhängig vom Controller ist es noch nicht: Die Callbacks > sind momentan leider nicht unabhängig von der Schnittstelle (das müsste > aber eigentlich aufgrund der dynamischen Registrierung auch möglich sein > - wird beim nächsten Projekt vielleicht umgesetzt). Der callback wird doch dem huart zugeordnet, und beim Aufruf auch mitgegeben. D.h. in deinem gezeigten Code ist doch nur das huart2 durch huart zu ersetzen. Und die anderen Variablen auch davon abhängig zu machen. Was der HAL fehlt ist da ein UserData Pointer in den Strukturen um solchen cb einfacher einen Kontext mitgeben zu können. Rahul D. schrieb: > Mich würde zu zu sehr interessieren, wie jemand (von den Nölis) direkt > auf Registerebene eine universelle Funktion programmiert, die auf > jedem 32-Bit-Controller funktioniert. Es gibt auch OS die versuchen vieles bis alles zu unterstützen, aber da muss man sich auch lange und tief reinarbeiten bis man das beherrscht.
:
Bearbeitet durch User
J. S. schrieb: > Es gibt auch OS die versuchen vieles bis alles zu unterstützen, aber da > muss man sich auch lange und tief reinarbeiten bis man das beherrscht. Da hat man dann aber auch für jede Schnittstelle einen Treiber mit vom OS definierter Software-Schnittstelle. J. S. schrieb: > Was der HAL fehlt ist da ein UserData Pointer in den Strukturen um > solchen cb einfacher einen Kontext mitgeben zu können. Das fehlt nicht nur der HAL. Wäre für den Controller eine CMSIS-Library vorhanden (bzw. hätte ich eine gefunden), hätte es dasselbe Problem gegeben. Das mit der Callback behalte ich im Hinterkopf (und den Thread in meiner Linksammlung).
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.