uint8_t cast to int8_t

OP #6644795
Lesenswert?

Hallo zusammen
Ich habe einen uint8_t Wert, der als int interpretiert werden soll. Ich 
arbeite auf einem STM32G474 mit IAR.
Bei +1 kommt 0x01 daher, bei -1 0xFF, alles korrekt. Dann habe ich den 
cast auf (int8_t) gemacht aber 0xFF beleibt 0xFF. Jemand eine Idee?
Die Screenshots vom Debugger sind in den Bilder zu sehen.

static void on_cmd_wheel_turned_f(const uint8_t *data_p, uint_fast16_t 
data_length) {
    /*-- Local Variables 
---------------------------------------------------------------*/
    union tDATA_Event_RemoteControl t_RemoteControl;

    uint8_t response_a[SCP_PAYLOAD_MAX_LENGTH];
    size_t  response_len = 0;
    int8_t nWheelInc = 0;
    uint16_t nLogValue = 0;

    /*-- Code Statements 
---------------------------------------------------------------*/
    nWheelInc = (int8_t)(BUF_READ_BE_U8_F(data_p, 0));
Angehängte Dateien:
OP #6644827
Lesenswert?

(prx) A. K. schrieb:
> Hast du ein Problem mit dem Verhalten des Compilers, oder nur mit der
> Darstellung durch den Debugger? Lässt sich die Art einstellen, wie der
> Debugger Werte anzeigt, z.B. hex/dez?

Danke für den konstruktiven Beitrag.
Die Darstellung ist mir egal, die if Anweisung danach mit >= 0 
funktioniert so nicht, denn -1 ist ja wie im Debugger zu sehen ist 0xFF 
und darum ist die if >= 0 bei 0xFF true, was ich genau nicht möchte. Ich 
muss alle negativen Werte im else behandeln. Das ist die wirklich 
einfache Aufgabe, aber da es nicht funktionierte habe ich im Debugger 
den Wert angeschaut und war etwas erstaunt, dass ich 0xFF anstatt -1 
angezeigt bekam.
... Die ersten Antworten im Thread haben dies wahrscheinlich nicht 
bemerkt.
#6644829
Lesenswert?

Mach F. schrieb:
> Die Darstellung ist mir egal, die if Anweisung danach mit >= 0
> funktioniert so nicht, denn -1 ist ja wie im Debugger zu sehen ist 0xFF
> und darum ist die if >= 0 bei 0xFF true, was ich genau nicht möchte.

Compiler und Debugger sind zwei völlig verschiedene paar Stiefel. Es ist 
durchaus möglich, dass der Debugger in deiner Einstellung alle 8-Bit 
Werte unabhängig vom deklarierten Vorzeichen so anzeigt, wie oben 
abgebildet, obwohl der Compiler 0xFF im if als negativen Wert 
behandelt.

Deshalb meine Frage danach, ob du ein Problem mit dem Verhalten des 
Compilers hast, oder aufgrund der Anzeige des Debuggers nur eines 
vermutest.
OP #6644833
Lesenswert?

(prx) A. K. schrieb:
> Deshalb meine Frage danach, ob du ein Problem mit dem Verhalten des
> Compilers hast, oder aufgrund der Anzeige des Debuggers nur eines
> vermutest.

ja habe ein Problem mit dem Compiler, denn der Compiler behandelt den 
Wert 0xFF als positiven Wert, sprich die if >= 0 ist true, was nicht 
sein sollte. Wenn ich einen Breakpoint im else setze, wird dieser nicht 
getriggert, auch bei 0xFF oder eben -1 nicht.
#6644838
Lesenswert?

Wenn das Verhalten des Programms den Wert als positiv sieht, dann wird 
es fällig, sich den erzeugten Code und die Registerinhalte per single 
step oder breakpoint nicht auf C-Ebene anzusehen, sondern auf 
Assembler/Register-Ebene.

Vorsichtshalber sei noch erwähnt, dass das Verhalten von Typen mit 
Vorzeichen bei Überlauf undefiniert ist. Ob das auch beim Cast zutrifft, 
weiss ich gerade nicht - wenn ja, dann ist der Ausdruck (int8_t)0xFF 
undefiniert und der Compiler immer im Recht, völlig egal was er macht. 
Mich würde das allerdings beim Zielmarkt von IAR etwas überraschen.
OP #6644844
Lesenswert?

Ich habe die Hardware jetzt nicht auf dem Tisch, aber werde das nochmals 
versuchen Danke.
Jedenfalls spuckt mir der Compiler bei if (nWheelInc < -128) {
die Warning aus:
Warning[Pa084]: pointless integer comparison, the result is always false

Bei if (nWheelInc < -127) ist wie warning weg, was bei einem int8_t auch 
so sein muss, warum das Verhalten der if Anweisung aber anders ist kann 
ich mir im Moment nicht erklären, werde dies aber Morgen nochmals 
genauer untersuchen. Es hat mich einfach stutzig gemacht, dass der 
Debugger den Datentyp zwar mit int8_t angibt, aber die Darstellung nicht 
auf Dezimal -1 wechselt, wobei dies nicht im Watch Window ist, das 
könnte noch ein Versuch wert sein
Gast #6644867
Lesenswert?

Mach F. schrieb:
> warum das Verhalten der if Anweisung aber anders ist kann
> ich mir im Moment nicht erklären,

ich kenne den compiler nicht aber:
der Vergleichswert "0" ist ein signed int (also 32 Bit).
Den vergleichst Du mit einem sint8_t.
-> er wird vor dem Vergleich erst auf eine 32 Bit Zahl erweitert.
Eventuell wird dabei das Vorzeichen unterschlagen.

Gruß Anja
Moderator #6644879
Lesenswert?

Das Ergebnis von (int8_t)255 ist zwar implementation defined, ich kann
mir aber nicht vorstellen, dass irgendein ARM-Compiler dafür bewusst
einen anderen Wert als -1 liefert. Unbewusst (d.h. auf Grund eines Bugs)
wäre dies zwar denkbar, aber unwahrscheinlich. Ob tatsächlich ein Bug
vorliegt, kann man dem erzeugten Assemblercode entnehmen.

Dass der Debugger 0xFF anzeigt, braucht dich nicht zu beunruhigen, da
die Hexadezimaldarstellung in C (also bspw. auch in printf) immer
vorzeichenlos ist. Wenn du den Debugger dazu bringen kannst, den Wert
dezimal anzuzeigen, wirst du ziemlich sicher die erwartete -1 sehen.
(Firma: fritzler-avr.de) #6644891
Lesenswert?

Yalu X. schrieb:
> Unbewusst (d.h. auf Grund eines Bugs)
> wäre dies zwar denkbar, aber unwahrscheinlich.
Beim IAR ist das aber warscheinlicher als woanderswo ;)

@machfax
Der Mouseover des IAR Debuggers ist sehr unzuverlässig und zeigt meist 
"irgendwas" an.
Der schnallt einfach nicht, dass es ein int ist und nutzt trotzdem die 
Hex Darstellung.
Packe die Variable in das Watchfenster und stell von Hex auf Decimal um.
Gast #6644924
Lesenswert?

Mach F. schrieb:
> if (nWheelInc < -128) {
> die Warning aus:
> Warning[Pa084]: pointless integer comparison, the result is always false

Verstehe ich irgendwas nicht? Wenn nWheelInc ein int8 ist, ist das doch 
korrekt. Es kann nicht kleiner -128 werden und damit ist der Ausdruck 
niemals true?

Du sagst doch selbst, beim Vergleich mit < -127 geht es, ja weil es noch 
-128 sein kann.

Was übersehe ich, was ist die Erwartung?
#6644940
Lesenswert?

Mach F. schrieb:
> ja habe ein Problem mit dem Compiler,

Nach all dem, was du also so geschrieben hast, scheint das Problem doch 
eher vor dem Computer zu sitzen. Es gibt keine fehlerfreie Software, 
aber das ein gcc einen einfachen signed-Vergleich versemmelt, ist doch 
eher unwahrscheinlich.

Da du aber keine aussagekräftige Sourcen zeigst, ist die ganze 
Diskussion müßig. Zeig ein compilierbares Beispiel mit dem „Fehler“, 
dann schauen wir weiter.

Oliver
OP #6644944
Lesenswert?

Oliver S. schrieb:
> Mach F. schrieb:
>
>> ja habe ein Problem mit dem Compiler,
>
> Nach all dem, was du also so geschrieben hast, scheint das Problem doch
> eher vor dem Computer zu sitzen. Es gibt keine fehlerfreie Software,
> aber das ein gcc einen einfachen signed-Vergleich versemmelt, ist doch
> eher unwahrscheinlich.
> Da du aber keine aussagekräftige Sourcen zeigst, ist die ganze
> Diskussion müßig. Zeig ein compilierbares Beispiel mit dem „Fehler“,
> dann schauen wir weiter.
> Oliver

sehr sehr hilfreich... ich habe ja geschrieben dass der breakpoint nicht 
getriggert wird. Natürlich sitzt das Problem vor dem Computer, die Frage 
ist nur vor welchem ;-)
#6644961
Lesenswert?

Große Auswahl gibts ja nicht...

Geh einfach mal davon aus, daß der Compiler einen int-Vergleich 
fehlerfrei hinbekommt. Was dazu führt, daß der Fehler, wenn’s denn 
überhaupt einer ist, woanders her kommt.

Ein Kandidat wäre z.B. scp_transmit..., daß das Array über die Grenzen 
beschreibt, oder auch einfach Kompilierung mit Optimierung, die sich 
schlicht im Debugger verwirrt, oder ein falsch initialisierter Stack, 
oder was auch immer.

Da gibt es Unendliche viele Möglichkeiten, aber der int-Vergleich ist 
mit Sicherheit nicht das Problem.

Hinner schrieb:
> Hier gibt es weiteres Futter zum Nachlesen:
>
> Beitrag "ergebnis kann negativ werden, obwohl nur uint8_t verwendet
> wird"

Ist eine andere Baustelle.

Oliver
OP #6644968
Lesenswert?

Oliver S. schrieb:
> Da gibt es Unendliche viele Möglichkeiten, aber der int-Vergleich ist
> mit Sicherheit nicht das Problem.

Das denke ich auch nicht. scp_transmit funktioniert einwandfrei, 
Optimierungen sind komplett deaktiviert. So wie ich das sehe, ist diese 
"einfache" Abfrage doch nicht so einfach wie es auf den ersten Blick 
aussieht -> Beitrag "ergebnis kann negativ werden, obwohl nur uint8_t 
verwendet wird"

Ich finde es einfach nicht sehr konstruktiv, wenn hier im Forum immer 
wieder direkt Leute angegriffen und als Idiot abgestempelt werden, und 
das ist definitiv nicht das erste Mal dass ich dies (bei meinen wie auch 
bei anderen Threads) sehe. Finde dies ehrlich gesagt schade.
#6644984
Lesenswert?

Nochmal im Klartext:

Der Code, von dem du meinst, daß er fehlerhaft ausgeführt wird, lautet:
1
if (nWheelInc >=0){
2
...
3
} else {
4
...
5
}

Das ist so einfach, wie es aussieht. Ende der Diskussion.

Und wer Code als .png anhängt, hat gleich vom ersten Beitrag an ein 
schlechtes Standing. Ist leider auch so.

Oliver
OP #6644987
Lesenswert?

Oliver S. schrieb:
> Das ist so einfach, wie es aussieht. Ende der Diskussion.

korrekt, dann erklär mir doch bitte mal warum bei einem Wert von 0xFF 
nicht die else Anweisung ausgeführt wird.

Auf das png muss ich nicht weiter darauf eingehen, es war eine schnelle 
Möglichkeit, den Teil vom Code zu zeigen, nicht mehr und nicht weniger, 
und scheinbar hat es auch sein Ziel erreicht. Leider bin ich zu blöd um 
zu sehen, wie man Code-Statements hier einfügen kann, entschuldige 
bitte.
#6645016
Lesenswert?

Mach F. schrieb:
> korrekt, dann erklär mir doch bitte mal warum bei einem Wert von 0xFF
> nicht die else Anweisung ausgeführt wird.

Oliver S. schrieb:
> Da gibt es Unendliche viele Möglichkeiten, aber der int-Vergleich ist
> mit Sicherheit nicht das Problem.

Wenn solche Fehler an Stellen auftreten, wo keine Fehler auftreten 
können, liegt das Problem häufig ganz woanders. Startup-Code, 
Linkerscript, sämtlicher anderer Code im Projekt, was auch immer. Nur 
nicht da, wo du suchst.

Du suchst an der falschen Stelle.

Oliver
OP #6645028
Lesenswert?

Also als Backup-Lösung werde ich dies dann implementieren, aber 
interessieren würde es mich trotzdem, warum dies mit dem cast nicht 
geht. Ich melde mich, sobald ich dies mit dem cast ausprobiert habe.
1
uint8_t nWheelInc = 0;
2

3
/*-- Code Statements 
4
nWheelInc = BUF_READ_BE_U8_F(data_p, 0);
5
if (nWheelInc > 127) {
6
        //invert the Increments
7
        nWheelInc = 128 - (nWheelInc & 0x7F);
8
        ...
9
    } else {
10
       ...
11
    }
Gast #6645080
Lesenswert?

Wie andere schon schrieben: der Code ist zwar nicht schön, macht aber 
das, was du willst.  Such den Fehler woanders.  Debugger sind notorisch 
unzuverlässig - schau dir den generierten Code an.  Evtl wird das Lesen 
des Buffers ja verschoben und der Buffer, auf den data_p zeigt, ist doch 
nicht so "const" und scp_transmit ändert den?  Oder du hast den falschen 
code gebrannt ...
OP #6645806
Lesenswert?

Update, funktioniert so:
1
uint8_t nWheelInc = 0;
2
uint8_t nWheelAbs = 0;
3
bool bWheelNegative = false;
4

5
nWheelInc = BUF_READ_BE_U8_F(data_p, 0);
6

7
//check if the value is Inc or Dec and cast to have an absolute value for CIP
8
    if ((int8_t)nWheelInc < 0) {
9
        bWheelNegative = true;
10
        nWheelAbs = (int8_t)(-nWheelInc);
11
    } else {
12
        bWheelNegative = false;
13
        nWheelAbs = nWheelInc;
14
    }
15
...
16

17
//nur noch mit nWheelAbs und bWheelNegative arbeiten
#6645827
Lesenswert?

Mach F. schrieb:
> Update, funktioniert so

Das mag ja sein, aber magst du soetwas abgeben?

Hast du dir, wie oben schon vorgeschlagen, den generierten Assemblercode 
mal angesehen? Also von der Version die nicht funktioniert? Bzw. wenn 
der Debugger auf der scheinbar falsch ausgeführten if Anweisung steht, 
dann(!) den Wert der Variablen nWheelInc angeschaut? Oben im 
Eröffnungspost liegen noch 2 Statements vor der if-Anweisung. Vielleicht 
machen die etwas kaputt?
Das Pflaster, was du da jetzt drauf geklebt hast, ich würde das nicht 
abgeben mögen. Würde ich maximal auf meinem Basteltisch machen wenn ich 
keine Zeit habe. Aber im Job nicht.
Am Ende ist es natürlich deine Entscheidung.

Edit: Aus Neugier... was ist das für eine CPU und welcher Compiler.
OP #6645848
Lesenswert?

Update:
Es ist ein STM32G474VE-T6, IAR 8.50.9
Der cast auf (int8_t) auf den BUF_READ_BE_U8_F funktioniert nicht
1
nWheelIncs = (int8_t)(BUF_READ_BE_U8_F(data_p, 0));

Es ist jetzt so:
1
uint8_t nWheelInc = 0;
2
bool bWheelNegative = false;
3

4
nWheelInc = BUF_READ_BE_U8_F(data_p, 0);
5

6
//check if the value is Inc or Dec
7
    if ((int8_t)nWheelInc < 0) {
8
        bWheelNegative = true;
9
    } else {
10
        bWheelNegative = false;
11
    }
12

13
// get the absolute value for CIP
14
t_RemoteControl._Integer.Integer = abs ((int8_t)nWheelInc);
15
IN_ReleaseUnit.Event_RemoteControl(bWheelNegative? Event_RemoteControl_Decrement : Event_RemoteControl_Increment, &t_RemoteControl);
(Firma: fritzler-avr.de) #6645884
Lesenswert?

900ss D. schrieb:
> Aber trotzdem ist es schräg, dass die
> if-Anweisung so wie am Anfang beschrieben, nicht funktioniert. Es steht
> ja (angeblich) 0xFF drin was negativ ist.

Das ist beim IAR 8.x leider gang und gäbe.
Das hab ich schon so oft erlebt, dass es nicht mehr feierlich ist.
Beim IAR 7.x gabs diese Probleme nicht.
Offensichtlich hat der Probleme beim recompilen wenn man nur etwas an 
einer Funktion ändert, ein Rebuild All löst das dann meistens.
(Beim GCC hab ich sowas jedenfalls noch nie erlebt, egal welche Version)

Beispiel im Anhang!
Da war nichtmal ein cast im Spiel.
Es läuft nur ein Task und niemand weiter schreibt die Variable.
Der Debugger steht auf dem if -> das bool steht auf true.
Drückste einmal F10 für Step und du landest im else Zweig, auf einmal is 
die Variable false.
Hä was? Ein Rebuild All löste das Problem.
Der IAR bekommt auch des öfteren Änderungen in Headern nicht mit, da hab 
ich mir auch schonmaln Wolf gesucht.

Ich kann daher Mach F. (und der Firma in der er arbeitet) nur empfehlen 
sich nach einem ordentlichen Compiler/IDE umzusehen!
Angehängte Dateien:
#6645890
Lesenswert?

Mach F. schrieb:
> Es ist ein STM32G474VE-T6, IAR 8.50.9
> Der cast auf (int8_t) auf den BUF_READ_BE_U8_F funktioniert nicht

Ganz ehrlich, ein Compiler, der bei solch grundlegenden Dingen versagt, 
gehört sofort in die Tonne. Da das Ding zudem noch nicht ganz wenig Geld 
gekostet hat, wirds jetzt wirklich Zeit für einen bitterbösen Brief an 
IAR.

Allerdings erst, nachdem nachgeweisen wurde, daß der Compiler wirklich 
Murks macht, und nicht nur der Debugger, oder der Fehler von woanders 
kommt.

Oliver
Gast #6645903
Lesenswert?

900ss D. schrieb:
> Keiner N. schrieb:
>> das if kannst du auch wehschmeißen
>
> Was für einen Vorteil hätte das? Außer das man die Tastatur schont?

Man kann die Variable richtig initialisieren, wenn man sie definiert
1
bool bWheelNegative = (int8_t)nWheelInc < 0;

Warum wurde die Variable vorher mit false initialisiert?
#6645909
Lesenswert?

mh schrieb:
> Man kann die Variable richtig initialisieren, wenn man sie definiert

Der Wert von nWheelInc ist noch nicht bekannt. Ja klar kann man alles 
hinschustern und noch mehr schlecht lesbaren Code produzieren.
Und ohne Klammern geht das bei "uns" auch nicht durch Rulechecker wenn 
der Compiler nicht schon eine Warnung wirft. Aber das ist alles OT hier.
Gast #6645917
Lesenswert?

900ss D. schrieb:
> mh schrieb:
>> Man kann die Variable richtig initialisieren, wenn man sie definiert
>
> Der Wert von nWheelInc ist noch nicht bekannt.
Da wo das If-Statement steht ist nWheelInc bekannt. Die Definition von 
bWheelnegativ kommt da hin, wo sie das erste mal gebraucht wird und 
nicht an den Anfang der Funktion.

> Ja klar kann man alles  hinschustern und noch mehr schlecht lesbaren Code > 
produzieren. Und ohne Klammern geht das bei "uns" auch nicht durch
> Rulechecker wenn der Compiler nicht schon eine Warnung wirft. Aber das
> ist alles OT hier.
Bei "euch" ist das so. Bei uns würde so eine Definition mit vermutlich 
unsinniger Initialisierung nicht durchs Review kommen, da es die 
Wartbarkeit der Software reduziert.
Persönliche Seite #6645960
Lesenswert?

Mach F. schrieb:
> Update, funktioniert so:

Sorry, aber ich finde es trotzdem einen Fehler, eine uint8_t Variable zu 
erstellen, wenn man diese später als int verwenden will. So weit ich 
sehe, ist doch nur das Makro das Problem - und da steht nicht viel drin.

Mach F. schrieb:
> ((((uint8_t)(*(((const uint8_t *)buffer_p) + (offset) + 0))) <<  0))

Warum das ganze nicht entsprechend anpassen und komplett mit int8_t 
arbeiten?
OP #6646004
Lesenswert?

Christian H. schrieb:
> Warum das ganze nicht entsprechend anpassen und komplett mit int8_t
> arbeiten?

Weil dieses Makro normalerweise immer für uint benötigt wird, nur in 
diesem speziellen Fall müssen die Daten vom RX Buffer als signed 
interpretiert werden und ich wollte dasselbe Makro verwenden. Ja ich 
könnte dies jetzt anpassen und ein spezielles Makro für diesen einen 
Fall erstellen oder den Buffer in uint auslesen und danach casten, was 
ich jetzt auch so mache.
Gast #6646157
Lesenswert?

Mach F. schrieb:
> Die Darstellung ist mir egal, die if Anweisung danach mit >= 0
> funktioniert so nicht, denn -1 ist ja wie im Debugger zu sehen ist 0xFF
> und darum ist die if >= 0 bei 0xFF true, was ich genau nicht möchte. Ich
> muss alle negativen Werte im else behandeln. Das ist die wirklich
> einfache Aufgabe, aber da es nicht funktionierte habe ich im Debugger
> den Wert angeschaut und war etwas erstaunt, dass ich 0xFF anstatt -1
> angezeigt bekam.

Hallo,

in wie weit könnten die in folgendem Link beschriebenen "integral types" 
des C-Standards das sonderbare Verhalten erklären?
https://www.iar.com/knowledge/support/technical-notes/general/integral-types-and-possibly-confusing-behavior/

Ein rudimentärer cast von uint8_t auf int8_t liefert laut dem 
angehängten Screenshot das erwartete Ergebnis und der "else" Zweig wird 
durchlaufen.

Kannst Du an Hand der Variablenwerte im Watch-Window, bzw. des 
generierten Assembler-Codes eingrenzen, was die fehlerhafte if-Abfrage 
in Deinem Code verursacht?

Gruß,
Michael
Angehängte Dateien:
#6646163
Lesenswert?

Michael F. schrieb:
> in wie weit könnten die in folgendem Link beschriebenen "integral types"
> des C-Standards das sonderbare Verhalten erklären?

Gar nicht.

Der Code, der angeblich nicht funktioniert, lautet:
1
    int8_t nWheelInc = 0;
2
    nWheelInc = (int8_t)(BUF_READ_BE_U8_F(data_p, 0));
3
    if (nWheelInc >=0){
4
...
5
    } else {
6
...
7
    }

Da wird nichts promoted, nWheelInc selber wird nicht mal gecastet, 
sondern nur zugewiesen und dann verglichen. Da kann und darf nichts 
schiefgehen, was mit der Sprachdefinition von C zu tun hat.

Alles drumherum allerdings schon

Oliver
Gast #6646210
Lesenswert?

Hier wird mal wieder typisches Voodoo-Programing betrieben.  Korrekter 
C-Code tut nichts das Erwartete und wird ziellos solange verändert, bis 
es passt.  Das ursprüngliche Problem bleibt bestehen und der Fehler wird 
auf den Compiler geschoben.  Meiner Erfahrung nach, ist das fast immer 
falsch, der Compiler ist korrekt und der Fehler liegt beim 
Programmierer.  Wie auch immer: einem ist nicht geholfen - wenn der 
Compiler defekt ist, wird der Fehler auch in anderen Programmteilen 
vorkommen und man hat es nur noch nicht gefunden; das gleiche passiert, 
wenn die Programmierlogik verkehrt ist.  Ziel sollte immer sein, den 
Fehler zu verstehen!

Ist es denn so schwierig, im Debugger mal kurz auf Assembler-Mode 
umzuschalten und nachzuschauen, ob wirklich der Code produziert wurde, 
den man erwartet hat?  Dann weiß man sofort, ob der Compiler 
fehlerhaften Code produziert hat.

Je länger ich drüber nachdenke, desto wahrscheinlicher kommt mir das 
"const" als Fehlerursache vor:
1
Pseudocode ohne const (push/pop temp register):
2
   load reg,*data_p
3
   push reg
4
   call scp_transmit
5
   pop reg
6
   comp reg,0
7
   ...
8

9
Pseudocode mit const (reload temp register from const-pointer):
10
   load reg,*data_p  // evtl ganz wegoptimiert
11
   call scp_transmit
12
   load reg,*data_p
13
   comp reg,0
14
   ...

Falls der Buffer, auf den data_p zeigt, während des Aufrufs von 
scp_transmit verändert wird, ist der Fehler sofort offensichtlich.

Also nochmal: besteht die Möglichkeit, dass während des Aufrufs von 
scp_transmit, die Daten, auf die data_p zeigt, verändert werden?  Egal 
ob durch Nutzung des gleichen Buffers von scp_transmit oder durch 
längere Laufzeit mit zwischenzeitlichen Interrupts?

Falls ja, musst du dir überlegen, ob das Weglassen von "const" wirklich 
das Problem löst ...
#6646257
Lesenswert?

(prx) A. K. schrieb:
> Das Verhalten müsste also bei IAR irgendwo dokumentiert sein.

Indirekt ist es das in dem o.a. link:

Michael F. schrieb:
> in wie weit könnten die in folgendem Link beschriebenen "integral types"
> des C-Standards das sonderbare Verhalten erklären?
> 
https://www.iar.com/knowledge/support/technical-notes/general/integral-types-and-possibly-confusing-behavior/

Beispiel 3 kommt dem am nächsten. Danach werden die unteren 8 bit des 
int für den int8_t genommen, und damit müsste der Vergleich >=0 
funktionieren. Schief ginge das mit Werten < -128, wenn die 
Vorzeichenbits aus dem letzten Byte rausrutschen, da der aber aus einem 
uint8_t promoted wurde, kommt das nicht vor.

Oliver
Gast #6646420
Lesenswert?

Also der Debugger ist schon grenzwertig.
Er zeigt als Datentyp int8_t und den Wert als char plus uint8_t.

Da hätte ich jetzt von IAR mehr erwartet.
(Selbst VSCode mit GCC zeigt die Datentypen int8_t, uint8_t korrekt 
an....)
Gast #6646439
Lesenswert?

Interessant, die Screenshots von Mach F. und Michael F. zeigen, dass 
beide die Version IAR 8.50.9 genutzt haben. Bei Michael wird aber der 
Wert im Watch Fenster als negativer Wert dargestellt.

Eine Frage an Mach: hast Du mal wirklich ein clean und rebuild all 
gemacht?
Gast #6646444
Lesenswert?

Und noch eine blöde Frage:
Ihr habt nicht zufällig euch den Datentyp int8_t durch ein uraltes Makro
im Code ala
#define int8_t ....
verbastelt?

Hatte zwar auch schon Probleme mit der IAR Workbench, aber meistens lag 
das Problem doch eher auf Programmiererseite...
Moderator #6646476
Lesenswert?

Marc schrieb:
> Also der Debugger ist schon grenzwertig.
> Er zeigt als Datentyp int8_t und den Wert als char plus uint8_t.

Wie ich oben schon schrieb, ist es bei Hex-Zahlen nicht üblich, sie mit
Vorzeichen anzuzeigen, schon gar nicht im C-Umfeld. Die Hex-Schreibweise
dient ja primär dazu, das Bitmuster herauslesen zu können, was aber bei
negativem Vorzeichen, arg erschwert würde.

Marc schrieb:
> Interessant, die Screenshots von Mach F. und Michael F. zeigen, dass
> beide die Version IAR 8.50.9 genutzt haben. Bei Michael wird aber der
> Wert im Watch Fenster als negativer Wert dargestellt.

Bei Michael wird er nicht hexadezimal, sondern dezimal und deswegen mit
Vorzeichen dargestellt. Ich schätze, dass man das Ausgabeformat im
Debugger irgendwo einstellen kann.
Gast #6646480
Lesenswert?

> [assembler.jpg]

Sieht vollkommen korrekt aus - macht genau das, was im C-Code steht. 
Wäre natürlich hilfreich gewesen, zu wissen, welchen Wert R7 in der 
grünen Zeile hat und wo jetzt überhaupt ein "Fehler" auftritt (das 
ursprüngliche IF gibt's ja nicht mehr).
Gast #6646486
Lesenswert?

Yalu X. schrieb:
> Die Hex-Schreibweise
> dient ja primär dazu, das Bitmuster herauslesen zu können, was aber bei
> negativem Vorzeichen, arg erschwert würde.

Bei Anzeige von "char" ist das natürlich so, da hätte ich ggf auch eine 
dazu passende Hex Zahl. Aber der Debugger zeigt ja "int8_t" als Datentyp 
an, da hätte ich erwartet, dass er automatisch den dezimaln Wert mit 
Vorzeichen anzeigt.
Moderator #6646498
Lesenswert?

foobar schrieb:
> Sieht vollkommen korrekt aus

Sehe ich auch so. Ich schätze, dass danach in bWheelNegative auch der
erwartete Wert steht.

Aber der Code ist ja ein ganz anderer als der ursprüngliche, in dem der
Fehler auftrat. Zum einen gibt es dort die if-Anweisung, zum anderen
wird dort nWheelInc schon vor dem Aufruf von scp_transmit beschrieben.
Wer weiß, ob nicht in scp_transmit auf Grund eines Pufferüberlaufs o.ä.
nWheelInc überschrieben wird, so dass bei der if-Anweisung ein ganz
anderer Wert ankommt.

@Mach:

Hast du dir eigentlich in deinem ursprünglichen Code den Breakpoint auch
mal auf die if-Anweisung gesetzt und dir dort den Wert von nWheelInc
anzeigen lassen? In deinen bisherigen Screenshots sieht es so aus, als
ob du nur die korrekte Zuweisung in nWheelInc=... überprüft hast, nicht
aber, ob der Variableninhalt danach möglicherweise geändert wurde.


@Marc:

Marc schrieb:
> Aber der Debugger zeigt ja "int8_t" als Datentyp an, da hätte ich
> erwartet, dass er automatisch den dezimaln Wert mit Vorzeichen
> anzeigt.

Ja, sinnvoller wäre das auf jeden Fall. Immerhin hat es Michael
geschafft, dem Debugger auch die Dezimaldarstellung zu entlocken.
Gast #6646540
Lesenswert?

Oliver S. schrieb:
> Wenn’s jetzt noch der nicht funktionierende Code wäre,

Den hat er ja noch nie gezeigt. Er hat nicht einmal gesagt, ob der Code 
nicht funktioniert hat oder was falsch lief. Er hatte eigentlich nur 
einen Breakpoint, der nicht gebreakt hat.

Mach F. schrieb:
> Wenn ich einen Breakpoint im else setze, wird dieser nicht getriggert,
> auch bei 0xFF oder eben -1 nicht.
OP #6646649
Lesenswert?

Oliver S. schrieb:
> Wenn’s jetzt noch der nicht funktionierende Code wäre, und dazu als
> Text, und nicht als Bild, wäre es noch besser...
1
static void on_cmd_wheel_turned_f(const uint8_t *data_p, uint_fast16_t data_length) {
2
    /*-- Local Variables ---------------------------------------------------------------*/
3
    union tDATA_Event_RemoteControl t_RemoteControl;
4

5
    uint8_t response_a[SCP_PAYLOAD_MAX_LENGTH];
6
    size_t  response_len = 0;
7
    int8_t nWheelInc = 0;
8
    uint16_t nLogValue = 0;
9

10
    /*-- Code Statements ---------------------------------------------------------------*/
11
    nWheelInc = (int8_t) BUF_READ_BE_U8_F(data_p, 0);
12

13
    response_a[response_len++] = SCP_STATUS_OK;
14
    scp_transmit_f(SCP_CMD_WITH_ACK_F(CMD_WHEEL_TURNED), response_a, response_len);
15

16
    if (nWheelInc >= 0) {
17
        t_RemoteControl._Integer.Integer = (uint8_t) nWheelInc;
18
        IN_ReleaseUnit.Event_RemoteControl(Event_RemoteControl_Increment, &t_RemoteControl);
19
    } else {
20
        //invert the Increments
21
        t_RemoteControl._Integer.Integer = (uint8_t) -nWheelInc;
22
        IN_ReleaseUnit.Event_RemoteControl(Event_RemoteControl_Decrement, &t_RemoteControl);
23
    }
24

25
    BUF_WRITE_BE_U8_F(nLogValue, 0, CMD_WHEEL_TURNED);
26
    BUF_WRITE_BE_U8_F(nLogValue, 1, (uint8_t) nWheelInc);
27

28
    WriteDiagnoseBuffer (SENSOR_RC_COMMAND, nLogValue);
29
}
Hab es reverted und beim Watch auf dez gestellt, rebuild all, jetzt 
funktioniert auch dieser erste Code. Der einzige Unterschied zum init 
Post war das Rebuild all...

Entschuldigt bitte all die Zeit die Ihr aufgewendet habt, aber eine 
anregende Diskussion war es allemal. Schönen Abend allerseits
Angehängte Dateien:
Gast #6646871
Lesenswert?

Mach F. schrieb:
> Hab es reverted und beim Watch auf dez gestellt, rebuild all, jetzt
> funktioniert auch dieser erste Code.

Das ist hoch anständig von Dir, dass Du es am Ende doch noch mal 
versucht hast und das Ergebnis postest. Ich dachte schon, Du wärest mit 
Deinen "Patchen" zufrieden. Aus sowas entsteht schnell Voodoo: Wenn 
etwas nicht geht, dann obskure Verrenkungen weil "der Compiler spinnt".

Das gibt es natürlich auch, aber nicht bei O0 und trivialen Dingen. Und 
wenn doch, sollte man erst Recht nicht flicken, bevor man den Fehler 
isoliert und vom Hersteller bestätigt hat. Wenn man einfachen 
Anweisungen nicht trauen kann, wie soll man jemals Fehler suchen.
OP #6646917
Lesenswert?

A. S. schrieb:
> Das ist hoch anständig von Dir, dass Du es am Ende doch noch mal
> versucht hast und das Ergebnis postest. Ich dachte schon, Du wärest mit
> Deinen "Patchen" zufrieden. Aus sowas entsteht schnell Voodoo: Wenn
> etwas nicht geht, dann obskure Verrenkungen weil "der Compiler spinnt".

Das ist das Mindeste was ich tun sollte nachdem alle so viel Zeit damit 
verbracht haben. Danke
Gast #6646961
Lesenswert?

Oliver S. schrieb:
> (prx) A. K. schrieb:
>> Das Verhalten müsste also bei IAR irgendwo dokumentiert sein.
>
> Indirekt ist es das in dem o.a. link:

Jein... Das implementation defined behavior des IAR Compilers ist im 
"C/C++ Reference Guide" beschrieben.

Yalu X. schrieb:
> Bei Michael wird er nicht hexadezimal, sondern dezimal und deswegen mit
> Vorzeichen dargestellt. Ich schätze, dass man das Ausgabeformat im
> Debugger irgendwo einstellen kann.

Der Debugger zeigt im Watch-Fenster per Default den Wert als ASCII + HEX 
an. Über einen rechts-klick auf die Variable kann das Ganze dann 
beispielsweise als "Dezimal" interpretiert werden. Über "Show As" sind 
dann noch mehr Optionen möglich (siehe Screenshot).

Gruß,
Michael
Angehängte Dateien:
(Firma: fritzler-avr.de) #6647798
Lesenswert?

Mach F. schrieb:
> Der einzige Unterschied zum init
> Post war das Rebuild all...

Hatte ich dir ja schon oben geschrieben, dass der IAR v8 da ein paar 
üble Macken hat ;)

Auf einem SAM9G45 setzt der neue IAR8.x übrigens manchmal den Breakpoint 
nicht wenn die CPU läuft.
Es hat sich nur der IAR von v7.x auf v8.3/8.5 geändert.
Gleicher J-Link, gleiches HW Target, gleicher PC, kein Win10 Update 
zwischendurch.

Da haste eine main Schleife und weist zu 100%, dass der da durchläuft.
Setzt den Breakpointer, der kommt nicht.
Drückst beim IAR auf Pause und dann run -> Breakpoint kommt.
Ganz großes Kino!

Auf STM32 ist das bisher allerdings nicht passiert.
Da hat der IAR eine ganz andere Marotte!
Manchmal überspringt er Funktionen bei F11 (Step Into).
Passiert nur auf unseren STM32 Targets, auf dem dicken Cortex-A 
passierts nicht.
Zudem hab ichs nur bei CPP Code mit virtual functions (Sprungtabelle) 
erlebt.
Da verschluckt er sich wohl manchmal...

Mach F. schrieb:
> Entschuldigt bitte all die Zeit die Ihr aufgewendet habt
Es hat ja vor allem viel Entwicklerzeit für die Firma gekostet, nämlich 
deine.
Wenn das öfter vorkommt muss man mals Tooling überdenken ;)

@Michael F:
Was machen die rutschenden Breakpoints?
Da gabs im THread ja kein STatusupdate mehr von dir.
OP #6648059
Lesenswert?

Oliver S. schrieb:
> Na ja, das könnte dein Chef anders sehen. Der bezahlt dich für
> Ergebnisse, nicht zum rumprobieren.

genau so ist es, nur Ergebnisse zählen, aber jeder und jede die in der 
Entwicklung arbeiten wissen auch, dass der Tag 24h hat und nicht immer 
alles nach Plan läuft, zumindest habe ich das noch nie erlebt, wäre ja 
auch langweilig... obwohl es zugegebenermassen ein wirklich sehr sehr 
dummer "Bug" war aber das gibt es nun mal...

Schönen Abend noch
Gast #6649075
Lesenswert?

Mw E. schrieb:
> Auf einem SAM9G45 setzt der neue IAR8.x übrigens manchmal den Breakpoint
> nicht wenn die CPU läuft.
> Es hat sich nur der IAR von v7.x auf v8.3/8.5 geändert.
> Gleicher J-Link, gleiches HW Target, gleicher PC, kein Win10 Update
> zwischendurch.

Mw E. schrieb:
> Manchmal überspringt er Funktionen bei F11 (Step Into).
> Passiert nur auf unseren STM32 Targets, auf dem dicken Cortex-A
> passierts nicht.
> Zudem hab ichs nur bei CPP Code mit virtual functions (Sprungtabelle)
> erlebt.

Gehe ich recht in der Annahme, dass Du zu beiden Themen Support-Requests 
gestartet hast, damit die Probleme genauer untersucht werden können?

Mach F. schrieb:
> obwohl es zugegebenermassen ein wirklich sehr sehr
> dummer "Bug" war aber das gibt es nun mal...

Es wäre gut gewesen, gleich von Anfang an den erzeugten Assembler-Code 
zu posten, da nun nicht mehr nachvollziehbar ist, was schief gelaufen 
sein könnte...

Gruß,
Michael
Beitrag #6649245 wurde von einem Moderator gelöscht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren