Hallo, wie schon im Betreff beschrieben, möchte ich itoa in der ISR verwenden und bekomme die Warnung wegen des volatile-Qualifiers des string-pointers, der an itoa übergeben wird. Itoa möchte ich nicht unbedingt ändern. Ich abe aber gelesen, dass man das volatile beim Aufruf wegcasten kann. Wie sähe das denn aus? Mein Aufruf ist uart0_puts (itoa(i, tmp_str, 10)); wie müsste ich das schreiben mit weggecastetem volatile? Wenn ich das in der ISR ohne volatile für tmp_str mache, was könnte an Fehlern passieren? Gruß und Danke, Alex
Alex schrieb: > Wenn ich das in der ISR ohne volatile für tmp_str mache, was könnte an > Fehlern passieren? Warum machst du es denn mit volatile? volatile brauchst du nur, wenn du eine Variable in der ISR und im Hauptprogramm verwendest. Der Name "tmp_str" könnte darauf hinweisen, daß das nicht so ist. Alex schrieb: > Mein Aufruf ist uart0_puts (itoa(i, tmp_str, 10)); > wie müsste ich das schreiben mit weggecastetem volatile? (char *)tmp_str Aber: Wenn uart0_puts eine Ausgabe über UART ist, ist das in einer ISR gar keine gute Idee. Da drüber solltest du nochmals nachdenken. Oliver
Hallo Oliver, danke für die schnelle Antwort. Ich weiß, dass es nicht optimal ist in der ISR was zu senden, aber da es zeitgenau geschehen muss, weiß ich gerade keinen besseren Weg und es sind nur wenige Zeichen pro Ineterrupt, der alle 500ms ausgelöst wird. Und ich schreibe es auch nur in den Sendepuffer und schicke es nicht direkt mir der UART weg. Ich hatte noch überlegt, den in der ISR verwendeten tmp_str lokal in der ISR anzulegen, wäre das dann ohne volatile i.O.? Momentan benutze ich einen globalen tmp_str für alles mögliche im Programm, auch außerhalb der ISR. Was sagst Du dazu? Danke, Alex
Alex schrieb: > Momentan benutze ich einen > globalen tmp_str für alles mögliche im Programm, auch außerhalb der ISR. > Was sagst Du dazu? Das ist eine ganz schlechte Idee. Wie synchronisierst Du Zugriffe darauf? Deine ISR hat bei Aufruf keine Ahnung davon, ob nicht zufälligerweise Dein Hauptprogramm irgendwas mit diesem Puffer anfängt und überschreibt gnadenlos das, was da möglicherweise schon drinsteht. Das wiederum dürfte Dein Hauptprogramm aus dem Tritt bringen, das ja wohl nicht ohne Grund etwas dort hingeschrieben hat. Je nach Größe dieses Puffers: Mach daraus eine automatische Variable, die nur zur Laufzeit der ISR existiert (also auf dem Stack liegt). Andererseits: Statt die per itoa ermittelten Zeichen in den UART-Sendepuffer einzutragen, könntest Du auch einfach den Wert in einen dem UART-Sendepuffer vorgeschalteten Puffer eintragen, und die Aufbereitung und Ausgabe erfolgt dann außerhalb der ISR. In Deinem Beispiel ist zwar der itoa-Aufruf in der ISR recht harmlos (da die ISR so selten auftritt und die Chose anscheinend auch nicht extrem zeitkritisch ist), aber so etwas sollte man vermeiden.
Hallo Rufus, Rufus t. Firefly schrieb: > Andererseits: Statt die per itoa ermittelten Zeichen in den > UART-Sendepuffer einzutragen, könntest Du auch einfach den Wert in einen > dem UART-Sendepuffer vorgeschalteten Puffer eintragen, und die > Aufbereitung und Ausgabe erfolgt dann außerhalb der ISR. Das mache ich ja. Ich habe eine Ringpuffer, in den ich die Werte schreibe und der dann im UART Interrupt gelesen und gesendet wird. Ansonsten danke für die Tipp, leuchtet mir alles ein und ich werde das so umsetzten. Das mit dem tmp_str ist wirklich dumm so und auch offensichtlich dumm, trotzdem ist mir das so noch gar nicht den Sinn gekommen. Grüße, Alex
Alex schrieb: > Hallo Rufus, > > Rufus t. Firefly schrieb: >> Andererseits: Statt die per itoa ermittelten Zeichen in den >> UART-Sendepuffer einzutragen, könntest Du auch einfach den Wert in einen >> dem UART-Sendepuffer vorgeschalteten Puffer eintragen, und die >> Aufbereitung und Ausgabe erfolgt dann außerhalb der ISR. > > Das mache ich ja. Ich habe eine Ringpuffer, in den ich die Werte > schreibe und der dann im UART Interrupt gelesen und gesendet wird. Ist trotzdem immer noch eine ganz schlechte Idee. Das Problem: Dein Hauptprogramm möchte zb ausgeben "Hallo World" Dazu beginnt es den String in den Sendepuffer zu übertragen. Es wird zeichenweise in den Sendepuffer eingetragen H a l l Und wie es der Zufall so haben will, kommt ausgerechnet jetzt dein anderer Interrupt daher. Der seinerseits 123 in den Sendepuffer stellt. Irgendwann ist auch dieser Interrupt beendet und es geht zurück zum Hauptprogramm welches immer noch Zeichen in den Sendepuffer einstellt o W o r l d Dein Empfänger bekommt damit den Text Hall123o World zu Gesicht. Und das dürfte in den meisten Fällen für Verwirrung sorgen. Halte dich an die klassischen Methoden und du hast weniger Probleme: * In einer ISR wird ein Flag gesetzt, vielleicht noch ein bischen Arbeit gemacht * In der Hauptschleife werden alle Flags reihum abgearbeitet und der zugehörige Job ausgeführt, wenn das Flag richtig steht * Kein Job darf lange dauern. Länger andauernde Prozesse werden in Einzelteile zerlegt, für jeden Einzelteil gibt es ein Flag und die Einzelteile aktivieren sich nacheinender selber, indem sie das jeweilige Flag setzen. Es hat schon seinen Grund, warum manche Programm-Systematiken es zum Klassiker schaffen und andere nicht.
Oder noch schöner: Im Hauptfluß wird ein Zeichen geschrieben, aber bevor der zugehörige Zähler oder Zeiger erhöht wird, kommt der Interrupt. Der gibt dann etwas aus (wobei er das letzte zuvor geschriebene Zeichen überschreibt), und anschließend geht es an der unterbrochenen Stelle weiter - dann wird der Zähler wiederum fälschlicherweise weiter gesetzt. (Du schwächelst! Sonst kommen die düsteren Beispiele doch immer von Dir...)
Wäre es eine Option, die Schreibzugriffe im Main atomic auszuführen? Grüße, Alex
Das lohnt nicht, wenn nicht wirklich Daten ausgetauscht werden sollen. Wenn ich das richtig mitbekommen habe, braucht er den tmp_str aber gar nicht zum Austausch. Mit einem Feld im Hauptprogramm und einem im Interrupt gibt es keine Kollisionen, und die aufwendige Abstimmung entfällt.
Klaus Wachtler schrieb: > (Du schwächelst! Sonst kommen die düsteren Beispiele doch immer von > Dir...) LOL. Ich hab da ein 'nebenbei' ein saublödes Problem zu bearbeiten. Wird ein Fenster mit einem hochgezogenen Fensterbrett in eine Mauer gesetzt, so dass das Fenster am Fertigfussboden unten ansteht, der auch noch von der Mauervorderkante zurückgesetzt ist, dann verhaut sich die Schnittberechnung, die einen Querschnitt durch das Geschoss berechnet und dieser Mauerteil wird nicht richtig schraffiert. Ich denke mal, es ist irgendwo ein Epsilon in einem schleifenden Schnitt, welches zu klein ist. Kann auch sein, dass die Urgeometrie schon nicht sauber ist und die boolsche Operation Mist gebaut hat. (Datenstrukturdumps deuten in diese Richtung). Sitzt jetzt schon den 2. Tag daran und finde das Problem einfach nicht. Auf zur nächsten Debug-Session und rund 15tausend Zeilen Code erneut durchsteppen :-)
Das ist ja reine Elektronik, was du da treibst. Baust du oder schreibst du CAD-SW?
Alex schrieb: > zeitgenau geschehen muss, weiß ich > Und ich schreibe es auch nur > in den Sendepuffer Das beißt sich... Annahme: Deine Main schreibt den Sendepuffer mit irgendwas voll... und dann kommt dein ISR.... Also das ablegen der Daten geht vielleicht zeitgenau aber das Senden nie und nimmer... Speicher einfach die Daten aus der ISR (ohne vorher itoa zu wandeln) irgendwohin und setzt dann ein Flag und dann holt die main die Daten ab und wandelt die um
Klaus Wachtler schrieb: > Das ist ja reine Elektronik, was du da treibst. > Baust du oder schreibst du CAD-SW? CAD - Architektur
Ich hab das Programm jetzt so geändert, wie von euch vorgeschlagen. Keine zeitintensiven Geschichten in der ISR und mit Flags. Es funktioniert. Und der Rest der Codes, der vorher schon lief, auch ;-) Toll! Danke...
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.