Forum: Compiler & IDEs Was geht da ab? Bitte um hilfe


von Micha (Gast)


Lesenswert?

Hallo Leute.

Folgender Code streikt bei mir:

#include <avr/io.h>

volatile unsigned char test=0;;

void main (void)
{

  while(1)
  {
    switch(test)
    {
      case 0:
        test++;
        if (test>2)
        test=0;
        break;
      case 1:
        test++;
        if (test>2)
        test=0;
        break;
      case 2:
        test++;
        if (test>2)
        test=0;
        break;
    }
  }

}

bei jedem schleifendurchgang müsste er einen anderen case zweig
nehmen.
Aber obwohl test null ist hüpft er beim ersten mal laut avr studio
simulation sofort in den case 2 zweig.....
Warum...???!!!!!!!

bitte um eure antworten

von Feadi (Gast)


Lesenswert?

Hallo,

an Deinem Code wird es sicher nicht liegen. Dieser Code funktioniert
bei mir:
1
#include <cstdlib>
2
#include <iostream>
3
#include <windows.h> // wegen Sleep(DWORD)
4
5
using namespace std;
6
7
8
unsigned char test;
9
10
int main(int argc, char *argv[])
11
{
12
  test = 0;
13
  
14
  for (;;)
15
  {
16
    cout << (unsigned int)test << "\n";
17
18
    switch( test )
19
    {
20
      case 0:
21
        test++;
22
        break;
23
      case 1:
24
        test++;
25
        break;
26
      case 2:
27
        test = 0;
28
        break;
29
    }
30
    
31
    Sleep( 500 );
32
  }
33
  
34
  system("PAUSE");
35
  return EXIT_SUCCESS;
36
}

Dieser Code ist geschrieben in Dev-Cpp unter Windows.

AVR Studio habe ich leider nur mit Assemblerunterstützung, ich kann
nicht weiterhelfen.

Gruß, Feadi

von Volker (Gast)


Lesenswert?

volatile unsigned char test=0;;


Ein Semikolon zuviel.

von Karl H. (kbuchegg)


Lesenswert?

Schalt mal die Compileroptimierungen ab.

Der Compiler sieht nämlich überhaupt keinen Sinn darin
(und ich auch nicht) für jeden case-Zweig seperaten Code
zu erzeugen, wenn alle Zweige identisch sind.

von Micha (Gast)


Lesenswert?

Schalt mal die Compileroptimierungen ab.

Der Compiler sieht nämlich überhaupt keinen Sinn darin
(und ich auch nicht) für jeden case-Zweig seperaten Code
zu erzeugen, wenn alle Zweige identisch sind.

Das ist jetzt nur ein beispiel.

Ich habe schon einen größeren Code mit unterschiedlichen Case blöcken.

Hab mich jetzt nur aufs herunterste getestet und nichtmal das
funktioniert.

die 2 semikolons machen nicht hab ich schon getestet.

Wie schaltet man die Compileropt ab?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Anders gesagt: benutze keine degenerierten Testfälle.  Du kannst
einem Compiler, der Projekte von 100000 Quellzeilen locker in
der Praxis bewältigt, ruhig glauben, dass er compilieren kann.  Denk
dir also lieber etwas aus, was auch wirklich irgendwie sinnvollen
Code erzeugt, und gib dem Compiler das dann zum Compilieren hin.

von Karl H. (kbuchegg)


Lesenswert?

> Das ist jetzt nur ein beispiel.
>
> Ich habe schon einen größeren Code mit unterschiedlichen Case
> blöcken.

Und das kann jetzt einer von uns riechen oder wie?

> Hab mich jetzt nur aufs herunterste getestet und nichtmal das
> funktioniert.

Das funktioniert perfekt.
Das einzige was nicht funktioniert ist der Programmierer der
den Testfall gebaut hat.

> Wie schaltet man die Compileropt ab?

Menüpunkt Project / Configuration Options

Allerdings: Eine Menge Leute die viel von Compilerbau verstehen
haben eine Menge Hirnschmalz in diesen Compiler gesteckt. Die
Wahrscheinlichkeit das du einen Compilerfehler entdeckt hast
ist verschwindend gering. Sehr viel wahrscheinlicher ist es,
dass dein Programm (das richtige, nicht der Testfall!) einen
Fehler enthält.

von Micha (Gast)


Angehängte Dateien:

Lesenswert?

@Karl Heinz Buchegger
Bitte ordentlich Comments die helfen.

Naja Compilerfehler.

Entweder hat mein makefile einen fehler oder das winavr kompiliert die
elf datei nicht richtig.

Also ich schreibe den Code mit dem Programmers Notepad und kompiliere
ihn dort auch. über avr studio tu ich dann debuggen (simulieren).

Wenn ich den Code mit AVR Studio schreibe und mit AVR studio builde
(ohne makefile) dann funktionert das simulieren.

Sobald ich im AVR Studio einstelle das er ein makefile verwenden soll
funktioniert das simulieren nicht mehr richtig.

makefile habe ich mal angehängt.

Andere frage:
Ich habe im Projectverzeichnis vom AVR-Studio meine Sourcefiles.
Wenn ich diese alle einbinden will:
mit #include <beispiel.c> kommt die fehlermeldung das er das file nicht
findet.

Wie kann man dem dummen AVR studio relative pfade angeben?


schöne Grüße

von Karl H. (kbuchegg)


Lesenswert?

> Sobald ich im AVR Studio einstelle das er ein makefile verwenden
> soll funktioniert das simulieren nicht mehr richtig.

Kann ich mir nicht vorstellen. Was soll den der Simulator
damit zu tun haben ob du ein externes Makefiole benutzt?
In dem Moment in dem der Simulator loslegt, ist das Makefile
aber sowas von unintereessant.

> makefile habe ich mal angehängt.

Da ist ja immer noch die Optimierung aufgedreht!

Bist du lernresistent?
Schalt die Optimierung ab!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Entweder hat mein makefile einen fehler oder das winavr
> kompiliert die elf datei nicht richtig.

Oder du erwartest Dinge, die der Compiler dir nicht geben will.

Der Compiler ist darauf getrimmt, praxistauglich möglichst guten
Code zu erzeugen.  Typischerweise beißt sich das mit der
Anforderung vor allem beginnender Programmierer, jeden einzelnen
Schritt ihres C-Codes auch tatsächlich in der Maschine wiederzu-
finden.  Der Compiler wird bestimmte Zwischenergebnisse, die du
für dein Verständnis brauchst, eventuell am Ende gar nicht
benötigen und sie daher eliminieren.  Variablen wird er auch nur
so lange Speicherplatz (im RAM oder in einem Register) gönnen,
wie deren Ergebnis wirklich noch benötigt wird, danach kann er
diese wertvolle Resource anderweitig benutzen.  Das hat eben auch
zur Folge, dass Variablen, die gar nicht benutzt werden (also
zwar geschrieben aber nie gelesen) auch gar nicht erst existieren.

Durch Ausschalten der Optimierung kannst du den Compiler dazu
bewegen, den Code genau so zu erzeugen, wie du das hingeschrieben
hast.  Praxistauglich ist das aber nicht, und wenn dieser Code
dann funktioniert, heißt das noch lange nicht, dass der optimierte
Code trotzdem auch noch funktionieren muss.

von Karl H. (kbuchegg)


Lesenswert?

> Ich habe im Projectverzeichnis vom AVR-Studio meine Sourcefiles.
> Wenn ich diese alle einbinden will:
> mit #include <beispiel.c> kommt die fehlermeldung das er das file
> nicht findet.

Das macht man auch nicht per include.

Du klickst links im Projektbaum den Eintrag 'Source Files' an.
Rechte
Maustaste - 'Add existing Source file(s)' und zeigst ihm alle
c Dateien, die zu dem Projekt gehören.

> dem dummen AVR studio

Wer im Glashaus sitzt, ....

von Micha (Gast)


Angehängte Dateien:

Lesenswert?

>>Kann ich mir nicht vorstellen. Was soll den der Simulator
>>damit zu tun haben ob du ein externes Makefiole benutzt?
>>In dem Moment in dem der Simulator loslegt, ist das Makefile
>>aber sowas von unintereessant.

Warum kannst du dir das nicht vorstellen.

Wenn ich bei meinem Project im AVR Studio einstelle das er das makefile
verwenden soll dann funktiniert das debuggen nicht richtig.
Wenn ich ohne makefile builde, sozusagen AVR studio simuliert durch die
daten die ich in der gui angebe das makefile dann funkioniert es.

von Micha (Gast)


Lesenswert?

> dem dummen AVR studio

>>Wer im Glashaus sitzt, ....

Wenn man mit dem Visual Studio programmiert und dann macht man wieder
mal was im AVR Studio dann geht einem das schnell auf den sack.
Ich glaube man wird einfach zu bequem.

greets

von Karl H. (kbuchegg)


Lesenswert?

> Visual Studio

Du benutzt Visual Studio und findest nicht alleine raus
wie man Source Code Files zu einem Projekt hinzufügt?
Das funktionert im Visual Studio völlig gleich!

> dann funktiniert das debuggen nicht richtig.

Bis jetzt hab ich nur Bedienerfehler, bzw. falsche Einstellungen
bzw. falsche Erwartungen von dir gesehen. Da war aber auch
rein gar nichts dabei, was den Schluss zulässt dass der Debugger
nicht richtig funktioniert.

Als Trost für dich: Es gibt tatsächlich Fehler im Simulator, aber
das was du beschreibst ist definitv keiner. Alles funktioniert
genau so wie man es erwarten würde.

von Micha (Gast)


Lesenswert?

>Als Trost für dich: Es gibt tatsächlich Fehler im Simulator, aber
>das was du beschreibst ist definitv keiner. Alles funktioniert
>genau so wie man es erwarten würde

Achja.

Wenn ich eine Switch case mache und die variable beinhaltet eine 1 und
dann hüpft er in den case teil 5 das ist richtig ok..

vieleicht sollte ich die variable rückwärtszählen dann noch 3 mal
verodern und noch einmal invertieren das es hinhaut..

danke für die hilfe..

von Micha (Gast)


Lesenswert?

> Visual Studio

>>Du benutzt Visual Studio und findest nicht alleine raus
>>wie man Source Code Files zu einem Projekt hinzufügt?
>>Das funktionert im Visual Studio völlig gleich!

Ich habe im WINAVR auch die Sourcefiles in meinem Project und da muss
ich sie auch includen sonst geht nichts.

von Karl H. (kbuchegg)


Lesenswert?

Vielleicht solltest du einfach mal lernen mit deinen
Werkzeugen ukmzugehen.


Mach mal dein ach so heiss geliebtes Makefile mit dem Programmers
Notepad auf. Dann scrollst du ein bischen runter, bis du
folgenden Abschnitt siehst:


# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc
FAQ.)


Und was steht dort als Optimierungslevel?

OPT = s

s ! nicht 0 !

Du erlaubst also dem Compiler, dass er den Code umstellen
darf, solange sich an der Programmlogik nichts aendert und
der Compiler Bytes einsparen kann. Und genau das macht der
Compiler auch. Und genau das siehst du auch im Debugger.

von Marcus (Gast)


Lesenswert?

Wie wärs denn mit unterschiedlichen Anweisungen in den Zweigen? Dann
hätte dein Programm auch einen Grund das auszuführen. Hast du dir das
Ergebnis denn mal im Assembler angeschaut? Das geht doch beim Studio?
Ausserdem benutzt du kein default. Hab ich mir persönlich angewöhnt is
besser um Fehler zu finden.

Marcus

von Karl H. (kbuchegg)


Lesenswert?

> Wenn ich eine Switch case mache und die variable beinhaltet eine 1
> und dann hüpft er in den case teil 5 das ist richtig ok..

Kann ich so nicht beurteilen.
In dem von dir geposteten Beispiel ist es ok. Weder du noch
dein Programm kann den Unterschied feststellen solange du nicht
im Debugger durchstepst. Und genau das darf der Compiler: Er
darf dein Programm umstellen, solange sich das externe Verhalten
nicht verändert. Im von dir geposteten Beispiel ändert sich
rein gar nichts.

>
> vieleicht sollte ich die variable rückwärtszählen dann noch 3 mal
> verodern und noch einmal invertieren das es hinhaut..

Den Sarkasmus kannst du dir sparen, der steht dir nicht zu.
Nicht bei deinem Wissen.

von Micha (Gast)


Lesenswert?

>>Wie wärs denn mit unterschiedlichen Anweisungen in den Zweigen? Dann
>>hätte dein Programm auch einen Grund das auszuführen. Hast du dir
>>das
>>Ergebnis denn mal im Assembler angeschaut? Das geht doch beim
>>Studio?
>>Ausserdem benutzt du kein default. Hab ich mir persönlich angewöhnt
>>is
>>besser um Fehler zu finden.

Marcus

if (chColor)
    {
      switch (Colorstep)
      {
        case 1:
          BLUE++;
          if (BLUE==MAX) Colorstep++;
          break;
        case 2:
          RED--;
          if (RED==MIN) Colorstep++;
          break;
        case 3:
          GREEN++;
          if (GREEN==MAX) Colorstep++;
          break;
        case 4:
          BLUE++;
          if (BLUE==MAX) Colorstep++;
          break;
        case 5:
          RED++;
          if (RED==MAX) Colorstep++;
          break;
        case 6:
          GREEN--;
          if (GREEN==MIN) Colorstep++;
          break;
      }
    chColor=0;

So sieht meine switch case syntax aus.
ich verstehe nicht warum er in case 5 springt wenn er eigenlicht in
case1 springen sollte.

von Karl H. (kbuchegg)


Lesenswert?

Ist aus diesem kurzen Ausschnitt nicht wirklich ablesbar.
Bau mal daraus ein komplettes Programm, stell sicher, dass
es immer noch den Effekt zeigt und stell es hier rein.

In diesem Abschnitt ist nichts erkennbar, was diesen Effekt
erklären könnte. Also muss es an den Teilen liegen die du nicht
gezeigt hast. Daher die Bitte um kompletten Code. Insofern war
dein Einstiegsposting absolut vorbildlich, nur hast du einen
Fehler gemacht: Dein Testprogramm hat das Problem nicht dupliziert.
Hier sind die einzelnen case-s unterschiedlich, in deinem Testprogram
sind sie es nicht. Und da hat dann der Optimizer zugeschlagen.
Hier kann er das nicht (zumindest nicht in dem Ausschnitt den
wir sehen). Irgendwo schlägt er aber zu, da bin ich mir ziemlich
sicher. Wir muessen jetzt nur die Stelle finden wo er zuschlägt.

von Karl H. (kbuchegg)


Lesenswert?

Bist du sicher, dass er den case 5 anspringt
und nicht den case 4 ?

case 1  und case 4 sind naemlich identisch.

von Marcus (Gast)


Lesenswert?

Meine Glaskugel streikt heute leider. Ich weiss nicht ob das beim
simulieren geht, aber mach mal einen Datachangebreakpoint auf die
Variable Colorstep und schau ob sie irgendwo sonst geändert wird.

Marcus

von Marcus (Gast)


Lesenswert?

Hallo Karl-Heinz die letzten Posts hören sich eher wieder nach dir an.
Wusste gar nicht, dass du so fuchsig werden kannst;).

Marcus

von Karl H. (kbuchegg)


Lesenswert?

Wenn ich was hasse dann das, wenn die Leute die Schuld auf ihre
Werkzeuge schieben und das Ganze dann auch noch so richtig
süffisant rüberbringen. Dabei kann jeder Hauptschüler sehen, dass
sie mit ihrem Werkzeug einfach nicht umgehen können.
Sicher, jeder muss mal anfangen. Du kennst mich lange genug
um zu wissen das ich mit Anfängern kein Problem habe. Aber
wie gesagt: Fehlendes Wissen mit einer Schuldzuweisung an
die Toolchain zu kompensieren, und sich dann auch nichts sagen
lassen, da ....

von Marcus (Gast)


Lesenswert?

Ja das ist wahr, ich hab schon viele deiner Beiträge gelesen und auch
viel "rausgeholt", deswegen konnt ich mir den Beitrag einfach nicht
verkneifen. Bin gespannt ob er das Problem in den Griff bekommt. Die
zwei identischen Cases sind mir auch aufgefallen. Ich denke man kann
sich das Ergebnis so vorstellen abhängig von der Optimierung:
case 1,4:
   do something
   break;
deswegen ja auch die Frage nach dem Assembly.

Marcus

von Karl H. (kbuchegg)


Lesenswert?

> Bin gespannt ob er das Problem in den Griff bekommt

Das kriegen wir schon hin. Sobald wir das Problem bei uns
reproduzieren können haben wir was um damit zu arbeiten.

Warten wir mal ab ob es ein Missverständnis zwischen 4 und 5
war. Die einzelnen cases sehen sich sehr ähnlich. Das kann
schon mal passieren, dass man im Debugger in die falsche Zeile
rutscht. Das ist momentan meine favorisierte Theorie. So ein
'Ablesefehler' ist schnell gemacht und zusammen mit dem Optimizer
würde es das 'Problem' ohne zusätzliche Annahmen erklären.

von Marcus (Gast)


Lesenswert?

So ich leg meine Ohren nun an Masse ich wünsch ein schönes WE

Marcus

von Micha (Gast)


Lesenswert?

Guten morgen.

Es haut jetzt hin. Es war wirklich diese Compileroptimierung.

Ich glaube aber einen anderen Fehler im AVR Studio gefunden zu haben.
Vieleicht kann das jemand mal ausprobieren.

Und zwar im FAST-PWM Mode der Counter wird das COMPARE REGISTER immer
erst beim MAX des Zähler registers upgedatet.

Beim Counter0 wird das bei einem prescaler von 64 gemacht
richtigerweise bei der simulation gemacht.
Wenn ich aber sage: no perscaling dann wird das COMPARE REGISTER
einfach irgendwie upgedated. Nicht bei jedem Zählvorgang sondern ca.
bei jedem 10ten.

Beim Counter2 wird bei mir das COMPARE REGISTER mit no prescaling
SOFORT!! upgedated.

Entweder habe ich wieder mal müll gecoded oder der simulator hat
wirklich einen fehler.
Vl ist einer so nett und testet das mal.

Hier mein Code:

//Counter-Output-Compare-Registers
#define RED OCR0A
#define GREEN OCR0B
#define BLUE OCR2B

void main(void)
{

TCCR0B =(1<<CS00); //no prescaler for counter0
TCCR2B = (1<<CS20); // no precaler for counter2

TCCR0A = (1<<WGM01) | (1<<WGM00); //FastPWM-mode for Counter0
TCCR2A = (1<<WGM21) | (1<<WGM20); //FastPWM-mode for Counter2

  for (int i=0; i<=500; i++)
  {
    RED++;
  }

  for (int i=0; i<=500; i++)
  {
    GREEN++;
  }

  for (int i=0; i<=500; i++)
  {
    BLUE++;
  }

  while(1);
}

Der Code ist jetzt bei beiden Countern mit no prescaling.
Prescaler 64 für Counter 0 währe:

TCCR0B = (1<<CS01) | (1<<CS00); //prescaler clk/64

Bitte um eure Comments:

von Karl H. (kbuchegg)


Lesenswert?

> Wenn ich aber sage: no perscaling dann wird das COMPARE REGISTER
> einfach irgendwie upgedated. Nicht bei jedem Zählvorgang sondern
> ca. bei jedem 10ten.

Na ja. 'irgendwie' ist übertrieben. Es passiert immer noch dann
wenn der Zähler MAX erreicht hat. Der Unterschied ist nur, dass
du bei einem Prescaler von 1 bei einem Druck auf F10 nicht einen
Taktzyklus ausführst sondern ein C Statement. Und in diesem C-
Statement passieren mehrere Dinge: zum einen wird RED geholt,
erhöht und wieder zurückgeschrieben; zum anderen wird der
Schleifenzähler erhöht. All das  braucht von einmal F10 zum
nächsten ein paar Zyklen. Beobachte mal das Zählregister. Das
zählt nicht schön gleichmässig hoch. Und wenn da jetzt im Hintergrund
ein Zählerüberlauf stattfindet dann wird der Compare Register
update gemacht.

> Beim Counter2 wird bei mir das COMPARE REGISTER mit no prescaling
> SOFORT!! upgedated.

Ja. Ist bei mir auch so. Was sagt denn das Datenblatt dazu?
Ich hab jetzt kein Datenblatt vom Mega48 da.

von Karl H. (kbuchegg)


Lesenswert?

> Der Unterschied ist nur, dass
> du bei einem Prescaler von 1 bei einem Druck auf F10 nicht einen
> Taktzyklus ausführst sondern ein C Statement

Das ist jetzt extrem schlecht ausgedrückt. Natürlich hängt
ein F10 nicht davon ab welcher Prescaler eingestellt ist.

Bei einem anderen Prescaler merkst du das nur nicht, weil
der Timer nicht bei jedem Takt erhöht wird, sondern länger
dazu braucht. Erst bei einem Prescaler von 1 merkt man
dass da mehrere Takte für ein C-Statement draufgehen.

von Micha (Gast)


Lesenswert?

> Beim Counter2 wird bei mir das COMPARE REGISTER mit no prescaling
> SOFORT!! upgedated.

>>Ja. Ist bei mir auch so. Was sagt denn das Datenblatt dazu?
>>Ich hab jetzt kein Datenblatt vom Mega48 da.

Also laut Datenblatt wird er genau gleich wie der timer0 upgedated.
Müsste eigenlich ein BUG im AVR-Studio sein.

schöne grüße

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.