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
voidcontWR_SPI2(unsignedchar*TxData)
2
{
3
intres,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
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.
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.
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:
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...
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)
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
voidFunktion(void)
2
{
3
unsignedcharps021conf[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
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.
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.
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.
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)
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