AVR-Studio 6 : Optimierungsproblem ?

OP #3573646
Lesenswert?

Hallo, ich habe folgendes Problem:
Ich nutze AVR-Studio 6 seit einigen Tagen, in Verbindung mit dem AVR 
Dragon und einem Olimexboard mit dem Mega 16.
Nun habe ich eine Routine um Zeitdifferenzen zu berechnen. Dieser 
Routine werden die Zeitangaben in einer struct übergeben (also ein 
Pointer darauf). Die Elemente der Struct sind unsigned!. es lässt sich 
aber einfacher rechnen wenn ich signed Variablen benutze. Deshalb habe 
ich signed Hilfsvariablen eingeführt: s, h und m.
Wenn ich nun den untenstehenden Code debugge, dann springt er mit in die 
Zeilen ab 6 nicht rein. Er führt 1,2 und 3 durch und springt dann auf 
Zeile 23. Wenn ich mir s,h und ma anschaue, dann zeigt er mir s und m 
an, bei h schreibt er "optimized away"...
Kann es sein dass der Code wegoptimiert wurde ? Wo stelle ich die 
Optimierungen ein ?


Gruß
Karlheinz




1  s = p2->second - p1->second;
2  m = p2->minute - p1->minute;
3  h = p2->hour - p1->hour;
4
5  // Evtl. Korrekturen
6  if (s < 0)
7  {
8    s += 60;
9    --m;
10  }
11
12  if (m < 0)
13  {
14    m += 60;;
15    --h;
16  }
17
18  if (h < 0)
19  {
20    h += 24;
21    flag = 1;
22  }
23  pResult->second = s;
24  pResult->minute = m;
25  pResult->hour = h;
26  if (flag)
27    pResult->day = -1;
Gast #3573696
Lesenswert?

Das Problem dürfte bereits in der ersten Zeile liegen: die Differenz 
wird noch als unsigned ausgerechnet, und ist entsprechend immer positiv. 
Die Bedingung (s<0) ist entsprechend nie erfüllt.  Das wird man noch 
einen expliziten Typecast gebrauchen, etwa:
 s = (int) (p2->second - p1->second);
Gast #3573707
Lesenswert?

Ulrich schrieb:
> Das wird man noch
> einen expliziten Typecast gebrauchen, etwa:
>  s = (int) (p2->second - p1->second);

dann kann nicht sein. Dieser cast macht kein Sinn weil er zu spät kommt.

Wenn überhaupt dann so:

s = ( (int)p2->second - p1->second);

ich würde aber fast sagen, das es automatisch in int gerechnet wird.
OP #3574095
Lesenswert?

Puh, erstmal Danke für eure Antworten. Jetzt weiß ich wenigstens wo ich 
die Compilereinstellungen ändern kann und warum das wegoptimiert wird.
Das es so ist habe ich im lss-File gesehen, der Assemblercode ist da 
eindeutig :-)
Das casten habe ich aber nicht probiert, ich hatte zwischenzeitlich die 
Idee dass ganze auf unsigned zu machen, indem ich die Zeitangaben 
einfach in Sekunden umrechne und das Ergebnis wieder zurückwandle :-)

Grrets
Karlheinz
OP #3574935
Lesenswert?

Zu früh gefreut.
Ich rufe die Funktion mit folgenden Parametern auf:
t1->hour: 23, t1->minute: 59, t1->seconds: 32

Für t1 berechnet er das Ergebnis mit 20836, dabei sollte es 86372 sein.
Fehler auch bei der Berechnung von t2.
Die Optimierungen habe ich alle ausgeschaltet.
Wenn ich mit dem Debugger in die Funktion springe, dann sagt ermit 
zunächst bei t1, t2 und t3: "Optimized ayway".
Wenn ich die Berechnung durchgeführt habe, dann steht da ein Ergebnis 
drin, leider das falsche.
Ich habe die t1, t2 und t3 auch schon als static deklariert, bringt aber 
nichts.

unsigned char TimeDiff(KM_DATE_TIME *pResult, KM_DATE_TIME *p1, 
KM_DATE_TIME *p2)
{
  uint64_t t1,t2,t3;
  char Overflow=0;
  char sbuffer[100];

  // Zielspeicher loeschen
  memset(pResult,0,sizeof(KM_DATE_TIME));

  // Differenzen auf Sekundenbasis berechnen
  t1 = 3600 * p1->hour + 60*p1->minute + p1->second;
  t2 = 3600 * p2->hour + 60*p2->minute + p2->second;
  if (t1 > t2)
  {
    t3 = t1 - t2;
    Overflow = 1;
  } else {
    t3 = t2 - t1;
  }

  pResult->hour = t3/3600;
  t3 -= pResult->hour*3600;

  pResult->minute = t3/60;
  t3 -= pResult->minute * 60;

  pResult->second = t3;

  sprintf(sbuffer,"TimeDiff: pResult: %d:%d:%d\n\r",pResult->hour, 
pResult->minute, pResult->second);
  uart_puts(sbuffer);

  return Overflow;
}
Gast #3574940
Lesenswert?

> t1 = 3600 * p1->hour + 60*p1->minute + p1->second;

in C werden Berechnungen in int ausgeführt. Damit bekommt du hier schon 
einen überlauf. Du musst die Berechnung schon zwingend mit uint64_t 
mache.

t1 = (uint64_t)3600 * p1->hour + 60*p1->minute + p1->second;

müsste für reichen. Aber Sinnvoll finde ich nicht den atmel mit 64bit 
Berechnungen zu quälen. Auf einen PC hat 32bit ewig gereicht, warum 
brauch du 64bit?
OP #3574944
Lesenswert?

ok, zur Erläuterung habe ich nochmal einen Screenshot als Anhang 
angefügt.
Ich habe jetzt die Variablen außerhalb der Funktion definiert, jetzt 
werden sie nicht mehr wegoptimiert.
Ich berechne zuerst t mit 3600 * p1->hour. pt1->hour;
p1->hour hat den Wert 23, t sollte also den Wert 82800 haben. t hat aber 
nur
17264. Woran kann das liegen ?
Angehängte Dateien:
Persönliche Seite #3574950
Lesenswert?

Ulrich schrieb:
> Das Problem dürfte bereits in der ersten Zeile liegen: die Differenz
> wird noch als unsigned ausgerechnet, und ist entsprechend immer positiv.
> Die Bedingung (s<0) ist entsprechend nie erfüllt.

Doch, denn s ist signed. 100-200 wird also 156 (wenn wir mal mit Bytes 
rechnen) und das als signed ist -100.

Peter II schrieb:
> Ulrich schrieb:
>> Das wird man noch einen expliziten Typecast gebrauchen, etwa:
>>  s = (int) (p2->second - p1->second);
>
> dann kann nicht sein. Dieser cast macht kein Sinn weil er zu spät kommt.

Nein, tut er nicht (zumindest für diese Rechnung, s.o.

> Wenn überhaupt dann so:
>
> s = ( (int)p2->second - p1->second);

Dann wird duie rechnung aber als unsigned ausgeführt, weil p1->second 
unsigned ist. Aber wie gesagt änder das nix am Ergebnis.

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