Forum: Mikrocontroller und Digitale Elektronik Compilerfehler?


von Matko (Gast)


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:
1
void contWR_SPI2(unsigned char* TxData)
2
{
3
  int res, i=0;
4
5
  pulseCS();           
6
  SPI2STATbits.SPIROV = 0;  
7
  IFS2bits.SPI2IF = 0;
8
  res = SPI2BUF;//clear buffer and reset SPIRBF
9
  while(i < 4)
10
  {
11
    if(!SPI2STATbits.SPITBF) // TxBuf = empty then fill TxBuf again!
12
      SPI2BUF = TxData[i++];
13
  }
14
  return;         
15
}

Komischer Weise macht es einen Unterschied, ob ich  es so
1
  ps021conf[0] = 0x84;  //Addr4 + CMD
2
  ps021conf[1] = 0x80;  
3
  ps021conf[2] = 0x00;  
4
  ps021conf[3] = 0x00;
5
  contWR_SPI2(ps021conf);
6
   WAIT();
7
8
  ps021conf[0] = 0x85;  //Addr5 + CMD
9
  ps021conf[1] = 0x80;  
10
  ps021conf[2] = 0x00;  
11
  ps021conf[3] = 0x00;
12
  contWR_SPI2(ps021conf);

oder -da die Daten [1...3] bei beiden Adressen gleich bleiben- so 
schreibe:
1
  ps021conf[0] = 0x84;  //Addr4 + CMD
2
  ps021conf[1] = 0x80;  
3
  ps021conf[2] = 0x00;  
4
  ps021conf[3] = 0x00;
5
  contWR_SPI2(ps021conf);
6
   WAIT();
7
8
  ps021conf[0] = 0x85;  //Addr5 + CMD
9
  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):
1
1001:                ps021conf[0] = 0x83;  //Addr3 + CMD
2
 03F30  2FF837     mov.w #0xff83,0x000e
3
 03F32  2FFF86     mov.w #0xfff8,0x000c
4
 03F34  478306     add.w 0x001e,0x000c,0x000c
5
 03F36  784B07     mov.b 0x000e,[0x000c]
6
1002:                ps021conf[1] = 0x00;  
7
 03F38  200006     mov.w #0x0,0x000c
8
 03F3A  2FFF97     mov.w #0xfff9,0x000e
9
 03F3C  478387     add.w 0x001e,0x000e,0x000e
10
 03F3E  784B86     mov.b 0x000c,[0x000e]
11
1003:                ps021conf[2] = 0xC0;  
12
 03F40  2FFC06     mov.w #0xffc0,0x000c
13
 03F42  2FFFA7     mov.w #0xfffa,0x000e
14
 03F44  478387     add.w 0x001e,0x000e,0x000e
15
 03F46  784B86     mov.b 0x000c,[0x000e]
16
1004:                ps021conf[3] = 0x01;
17
 03F48  200016     mov.w #0x1,0x000c
18
 03F4A  2FFFB7     mov.w #0xfffb,0x000e
19
 03F4C  478387     add.w 0x001e,0x000e,0x000e
20
 03F4E  784B86     mov.b 0x000c,[0x000e]
21
1005:                contWR_SPI2(ps021conf);
22
 03F50  2FFF80     mov.w #0xfff8,0x0000
23
 03F52  478000     add.w 0x001e,0x0000,0x0000
24
 03F54  07FB6B     rcall 0x00362c
25
1006:                 WAIT();
26
 03F56  000000     nop
27
 03F58  000000     nop
28
 03F5A  000000     nop
29
 03F5C  000000     nop
30
 03F5E  000000     nop
31
 03F60  000000     nop
32
 03F62  000000     nop
33
 03F64  000000     nop
34
 03F66  000000     nop
35
 03F68  000000     nop
36
 03F6A  000000     nop
37
 03F6C  000000     nop
38
 03F6E  000000     nop
39
 03F70  000000     nop
40
 03F72  000000     nop
41
1007:                
42
1008:                ps021conf[0] = 0x84;  //Addr4 + CMD
43
 03F74  2FF847     mov.w #0xff84,0x000e
44
 03F76  2FFF86     mov.w #0xfff8,0x000c
45
 03F78  478306     add.w 0x001e,0x000c,0x000c
46
 03F7A  784B07     mov.b 0x000e,[0x000c]
47
1009:                ps021conf[1] = 0x80;  
48
 03F7C  2FF806     mov.w #0xff80,0x000c
49
 03F7E  2FFF97     mov.w #0xfff9,0x000e
50
 03F80  478387     add.w 0x001e,0x000e,0x000e
51
 03F82  784B86     mov.b 0x000c,[0x000e]
52
1010:                ps021conf[2] = 0x00;  
53
 03F84  200006     mov.w #0x0,0x000c
54
 03F86  2FFFA7     mov.w #0xfffa,0x000e
55
 03F88  478387     add.w 0x001e,0x000e,0x000e
56
 03F8A  784B86     mov.b 0x000c,[0x000e]
57
1011:                ps021conf[3] = 0x00;
58
 03F8C  200006     mov.w #0x0,0x000c
59
 03F8E  2FFFB7     mov.w #0xfffb,0x000e
60
 03F90  478387     add.w 0x001e,0x000e,0x000e
61
 03F92  784B86     mov.b 0x000c,[0x000e]
62
1012:                contWR_SPI2(ps021conf);
63
 03F94  2FFF80     mov.w #0xfff8,0x0000
64
 03F96  478000     add.w 0x001e,0x0000,0x0000
65
 03F98  07FB49     rcall 0x00362c
66
 03F9A  000000     nop
67
 03F9C  000000     nop
68
 03F9E  000000     nop
69
 03FA0  000000     nop
70
 03FA2  000000     nop
71
 03FA4  000000     nop
72
 03FA6  000000     nop
73
 03FA8  000000     nop
74
 03FAA  000000     nop
75
 03FAC  000000     nop
76
 03FAE  000000     nop
77
 03FB0  000000     nop
78
 03FB2  000000     nop
79
 03FB4  000000     nop
80
 03FB6  000000     nop
81
1014:              
82
1015:                ps021conf[0] = 0x85;  //Addr5 + CMD
83
 03FB8  2FF857     mov.w #0xff85,0x000e
84
 03FBA  2FFF86     mov.w #0xfff8,0x000c
85
 03FBC  478306     add.w 0x001e,0x000c,0x000c
86
 03FBE  784B07     mov.b 0x000e,[0x000c]
87
1016:              /*  ps021conf[1] = 0x80;  
88
1017:                ps021conf[2] = 0x00;  
89
1018:                ps021conf[3] = 0x00;*/
90
1019:                contWR_SPI2(ps021conf);
91
 03FC0  2FFF80     mov.w #0xfff8,0x0000
92
 03FC2  478000     add.w 0x001e,0x0000,0x0000
93
 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

von spess53 (Gast)


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

von (prx) A. K. (prx)


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.

von Matko (Gast)


Lesenswert?

Danke für die schnellen Antworten!

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

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

von (prx) A. K. (prx)


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.

von Matko (Gast)


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:
1
1008:               ps021conf[0] = 0x84;  //Addr4 + CMD
2
 03F28  2FF847     mov.w #0xff84,0x000e
3
 03F2A  2FFF86     mov.w #0xfff8,0x000c
4
 03F2C  478306     add.w 0x001e,0x000c,0x000c
5
 03F2E  784B07     mov.b 0x000e,[0x000c++]
6
1009:               ps021conf[1] = 0x80;  
7
 03F30  2FF806     mov.w #0xff80,0x000e
8
 03F36  784B86     mov.b 0x000e,[0x000c]

Compileroptimierung 6...

Dankbar für jeden Tip!

von Matko (Gast)


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.
1
  ps021conf[0] = 0x84;  //Addr4 + CMD
2
  ps021conf[1] = 0x80;  
3
  ps021conf[2] = 0x00;  
4
  ps021conf[3] = 0x01;
5
  contWR_SPI2(ps021conf);
6
   WAIT();
7
8
  ps021conf[0] = 0x85;  //Addr5 + CMD
9
  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...

von Marcus O. (marcus6100)


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)

von Matko (Gast)


Lesenswert?

1
void Funktion(void)
2
{
3
  unsigned char ps021conf[5];
4
5
   ps021conf[0] = 0x80;   // Addresse 0
6
   ps021conf[1] = 0x01;
7
   ps021conf[2] = 0x02;
8
   ps021conf[3] = 0x03;
9
   contWR_SPI2(ps021conf);
10
11
   /* 
12
   ...
13
   und jetzt werden noch die restlichen Addressen des ICs beschrieben
14
   ...
15
  */
16
}

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:
1
void Funktion(void)
2
{
3
  unsigned char ps021conf[5];
4
5
   ps021conf[0] = 0x80;   // Addresse 0
6
   ps021conf[1] = 0x01;
7
   ps021conf[2] = 0x02;
8
   ps021conf[3] = 0x03;
9
   contWR_SPI2(ps021conf);
10
11
   ps021conf[0] = 0x81;   // Addresse 1
12
   contWR_SPI2(ps021conf);
13
14
   /* 
15
   ...
16
   und jetzt werden noch die restlichen Addressen des ICs beschrieben
17
   ...
18
  */
19
}

Reihenfolge in Register 1: 02-03-01

von (prx) A. K. (prx)


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.

von Matko (Gast)


Lesenswert?

Wo ist denn mein Fehler in:
1
void Funktion(void)
2
{
3
  unsigned char ps021conf[5];
4
5
   ps021conf[0] = 0x80;   // Addresse 0
6
   ps021conf[1] = 0x01;
7
   ps021conf[2] = 0x02;
8
   ps021conf[3] = 0x03;
9
   contWR_SPI2(ps021conf);
10
11
   ps021conf[0] = 0x81;   // Addresse 1
12
   contWR_SPI2(ps021conf);
13
14
   /* 
15
   ...
16
   und jetzt werden noch die restlichen Addressen des ICs beschrieben
17
   ...
18
  */
19
}

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.

von (prx) A. K. (prx)


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.

von Matko (Gast)


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!

von Marcus O. (marcus6100)


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)

von Matko (Gast)


Lesenswert?

Nochmals danke.

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

LG, Matko

von Matko (Gast)


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:
1
    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

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.