Forum: Mikrocontroller und Digitale Elektronik AVR GCC int32_t Problem


von Karsten S. (scottyrebel)


Lesenswert?

Hallo
Ich habe in meiner Anwendung(ATMega2560) einige Variablen vom typ 
int32_t.
Diese sind global deklariert:

int32_t ActX = 0;
int32_t ActY = 0;
int32_t ActZ = 0;
int32_t DstX = 0;
int32_t DstY = 0;
int32_t DstZ = 0;

int32_t dX = 0;
int32_t dY = 0;
int32_t dZ = 0;
int32_t sX = 0;
int32_t sY = 0;
int32_t sZ = 0;

In einer Timer-ISR(CompareMatchB) rechne ich dann irgendwo:

ActX += sX;

das geht bis gut solange Actx <= 32536 ist. Wird der Wert überschritten 
läuft die Anwendung wer weiß wohin.
Merkwürdig ist der Wert 32536. Das ist kein besonderer Wert wie 32767, 
dort könnte man einen Überlauf vermuten.

Ändere ich die Deklarationen auf int16_t funktioniert alles. Problem ist 
aber das meine Werte größer werden können als 65536, deshalb int32_t.

Danke für Eure Hilfe

Gruß Scotty

von Peter II (Gast)


Lesenswert?

Karsten S. schrieb:
> In einer Timer-ISR(CompareMatchB) rechne ich dann irgendwo

Hast du einen Schutz bei der abfrage eingebaut, damit die ISR die Daten 
nicht ändert wenn du sie abfragst?

von (prx) A. K. (prx)


Lesenswert?


von Karsten S. (scottyrebel)


Lesenswert?

Ich frage ja nicht nur ab, sondern ich will auch ändern.

Was meinst Du mit Schutz?

von Karsten S. (scottyrebel)


Lesenswert?

Ich habe es auch mit volatile probiert - Gleiches Problem

von (prx) A. K. (prx)


Lesenswert?

Karsten S. schrieb:
> Was meinst Du mit Schutz?

Das was im Link steht. Zu Variablen, die aus mehreren Bytes bestehen.

von Anon Y. (avion23)


Lesenswert?

Der GCC führt Rechnoperationen grundsätzlich auf Words aus. Und Words 
sind beim avr-gcc 16 Bit.

Das sorgt für einige gefährliche Situationen. Helfen kann man sich in 
dem man die Zwischenwerte einer Operation manuell castet.

von Peter II (Gast)


Lesenswert?

Anon Y. schrieb:
> Der GCC führt Rechnoperationen grundsätzlich auf Words aus.
nein auf int  - C(++) ist so definiert.

> Das sorgt für einige gefährliche Situationen. Helfen kann man sich in
> dem man die Zwischenwerte einer Operation manuell castet.
ist bei seinem Beispiel aber nicht notwendig.

ActX += sX;

Das wird mit dem Datentype von ActX gerechnet.

von Anon Y. (avion23)


Lesenswert?

Peter II schrieb:
> nein auf int  - C(++) ist so definiert.

Lassen wir besser die int vs. word Spekulation. Ich bin mir sehr sicher, 
dass es 16 Bit sind. Die FAQ dazu:
http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_intpromote

von c-hater (Gast)


Lesenswert?

Anon Y. schrieb:

> Der GCC führt Rechnoperationen grundsätzlich auf Words aus.

So ein Blödsinn, das kann er garnicht. Er muss schon damit vorlieb 
nehmen, was die Zielarchitektur kann. Und bei einer 8Bit-Zielarchitektur 
sind das im Allgemeinen auch nur 8Bit-Operationen.

Alles, was breiter ist, muss er logischerweise aus den verfügbaren 
Operationen zusammenbauen.

> Das sorgt für einige gefährliche Situationen.

Ja. Immer, wenn irgendwas nicht "atomar" bearbeitet werden kann und 
mehrere Codepfade gleichzeitig (multicore oder multiprocessor) oder 
zumindest quasi-gleichzeitig (interrupts/multitasking) bearbeitet 
werden, kann es zu solchen gefährlichen Situationen kommen.

> Helfen kann man sich in
> dem man die Zwischenwerte einer Operation manuell castet.

Nein, das hilft höchstens mal zufällig.

Was hingegen sicher hilft, ist, die Zugriffe zwischen den Codepfaden zu 
synchronisieren. Im Falle AVR mit Interrupts bedeutet das im Kern immer, 
dass bei Zugriffen aus main() die Interrupts verboten werden müssen, 
solange die Operation in main() dauert. Zugriffe aus ISRs heraus sind 
hingegen automatisch geschützt, solange man in den ISRs nicht mit sei() 
herumhantiert.

D.h. für den Fall des TO, dass bezüglich der ISR nur das "volatile" bei 
der Deklaration der Variablen fehlt. Der Rest des Fehlers steckt in 
main(). Den dortigen Code hat der TO allerdings nicht gepostet...

von fop (Gast)


Lesenswert?

Hi,
welchen Wert hat sX bei der Addition ? Und was meinst Du mit das 
Programm läuft irgendwohin ? Ist nur der Inhalt der Variablen ActX 
anders, als Du erwartest, oder nimmt der Programmablauf wirklich 
unvorhersehbare Wege ?

von (prx) A. K. (prx)


Lesenswert?

Anon Y. schrieb:
> Der GCC führt Rechnoperationen grundsätzlich auf Words aus. Und Words
> sind beim avr-gcc 16 Bit.

C tut zwar so, als ob die Rechnung mindestens in "int" stattfindet. Aber 
weder muss das im realen Code so sein, noch ist das hier das Problem.

> Lassen wir besser die int vs. word Spekulation. Ich bin mir sehr sicher,
> dass es 16 Bit sind.

Und ich bin mir sehr sicher, dass es per Sprachdefinition "int" ist. Und
"int" wiederum mindestens den Wertebereich von 16 Bits umfasst, aber je
nach Zielmaschine auch grösser sein kann.

von Karsten S. (scottyrebel)


Lesenswert?

Okay hat sich erledigt.

Ich nutze ja auch die Capture-ISR. Im Programmlauf wird dann das 
ICR1-Register geändert. Dies lief dann über und die andern beiden ISR' 
wurden nicht mehr ausgeführt. Das passierte genau nach die Variable ActX 
auf 32536 stand. ActX wurde dann nur noch getestet aber nicht mehr 
geändert, das passiert normalerweise in der CompareMatchB. Das ICR1 
wurde in CompareMatchA geändert. Diese beiden ISR wurden aber nicht mehr 
angesprungen. Folglich nur noch die Capture-ISR und dort war der Wert 
bei jedem Aufruf 32536.

Grrr. :=(

Danke für Eure Hilfe

Gruß Scotty

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.