Forum: Mikrocontroller und Digitale Elektronik AVR-Studio 6 : Optimierungsproblem ?


von Karlheinz D. (kdruschel)


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;

von Robert D. (d0rni)


Lesenswert?

unter Project... "<Projektname> Properties Alt+F7" dann unter Compiler / 
Optimization.

: Bearbeitet durch User
von Amateur (Gast)


Lesenswert?

Gibt's da keinen Meckerer, das "flag" nicht initialisiert ist?
Wenn h >= 0?

von Ulrich (Gast)


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

von Peter II (Gast)


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.

von Karlheinz D. (kdruschel)


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

von Karlheinz D. (kdruschel)


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;
}

von Peter II (Gast)


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?

von Karlheinz D. (kdruschel)


Angehängte Dateien:

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 ?

von Johann L. (gjlayde) Benutzerseite


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.

von Karlheinz D. (kdruschel)


Angehängte Dateien:

Lesenswert?

Update:
SO funktioniert es, ich kann mir nur nicht erklären warum .....

von Peter II (Gast)


Lesenswert?

Karlheinz Druschel schrieb:
> SO funktioniert es, ich kann mir nur nicht erklären warum .....

habe ich doch geschrieben, die Berechnung wird mit int gemacht. Damit 
bekommst du einen Overflow. Wenn alles Variablen 64bit sind, wird auch 
mit 64bit rechnet. - aber schön ist anders.

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.