www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Compilerfehler?


Autor: Matko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute!

Im Moment arbeite ich mit einem PIC24F. An sich ganz ok, nur die 
C-Compiler (sowohl C30 als auch HI-TECH) machen teilweise meiner Ansicht 
nach seltsame Sachen:
zB: in einer Funktion wird ein IC ,der über SPI mitm µC verbunden ist, 
konfiguriert. Dazu schreibe ich in ein (lokales) Array (unsigned char 
ps_conf[5]) und übergebe dieses an meine SPI_write Funktion, die so 
aussieht:
void contWR_SPI2(unsigned char* TxData)
{
  int res, i=0;

  pulseCS();           
  SPI2STATbits.SPIROV = 0;  
  IFS2bits.SPI2IF = 0;
  res = SPI2BUF;//clear buffer and reset SPIRBF
  while(i < 4)
  {
    if(!SPI2STATbits.SPITBF) // TxBuf = empty then fill TxBuf again!
      SPI2BUF = TxData[i++];
  }
  return;         
}

Komischer Weise macht es einen Unterschied, ob ich  es so

  ps021conf[0] = 0x84;  //Addr4 + CMD
  ps021conf[1] = 0x80;  
  ps021conf[2] = 0x00;  
  ps021conf[3] = 0x00;
  contWR_SPI2(ps021conf);
   WAIT();

  ps021conf[0] = 0x85;  //Addr5 + CMD
  ps021conf[1] = 0x80;  
  ps021conf[2] = 0x00;  
  ps021conf[3] = 0x00;
  contWR_SPI2(ps021conf);

oder -da die Daten [1...3] bei beiden Adressen gleich bleiben- so 
schreibe:

  ps021conf[0] = 0x84;  //Addr4 + CMD
  ps021conf[1] = 0x80;  
  ps021conf[2] = 0x00;  
  ps021conf[3] = 0x00;
  contWR_SPI2(ps021conf);
   WAIT();

  ps021conf[0] = 0x85;  //Addr5 + CMD
  contWR_SPI2(ps021conf);

Der Unterschied ist, dass sich die einzelnen Bytes vertauschen: aus den 
Daten (in hex) 80-00-00 wird 00-00-80, wenn ich die nicht wieder neu 
reinschreib. Also hab ich mir mal das Disassembly Listing angeschaut und 
mich gewundert, dass das upper byte mit xFF befüllt ist (zB erstes 
mov.w):
1001:                ps021conf[0] = 0x83;  //Addr3 + CMD
 03F30  2FF837     mov.w #0xff83,0x000e
 03F32  2FFF86     mov.w #0xfff8,0x000c
 03F34  478306     add.w 0x001e,0x000c,0x000c
 03F36  784B07     mov.b 0x000e,[0x000c]
1002:                ps021conf[1] = 0x00;  
 03F38  200006     mov.w #0x0,0x000c
 03F3A  2FFF97     mov.w #0xfff9,0x000e
 03F3C  478387     add.w 0x001e,0x000e,0x000e
 03F3E  784B86     mov.b 0x000c,[0x000e]
1003:                ps021conf[2] = 0xC0;  
 03F40  2FFC06     mov.w #0xffc0,0x000c
 03F42  2FFFA7     mov.w #0xfffa,0x000e
 03F44  478387     add.w 0x001e,0x000e,0x000e
 03F46  784B86     mov.b 0x000c,[0x000e]
1004:                ps021conf[3] = 0x01;
 03F48  200016     mov.w #0x1,0x000c
 03F4A  2FFFB7     mov.w #0xfffb,0x000e
 03F4C  478387     add.w 0x001e,0x000e,0x000e
 03F4E  784B86     mov.b 0x000c,[0x000e]
1005:                contWR_SPI2(ps021conf);
 03F50  2FFF80     mov.w #0xfff8,0x0000
 03F52  478000     add.w 0x001e,0x0000,0x0000
 03F54  07FB6B     rcall 0x00362c
1006:                 WAIT();
 03F56  000000     nop
 03F58  000000     nop
 03F5A  000000     nop
 03F5C  000000     nop
 03F5E  000000     nop
 03F60  000000     nop
 03F62  000000     nop
 03F64  000000     nop
 03F66  000000     nop
 03F68  000000     nop
 03F6A  000000     nop
 03F6C  000000     nop
 03F6E  000000     nop
 03F70  000000     nop
 03F72  000000     nop
1007:                
1008:                ps021conf[0] = 0x84;  //Addr4 + CMD
 03F74  2FF847     mov.w #0xff84,0x000e
 03F76  2FFF86     mov.w #0xfff8,0x000c
 03F78  478306     add.w 0x001e,0x000c,0x000c
 03F7A  784B07     mov.b 0x000e,[0x000c]
1009:                ps021conf[1] = 0x80;  
 03F7C  2FF806     mov.w #0xff80,0x000c
 03F7E  2FFF97     mov.w #0xfff9,0x000e
 03F80  478387     add.w 0x001e,0x000e,0x000e
 03F82  784B86     mov.b 0x000c,[0x000e]
1010:                ps021conf[2] = 0x00;  
 03F84  200006     mov.w #0x0,0x000c
 03F86  2FFFA7     mov.w #0xfffa,0x000e
 03F88  478387     add.w 0x001e,0x000e,0x000e
 03F8A  784B86     mov.b 0x000c,[0x000e]
1011:                ps021conf[3] = 0x00;
 03F8C  200006     mov.w #0x0,0x000c
 03F8E  2FFFB7     mov.w #0xfffb,0x000e
 03F90  478387     add.w 0x001e,0x000e,0x000e
 03F92  784B86     mov.b 0x000c,[0x000e]
1012:                contWR_SPI2(ps021conf);
 03F94  2FFF80     mov.w #0xfff8,0x0000
 03F96  478000     add.w 0x001e,0x0000,0x0000
 03F98  07FB49     rcall 0x00362c
 03F9A  000000     nop
 03F9C  000000     nop
 03F9E  000000     nop
 03FA0  000000     nop
 03FA2  000000     nop
 03FA4  000000     nop
 03FA6  000000     nop
 03FA8  000000     nop
 03FAA  000000     nop
 03FAC  000000     nop
 03FAE  000000     nop
 03FB0  000000     nop
 03FB2  000000     nop
 03FB4  000000     nop
 03FB6  000000     nop
1014:              
1015:                ps021conf[0] = 0x85;  //Addr5 + CMD
 03FB8  2FF857     mov.w #0xff85,0x000e
 03FBA  2FFF86     mov.w #0xfff8,0x000c
 03FBC  478306     add.w 0x001e,0x000c,0x000c
 03FBE  784B07     mov.b 0x000e,[0x000c]
1016:              /*  ps021conf[1] = 0x80;  
1017:                ps021conf[2] = 0x00;  
1018:                ps021conf[3] = 0x00;*/
1019:                contWR_SPI2(ps021conf);
 03FC0  2FFF80     mov.w #0xfff8,0x0000
 03FC2  478000     add.w 0x001e,0x0000,0x0000
 03FC4  07FB33     rcall 0x00362c

An Addresse 0x001E ist das Working Register 15, welches als Stackpointer 
benutzt wird. Total seltsam ist zB, dass wenn man 0x80 schreibt 0xFF80 
übergeben wird, aber bei 0x00 auch 0x0000 übergeben wird. Werden die 
Daten falsch am Stack abgelegt? So 100% check ich den ASM leider noch 
nicht, deshalb wollte ich mal fragen, ob mir jemand mit mehr 
Assembler-Wissen behilflich sein kann?

MfG, Matko

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Total seltsam ist zB, dass wenn man 0x80 schreibt 0xFF80 übergeben wird,

0x80    -128  in 8-Bit
0xFF80  -128  in 16-Bit

Passt doch.

MfG Spess

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matko schrieb:

> Also hab ich mir mal das Disassembly Listing angeschaut und
> mich gewundert, dass das upper byte mit xFF befüllt ist (zB erstes
> mov.w):

Irrelevant, da von dem Wort nur das untere Byte verwendet wird.

Der Code sieht auf den ersten Blick korrekt aus.

Autor: Matko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die schnellen Antworten!

@spess53:
Warum wird mein unsigned char als signed behandelt? Und zB da nicht:
...
 1004:                ps021conf[3] = 0x01;
 03EFC  200016     mov.w #0x1,0x000c
 03EFE  2FFFB7     mov.w #0xfffb,0x000e
 03F00  478387     add.w 0x001e,0x000e,0x000e
 03F02  784B86     mov.b 0x000c,[0x000e]
1005:                contWR_SPI2(ps021conf);
...

Wie kann es sein, dass der das Array verdreht nachdem er in einer 
Funktion war?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matko schrieb:

> Warum wird mein unsigned char als signed behandelt? Und zB da nicht:

Warum hängst du dich eigentlich so an einem Byte auf, das nirgends 
verwendet wird? Er läd 16 Bits ins Register und benutzt davon 8 Bits. Ob 
die oberen 0x00 sind, oder 0xFF, oder grün-schwarz kariert, das ist 
völlig unwichtig.

>  03EFC  200016     mov.w #0x1,0x000c
>  03F02  784B86     mov.b 0x000c,[0x000e]

Ausserdem ist auch dieser Wert möglicherweise signed, nur eben positiv.

Autor: Matko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja mir is das Byte ansich egal, wobei ich es recht komisch finde, dass 
einmal was positiv, dann negativ verwendet wird. Egal, soll so sein. 
Aber wie gesagt mich stört eigentlich, dass sich die Byte-Reihenfolge 
verändert, obwohl ich in cont_WR... nur lesend darauf zugreife. Nochmal 
die selben Daten auf die selben Speicherstellen zu schreiben is doch 
nicht normal? Da muss doch was schief gehen mit den Daten die für die 
Addressierung des Arrays verwendet werden und am Stack abgelegt 
werden... oder check ich da jetzt was grad nicht?

Außerdem wollt ich noch fragen, warum der Compiler nicht sowas macht, 
obwohls eigentlich auch egal is:
1008:               ps021conf[0] = 0x84;  //Addr4 + CMD
 03F28  2FF847     mov.w #0xff84,0x000e
 03F2A  2FFF86     mov.w #0xfff8,0x000c
 03F2C  478306     add.w 0x001e,0x000c,0x000c
 03F2E  784B07     mov.b 0x000e,[0x000c++]
1009:               ps021conf[1] = 0x80;  
 03F30  2FF806     mov.w #0xff80,0x000e
 03F36  784B86     mov.b 0x000e,[0x000c]

Compileroptimierung 6...

Dankbar für jeden Tip!

Autor: Matko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matko schrieb:
> Der Unterschied ist, dass sich die einzelnen Bytes vertauschen: aus den
> Daten (in hex) 80-00-00 wird 00-00-80, wenn ich die nicht wieder neu
> reinschreib.
  ps021conf[0] = 0x84;  //Addr4 + CMD
  ps021conf[1] = 0x80;  
  ps021conf[2] = 0x00;  
  ps021conf[3] = 0x01;
  contWR_SPI2(ps021conf);
   WAIT();

  ps021conf[0] = 0x85;  //Addr5 + CMD
  contWR_SPI2(ps021conf);

Bei den Daten 80-00-01 versendet er beim zweiten Aufruf von contWr_SPI2 
00-01-80. Also der Compiler haut da es total durcheinander. Aber auch 
nur in genau dieser Funktion. Woran das genau liegt sehe ich nicht...

spess53 schrieb:
> 0x80    -128  in 8-Bit
> 0xFF80  -128  in 16-Bit
>
> Passt doch.

Oder auch voll nicht... in diesem Fall stimmts. aber zB bei 0x85 und 
0xFF85 passts nimmer. Aber ja, ich will mich nicht "auf einem Byte 
aufhängen".kA was da falsch gemacht wird. Scheiß Compiler halt...

Autor: Marcus Overhagen (marcus6100)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matko schrieb:

> benutzt wird. Total seltsam ist zB, dass wenn man 0x80 schreibt 0xFF80
> übergeben wird, aber bei 0x00 auch 0x0000 übergeben wird. Werden die

Zeig bitte mal die Definition von deinem ps021conf[] array

Ausserdem wäre es verständlicher wenn du
void contWR_SPI2(unsigned char* TxData)

ändern würdest in:
void contWR_SPI2(const unsigned char* TxData)

Autor: Matko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void Funktion(void)
{
  unsigned char ps021conf[5];

   ps021conf[0] = 0x80;   // Addresse 0
   ps021conf[1] = 0x01;
   ps021conf[2] = 0x02;
   ps021conf[3] = 0x03;
   contWR_SPI2(ps021conf);

   /* 
   ...
   und jetzt werden noch die restlichen Addressen des ICs beschrieben
   ...
  */
}

Wie gesagt: Es passt solange unmittelbar vorm der Funktion contWR_SPI2 
dem Array die Werte erneut zugewiesen werden. zB das würde falsche 
Reihenfolge ergeben in Register 1 schreiben:
void Funktion(void)
{
  unsigned char ps021conf[5];

   ps021conf[0] = 0x80;   // Addresse 0
   ps021conf[1] = 0x01;
   ps021conf[2] = 0x02;
   ps021conf[3] = 0x03;
   contWR_SPI2(ps021conf);

   ps021conf[0] = 0x81;   // Addresse 1
   contWR_SPI2(ps021conf);

   /* 
   ...
   und jetzt werden noch die restlichen Addressen des ICs beschrieben
   ...
  */
}

Reihenfolge in Register 1: 02-03-01

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matko schrieb:

> Bei den Daten 80-00-01 versendet er beim zweiten Aufruf von contWr_SPI2
> 00-01-80. Also der Compiler haut da es total durcheinander. Aber auch
> nur in genau dieser Funktion. Woran das genau liegt sehe ich nicht...

Es ist ein bischen sinnlos, aus einem beobachteten Fehlverhalten des 
eigenen Progamms auf einen Compilerfehler zu schliessen, wenn der von 
ihm erzeugte Code soweit wie hier gezeigt korrekt ist.

Autor: Matko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo ist denn mein Fehler in:
void Funktion(void)
{
  unsigned char ps021conf[5];

   ps021conf[0] = 0x80;   // Addresse 0
   ps021conf[1] = 0x01;
   ps021conf[2] = 0x02;
   ps021conf[3] = 0x03;
   contWR_SPI2(ps021conf);

   ps021conf[0] = 0x81;   // Addresse 1
   contWR_SPI2(ps021conf);

   /* 
   ...
   und jetzt werden noch die restlichen Addressen des ICs beschrieben
   ...
  */
}

A. K. schrieb:
> Es ist en bischen unfair, aus einem beobachteten Fehlverhalten des
> eigenen Progamms auf einen Compilerfehler zu schliessen, wenn der von
> ihm erzeugte Code (soweit hier sichtbar) offensichtlich korrekt ist.

Ich finds unfair mir das zu unterstellen. Ich seh den Fehler auch nicht. 
Aber auch nicht in meinem Programm. Deswegen hab ich im Forum gefragt.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matko schrieb:

> Ich finds unfair mir das zu unterstellen. Ich seh den Fehler auch nicht.
> Aber auch nicht in meinem Programm. Deswegen hab ich im Forum gefragt.

Ich kenne diesen Effekt selber ganz gut. Man findet partout keinen 
Fehler, also stellt sich die Schlussfolgerung, es könne ja nur noch der 
Compiler sein, ganz von selbst ein. Das ist ok, wenn man das dann 
nachweisen kann, denn natürlich kann es ein Compilerfehler sein - das 
ist hier im Forum (und mir selbst bei meinem ersten Versuch mit dem C30) 
auch schon vorgekommen. Aber ohne diesen Nachweis sitzt man in der 
Falle, denn am Problem wird sich dann nichts ändern und am Compiler auch 
nicht.

Allerdings stellen sich die "Compilerfehler" später nicht eben selten 
als ganz andere Fehler dar, die auch häufig ausserhalb des unmittelbar 
betrachteten Codes liegen. Da kann ein Pointer oder ein Index im Wald 
stehen, da ist irgendein Stack zu klein dimensioniert, ...

Hier gibts irgendwo im Artikelwald einen Text, der einen sinnvollen 
Umgang mit dieser Diagnose beschreibt.

Autor: Matko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, stimmt oft ist es so. Sollte ich den Fehler (meinen oder den vom 
Compiler) finden, werde ich das hier festhalten.

Danke für Eure Antworten!

Autor: Marcus Overhagen (marcus6100)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Matko,

welcher PIC24F ist es denn, vielleicht der kleine mit 512 byte RAM?

Eventuell hast du hier einen Stack Überlauf, wenn das lokale
Array auf dem Stack nach Aufruf einer Funktion (ganz allgemein)
nicht mehr den selben Inhalt hat wie vorher.

Es könnte auch helfen das ganze Programm hier zu zeigen.

Du kannst auch zum Test mal das array static machen, wenn der
Fehler danach weg ist liegt es definitiv daran das der stack
überschrieben wird.

Vor Programmierfehlern kann man sich etwas schützen wenn man
Daten die nicht verändert werden sollen als const deklariert.

Compilerfehler sind extrem selten (ich hab allerdings auch mal
einen gefunden, das war was mit 64bit additionen in deiner Schleife)

Autor: Matko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nochmals danke.

SRAM hat 16K.
Ich werde die Tipps mal probieren und Euch morgen informieren was 
rausgekommen ist.

LG, Matko

Autor: Matko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, geholfen hats nix. Überschrieben wird nix, nur falsch abgelegt... 
Ich hab mir mal das komplette Instruction Set runtergeladen... wollte eh 
schon immer mehr über ASM lernen.

BTW: Das war nicht das erste Mal, dass der Compiler was versaut... zB 
hat mal so was ähnliches dazugeführt, dass sich der Controller immer 
reseted hat:
    if((n = getBLA()) == EVENT_MOMO){...

und einmal war auch was, mit einem Array was ihm nicht passt hat, (sowas 
wie if(gTxData[n++] ... kA) da hat er immer eine Trap ausglöst. Kaum 
wars auf 2 Zeilen aufteilt hats gepasst. Deswegen bin ich da so 
misstrauisch. Na gut, danke für die Tipps.

LG, Matko

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.