C-Mysterium beim ATMega16

Gast #232341
Lesenswert?

Hallo,
mir ist etwas widerfahren, was ich mir beim besten Willen nicht
erklären kann. Ich programmiere den ATMega16 in avr-gcc. Einige
Zählvaraiablen (long int), die vorher mit i, k, usw. benannt waren,
habe ich umbenannt in Count1, Count2, ... um die Aussagekraft zu
erhöhen. Dabei ist mir ein Ersetzungsfehler unterlaufen:

...
for (Count1=0;Count1<6;Count1++)
{
  LED[Count1] anmachen
  // Verzögerungsschleife
  for (Count2=0;Count2<15000;Count2++)
   {
        Delay++;
   }
  LED[Count1] ausmachen
}
...
while(1)
{
  ...
  for (Count1=0;Count2<15000;Count2++)
  ...
}

Vor der Endlosschleife wird eine Kaskade von 6 LEDs über ein
Schieberegister einmal von links nach rechts  zum Aufleuchten gebracht.
In der for-Schleife der Endlosschleife müsste richtigerweise
'Count2=0' statt 'Count1=0' stehen. Das wirkt sich in der
fehlerhaften Version so aus, dass der Aufleuchte-Vorgang der LEDs, der
vor der Endlosschleife steht, dann dreimal so lang dauert.
Wie kann es sein, dass ein logischer Fehler in einem sequentiellen
Programm sich auf eine vorher abgearbeitete Anweisung auswirkt?
Verletzt das nicht das Kausalitätsprinzip? Hat irgendjemand eine Idee?
Gruß Jörg
Gast #232342
Lesenswert?

Ich vermute, dass Du nur den Optimizer strapazierst. Denn wenn
"Count2" und "Delay" nicht als "volatile" deklariert sind, dann
ist
  for (Count2=0;Count2<15000;Count2++)
   {
        Delay++;
   }
aus Sicht des Compilers funktionell identisch mit
   Count2 = 15000;
   Delay += 15000;
und je nach Kontext, Laune und Wasserstand kann es sein, dass der
Compiler das mal wegoptimiert, mal nicht.

Daher: Delay-Funktion der Library verwenden.
Gast #232348
Lesenswert?

@jupp
Das Delay++ war dafür gedacht, dass die Schleife nicht wegoptimiert
wird,  obwohl die Gefahr lt. A.K. ja trotzdem besteht.

@alle
Das scheint mir aber bei mir nicht der Fall zu sein. Denn der von mir
oben beschriebene schnellere Fall, zeigt die LEDs immer noch deutlich
länger als wenn nur die beiden Befehle:

   Count2 = 15000;
   Delay += 15000;

statt der Schleife ausgeführt werden.

Was höchstens sein könnte ist, dass beim schnelleren Fall die Schleife
zu:
for (Count2=0;Count2<15000;Count2++)
   {

   }
Delay+= 15000;

teiloptimiert wird
und im langsamen Fall unverändert als

for (Count2=0;Count2<15000;Count2++)
   {
        Delay++;
   }

ausgeführt wird.

Die *.lst scheint mir die Assemblerdatei zu sein, die man diesbezüglich
untersuchen sollte, oder?
Gruß
   Jörg
Gast #232349
Lesenswert?

"Die *.lst scheint mir die Assemblerdatei zu sein, die man
diesbezüglich untersuchen sollte, oder?"

Ja.

Generell empfiehlt sich aber, erkennbar sinnlosen Code entweder ganz zu
vermeiden, oder dem Compiler unter Verwendung von "volatile" die
Optimierung abzugewöhnen. Alles andere ist ausgesprochen fragil.
Gast #232350
Lesenswert?

In der lst-Datei finde ich die Zeile

ldi r24,lo8(14999)

Ich konnte dieses 'lo8' (und auch 'hi8', das auch vorkommt) weder
im Datenblatt des ATMega, noch im 'Instruction Set' von Atmel noch in
'io.h' oder 'iom16.h'. Kannst Du mir vielleicht sagen, was deren
Bedeutung ist und wo ich hätte suchen müssen?
Gruß Jörg
Gast #232351
Lesenswert?

Hallo
das soll jetzt nicht in eine Assembler-Fragestunde ausarten, aber auf
Seite 120 des Atmel-Instruction-Set steht für den Befehl 'SBIW', dass
dort zwingend immer ein Register-Paar übergeben werden muss, als
Beispiel ist dort 'sbiw r25:r24,1' angegeben. In meinem lst-File
taucht aber die Zeile
 sbiw r24,1
auf. Widerspricht dies nicht den obigen Angaben?
Gruß Jörg
Gast #232354
Lesenswert?

Ja,
das ist mir dann auch aufgefallen. Trotzdem sollte diese Syntax doch in
irgendeinem Manual erklärt sein oder woher soll man von ihrer Existenz
wissen, wenn man sie nicht gerade aus bestehendem Code herausliest.
Zwar sind "+" oder "-" auch nicht erklärt, aber lo8 und hi8 haben
auch nicht diese Allgemeingültigkeit.
In einem DSP-Assembler-Dialekt mit dem ich auch mal gearbeitet habe,
gab es lo8 jedenfalls nicht.
Gruß Jörg

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