Forum: Compiler & IDEs itoa in der ISR mit volatile


von Alex (Gast)


Lesenswert?

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

von Oliver (Gast)


Lesenswert?

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

von Alex (Gast)


Lesenswert?

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

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Alex (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Klaus W. (mfgkw)


Lesenswert?

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...)

von Alex (Gast)


Lesenswert?

Wäre es eine Option, die Schreibzugriffe im Main atomic auszuführen?

Grüße, Alex

von Klaus W. (mfgkw)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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 :-)

von Klaus W. (mfgkw)


Lesenswert?

Das ist ja reine Elektronik, was du da treibst.
Baust du oder schreibst du CAD-SW?

von Alex (Gast)


Lesenswert?

???

von ... .. (docean) Benutzerseite


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

Klaus Wachtler schrieb:
> Das ist ja reine Elektronik, was du da treibst.
> Baust du oder schreibst du CAD-SW?

CAD - Architektur

von Alex (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.