Hallo, vielleicht kann mir einer der Experten helfen: Ich habe folgendes Problem: Eine Stateengine ist als zyklisch zu rufende Funktion mit einer globalen Variablen und einem davon abgeleitetem switch() kodiert. Rufe ich diese Funktion auf, springt mir der Simulator absolut wirr da drin rum - und zwar nicht das übliche Verschieben des Optimizers, sondern wie ich im Disassembler und an den ausgeführten Codepartikeln sehen, macht er auch wirklich Schrott. Ich habe dann folgende Versuche unternommen: - clean und rebuild all. - Datei aus dem prject gelöscht und wieder neu aufgenommen. - Optimize bis auf -o1 zurückgenommen - keine Änderung. - Quelltext auf Sonderzeichen abgesucht - keine Auffälligkeiten. - Umstellen der case-Blöcke: keine Änderung. - Einkopieren der Funktion in die aufrufende Routine: Und siehe da, es läuft. Momentan bin ich etwas ratlos, woran das liegen könnte; und es ist ja nicht das erste AVR-Programm, welches ich schreibe. Servus Wolfgang, www.opendcc.de
Hört sich nach einem Stack-Problem an. Speicher läuft über.
Wie stark ist das SRAM deines µC schon durch DATA und BSS ausgenutzt, lass dir mal eine Statistik nach dem Kompilieren ausgeben? Hast du viele dynamisch zur Laufzeit angelegte Variablen, die ja auf dem Stack zusätzlich angelegt werden? Eventuell sind es zu viele, so dass der Stack zerschossen wird.
Hallo, danke für den Hinweis, leider kein Treffer: Siumlator stopped: Stackpointer bei 0x10ED, Data endet bei 0x0D98. Also noch ewig viel Platz. Servus Wolfgang
Ich habe mal C Code und das was ich auf Maschinenebene sehe hier angehängt: Das Statement xbee_rx.header.len = data << 8 kommt im Disassembler sofort nach dem Funktionsaufruf, dürfte aber nur bei case 1 kommen. Gruß Wolfgang
1 | t_cr_task run_xbee_client(void) |
2 | { |
3 | #warning xbee_task still incomplete! |
4 | |
5 | rx_fifo_ready(); |
6 | |
7 | unsigned char data; |
8 | while (rx_fifo_ready()) |
9 | { |
10 | data = rx_fifo_read(); // reads one byte |
11 | |
12 | switch(bytes_rcvd++) |
13 | { |
14 | case 0: |
15 | if (data == XBEE_PKT_START) |
16 | { |
17 | xbee_rx.header.delimiter = data; |
18 | } |
19 | // else ignore data |
20 | break; |
21 | |
22 | case 1: |
23 | xbee_rx.header.len = data << 8; |
24 | break; |
25 | |
26 | case 2: |
27 | xbee_rx.header.len |= data; |
28 | // xbee_rx.header.len = ntohs(xbee_rx.header.len); // resolve endiness |
29 | bytes_left = xbee_rx.header.len; |
30 | |
31 | if ( bytes_left > XBEE_MAX_DATA_LEN ) |
32 | { |
33 | bytes_left = 0; |
34 | bytes_rcvd = 0; |
35 | // xbee_rx_err(xbee); |
36 | #warning handle error missing |
37 | } |
38 | |
39 | break; |
40 | case 3: |
41 | xbee_rx.header.cmd_id = data; |
42 | x_index = 0; |
43 | bytes_left--; |
44 | break; |
45 | |
46 | default: |
47 | if (bytes_left == 1) |
48 | { |
49 | if ( xbee_checksum(&xbee_rx) != data) |
50 | { |
51 | bytes_rcvd = 0; |
52 | // xbee_rx_checksum_err(xbee); |
53 | #warning handle error missing |
54 | } |
55 | else |
56 | { |
57 | PORTB = 0x35; |
58 | // now process this packet |
59 | xbee_rx.data[x_index] = 0; // set end delimiter |
60 | xbee_rx.data[x_index++] = 0x03; // set end delimiter |
61 | xbee_rx.data[x_index++] = 0x04; // set end delimiter |
62 | xbee_rx.data[x_index++] = 0x05; // set end delimiter |
63 | xbee_rx.data[x_index++] = 0x06; // set end delimiter |
64 | xbee_rx.data[x_index++] = 0x0F; // set end delimiter |
65 | xbee_rx.data[x_index++] = 0; // set end delimiter |
66 | parse_xbee_packet(); |
67 | } |
68 | bytes_rcvd = 0; |
69 | } |
70 | else |
71 | { |
72 | xbee_rx.data[x_index++] = data; |
73 | bytes_left--; |
74 | } |
75 | break; |
76 | } |
77 | } |
1 | @00007474: run_xbee_client |
2 | 367: { |
3 | +00007474: 92BF PUSH R11 Push register on stack |
4 | +00007475: 92CF PUSH R12 Push register on stack |
5 | +00007476: 92DF PUSH R13 Push register on stack |
6 | +00007477: 92EF PUSH R14 Push register on stack |
7 | +00007478: 92FF PUSH R15 Push register on stack |
8 | +00007479: 930F PUSH R16 Push register on stack |
9 | +0000747A: 931F PUSH R17 Push register on stack |
10 | +0000747B: 93CF PUSH R28 Push register on stack |
11 | +0000747C: 93DF PUSH R29 Push register on stack |
12 | 370: rx_fifo_ready(); |
13 | +0000747D: 940E2CBB CALL 0x00002CBB Call subroutine |
14 | 394: xbee_rx.header.len = data << 8; |
15 | +0000747F: E1CD LDI R28,0x1D Load immediate |
16 | +00007480: E0DD LDI R29,0x0D Load immediate |
17 | 428: PORTB = 0x35; |
18 | +00007481: E355 LDI R21,0x35 Load immediate |
19 | +00007482: 2EB5 MOV R11,R21 Copy register |
20 | 431: xbee_rx.data[x_index++] = 0x03; // set end delimiter |
21 | +00007483: E043 LDI R20,0x03 Load immediate |
22 | +00007484: 2EC4 MOV R12,R20 Copy register |
23 | 432: xbee_rx.data[x_index++] = 0x04; // set end delimiter |
24 | +00007485: E034 LDI R19,0x04 Load immediate |
25 | +00007486: 2ED3 MOV R13,R19 Copy register |
26 | 433: xbee_rx.data[x_index++] = 0x05; // set end delimiter |
27 | +00007487: E025 LDI R18,0x05 Load immediate |
28 | +00007488: 2EE2 MOV R14,R18 Copy register |
29 | 434: xbee_rx.data[x_index++] = 0x06; // set end delimiter |
30 | +00007489: E096 LDI R25,0x06 Load immediate |
31 | +0000748A: 2EF9 MOV R15,R25 Copy register |
32 | 435: xbee_rx.data[x_index++] = 0x0F; // set end delimiter |
Wolfgang schrieb: > Ich habe mal C Code und das was ich auf Maschinenebene sehe hier > angehängt: > > Das Statement xbee_rx.header.len = data << 8 kommt im Disassembler > sofort nach dem Funktionsaufruf, Darauf darfst du nichts geben. Im Listing taucht die C-Zeile in dieser Form auf. Aber im Assembler Code sieht man, dass hier lediglich 2 Register mit Zahlen gefüllt werden. Wahrscheinlich ist das die Speicheradresse von xbee_rx.header.len die die Datenflussanalyse ausgewählt hat um in einem Register ständig vorgehalten zu werden. Überhaupt: Auch die nächsten Assemblersequenzen machen nicht das, was im C-Source Code steht. Der Compiler hat anscheinend die Konstanten, die in diesen Ausdrücken vorkommen, in Registern, die gerade frei sind, zwischengeparkt. Wobei: Seltsam ist das schon. Schliesslich werden da ein Haufen Register mit Konstanten blockiert von denen noch nicht einmal feststeht, ob sie je zum Zuge kommen.
Ui, ich glaube, da habe ich mich doch irreführen lassen. Der Compiler macht zwar die Registerbelegungen, verwirft das dann aber in der Minderzahl der Fälle. Baue ich da zusätzlich Portausgabe rein (wo er nicht vorbei darf), dann sieht es schon wieder besser aus. Danke, Wolfgang
Könnte es sein, das der Compiler Grund zu der Annahme hat, das immer nur der der case 1: und der else-Teil im default ausgeführt wird? Das er deswegen aus dem data << 8 das laden einer Konstante macht, weil er zu wissen meint, das data immer einen bestimmten Wert haben wird. Also 0x1D. Andererseits woher nimmt er dann die 0x0D vom Lowbyte? Ein bischen komisch ist das schon. Es fällt auf, das (bis auf data) sämtliche Variablen die den Ablauf ändern könnten ausserhalb der Funktion deklariert sein müssen. Auch die Funktion xbee_checksum müsste dann immer ein Resultat != data liefern. Ich tippe zwar eher nicht darauf, aber ehe ich von einem Compilerfehler ausgehe, gehe ich davon aus, das ich der Dummbatz bin. Mich würde auch mal interessieren wie der Asm-Code weitergeht. Ob tatsächlich zurück zum while springt oder nicht.
Hier die ganze routine:
1 | @00007474: run_xbee_client |
2 | 367: { |
3 | +00007474: 92BF PUSH R11 Push register on stack |
4 | +00007475: 92CF PUSH R12 Push register on stack |
5 | +00007476: 92DF PUSH R13 Push register on stack |
6 | +00007477: 92EF PUSH R14 Push register on stack |
7 | +00007478: 92FF PUSH R15 Push register on stack |
8 | +00007479: 930F PUSH R16 Push register on stack |
9 | +0000747A: 931F PUSH R17 Push register on stack |
10 | +0000747B: 93CF PUSH R28 Push register on stack |
11 | +0000747C: 93DF PUSH R29 Push register on stack |
12 | 370: rx_fifo_ready(); |
13 | +0000747D: 940E2CBB CALL 0x00002CBB Call subroutine |
14 | 394: xbee_rx.header.len = data << 8; |
15 | +0000747F: E1CD LDI R28,0x1D Load immediate |
16 | +00007480: E0DD LDI R29,0x0D Load immediate |
17 | 428: PORTB = 0x35; |
18 | +00007481: E355 LDI R21,0x35 Load immediate |
19 | +00007482: 2EB5 MOV R11,R21 Copy register |
20 | 431: xbee_rx.data[x_index++] = 0x03; // set end delimiter |
21 | +00007483: E043 LDI R20,0x03 Load immediate |
22 | +00007484: 2EC4 MOV R12,R20 Copy register |
23 | 432: xbee_rx.data[x_index++] = 0x04; // set end delimiter |
24 | +00007485: E034 LDI R19,0x04 Load immediate |
25 | +00007486: 2ED3 MOV R13,R19 Copy register |
26 | 433: xbee_rx.data[x_index++] = 0x05; // set end delimiter |
27 | +00007487: E025 LDI R18,0x05 Load immediate |
28 | +00007488: 2EE2 MOV R14,R18 Copy register |
29 | 434: xbee_rx.data[x_index++] = 0x06; // set end delimiter |
30 | +00007489: E096 LDI R25,0x06 Load immediate |
31 | +0000748A: 2EF9 MOV R15,R25 Copy register |
32 | 435: xbee_rx.data[x_index++] = 0x0F; // set end delimiter |
33 | +0000748B: E00F LDI R16,0x0F Load immediate |
34 | +0000748C: C07A RJMP PC+0x007B Relative jump |
35 | 375: data = rx_fifo_read(); // reads one byte |
36 | +0000748D: 940E2CC4 CALL 0x00002CC4 Call subroutine |
37 | +0000748F: 2F18 MOV R17,R24 Copy register |
38 | 383: switch(bytes_rcvd++) |
39 | +00007490: 91800C86 LDS R24,0x0C86 Load direct from data space |
40 | +00007492: 5F8F SUBI R24,0xFF Subtract immediate |
41 | +00007493: 93800C86 STS 0x0C86,R24 Store direct to data space |
42 | +00007495: 5081 SUBI R24,0x01 Subtract immediate |
43 | +00007496: 3081 CPI R24,0x01 Compare with immediate |
44 | +00007497: F079 BREQ PC+0x10 Branch if equal |
45 | +00007498: 3081 CPI R24,0x01 Compare with immediate |
46 | +00007499: F038 BRCS PC+0x08 Branch if carry set |
47 | +0000749A: 3082 CPI R24,0x02 Compare with immediate |
48 | +0000749B: F079 BREQ PC+0x10 Branch if equal |
49 | +0000749C: 91900D1B LDS R25,0x0D1B Load direct from data space |
50 | +0000749E: 3083 CPI R24,0x03 Compare with immediate |
51 | +0000749F: F521 BRNE PC+0x25 Branch if not equal |
52 | +000074A0: C01E RJMP PC+0x001F Relative jump |
53 | 386: if (data == XBEE_PKT_START) |
54 | +000074A1: 371E CPI R17,0x7E Compare with immediate |
55 | +000074A2: F009 BREQ PC+0x02 Branch if equal |
56 | +000074A3: C063 RJMP PC+0x0064 Relative jump |
57 | 388: xbee_rx.header.delimiter = data; |
58 | +000074A4: 93100D1C STS 0x0D1C,R17 Store direct to data space |
59 | +000074A6: C060 RJMP PC+0x0061 Relative jump |
60 | +000074A7: 92100D1D STS 0x0D1D,R1 Store direct to data space |
61 | +000074A9: 8319 STD Y+1,R17 Store indirect with displacement |
62 | +000074AA: C05C RJMP PC+0x005D Relative jump |
63 | 398: xbee_rx.header.len |= data; |
64 | +000074AB: 2F81 MOV R24,R17 Copy register |
65 | +000074AC: E090 LDI R25,0x00 Load immediate |
66 | +000074AD: 91200D1D LDS R18,0x0D1D Load direct from data space |
67 | +000074AF: 91300D1E LDS R19,0x0D1E Load direct from data space |
68 | +000074B1: 2B82 OR R24,R18 Logical OR |
69 | +000074B2: 2B93 OR R25,R19 Logical OR |
70 | +000074B3: 93900D1E STS 0x0D1E,R25 Store direct to data space |
71 | +000074B5: 93800D1D STS 0x0D1D,R24 Store direct to data space |
72 | 400: bytes_left = xbee_rx.header.len; |
73 | +000074B7: 93800D1B STS 0x0D1B,R24 Store direct to data space |
74 | 402: if ( bytes_left > XBEE_MAX_DATA_LEN ) |
75 | +000074B9: 3881 CPI R24,0x81 Compare with immediate |
76 | +000074BA: F408 BRCC PC+0x02 Branch if carry cleared |
77 | +000074BB: C04B RJMP PC+0x004C Relative jump |
78 | 404: bytes_left = 0; |
79 | +000074BC: 92100000 STS 0x0000,R1 Store direct to data space |
80 | +000074BE: C038 RJMP PC+0x0039 Relative jump |
81 | 412: xbee_rx.header.cmd_id = data; |
82 | +000074BF: 93100D1F STS 0x0D1F,R17 Store direct to data space |
83 | 413: x_index = 0; |
84 | +000074C1: 92100C96 STS 0x0C96,R1 Store direct to data space |
85 | +000074C3: C040 RJMP PC+0x0041 Relative jump |
86 | 418: if (bytes_left == 1) |
87 | +000074C4: 3091 CPI R25,0x01 Compare with immediate |
88 | +000074C5: F5A1 BRNE PC+0x35 Branch if not equal |
89 | 420: if ( xbee_checksum(&xbee_rx) != data) |
90 | +000074C6: E18C LDI R24,0x1C Load immediate |
91 | +000074C7: E09D LDI R25,0x0D Load immediate |
92 | +000074C8: 940E740B CALL 0x0000740B Call subroutine |
93 | +000074CA: 1781 CP R24,R17 Compare |
94 | +000074CB: F559 BRNE PC+0x2C Branch if not equal |
95 | +000074CC: B8B5 OUT 0x05,R11 Out to I/O location |
96 | 430: xbee_rx.data[x_index] = 0; // set end delimiter |
97 | +000074CD: 91800C96 LDS R24,0x0C96 Load direct from data space |
98 | +000074CF: 2FE8 MOV R30,R24 Copy register |
99 | +000074D0: E0F0 LDI R31,0x00 Load immediate |
100 | +000074D1: 5EE4 SUBI R30,0xE4 Subtract immediate |
101 | +000074D2: 4FF2 SBCI R31,0xF2 Subtract immediate with carry |
102 | +000074D3: 82C4 STD Z+4,R12 Store indirect with displacement |
103 | +000074D4: 5F8F SUBI R24,0xFF Subtract immediate |
104 | +000074D5: 2FE8 MOV R30,R24 Copy register |
105 | +000074D6: E0F0 LDI R31,0x00 Load immediate |
106 | +000074D7: 5EE4 SUBI R30,0xE4 Subtract immediate |
107 | +000074D8: 4FF2 SBCI R31,0xF2 Subtract immediate with carry |
108 | +000074D9: 82D4 STD Z+4,R13 Store indirect with displacement |
109 | +000074DA: 5F8F SUBI R24,0xFF Subtract immediate |
110 | +000074DB: 2FE8 MOV R30,R24 Copy register |
111 | +000074DC: E0F0 LDI R31,0x00 Load immediate |
112 | +000074DD: 5EE4 SUBI R30,0xE4 Subtract immediate |
113 | +000074DE: 4FF2 SBCI R31,0xF2 Subtract immediate with carry |
114 | +000074DF: 82E4 STD Z+4,R14 Store indirect with displacement |
115 | +000074E0: 5F8F SUBI R24,0xFF Subtract immediate |
116 | +000074E1: 2FE8 MOV R30,R24 Copy register |
117 | +000074E2: E0F0 LDI R31,0x00 Load immediate |
118 | +000074E3: 5EE4 SUBI R30,0xE4 Subtract immediate |
119 | +000074E4: 4FF2 SBCI R31,0xF2 Subtract immediate with carry |
120 | +000074E5: 82F4 STD Z+4,R15 Store indirect with displacement |
121 | +000074E6: 5F8F SUBI R24,0xFF Subtract immediate |
122 | +000074E7: 2FE8 MOV R30,R24 Copy register |
123 | +000074E8: E0F0 LDI R31,0x00 Load immediate |
124 | +000074E9: 5EE4 SUBI R30,0xE4 Subtract immediate |
125 | +000074EA: 4FF2 SBCI R31,0xF2 Subtract immediate with carry |
126 | +000074EB: 8304 STD Z+4,R16 Store indirect with displacement |
127 | +000074EC: 5F8F SUBI R24,0xFF Subtract immediate |
128 | ---- xbee_if.c ------------------------------------------------------------------------------------ |
129 | 436: xbee_rx.data[x_index++] = 0; // set end delimiter |
130 | +000074ED: 2FE8 MOV R30,R24 Copy register |
131 | +000074EE: E0F0 LDI R31,0x00 Load immediate |
132 | +000074EF: 5EE4 SUBI R30,0xE4 Subtract immediate |
133 | +000074F0: 4FF2 SBCI R31,0xF2 Subtract immediate with carry |
134 | +000074F1: 8214 STD Z+4,R1 Store indirect with displacement |
135 | +000074F2: 5F8F SUBI R24,0xFF Subtract immediate |
136 | +000074F3: 93800C96 STS 0x0C96,R24 Store direct to data space |
137 | 437: parse_xbee_packet(); |
138 | +000074F5: 940E7468 CALL 0x00007468 Call subroutine |
139 | 439: bytes_rcvd = 0; |
140 | +000074F7: 92100C86 STS 0x0C86,R1 Store direct to data space |
141 | +000074F9: C00D RJMP PC+0x000E Relative jump |
142 | 443: xbee_rx.data[x_index++] = data; |
143 | +000074FA: 91800C96 LDS R24,0x0C96 Load direct from data space |
144 | +000074FC: 2FE8 MOV R30,R24 Copy register |
145 | +000074FD: E0F0 LDI R31,0x00 Load immediate |
146 | +000074FE: 5EE4 SUBI R30,0xE4 Subtract immediate |
147 | +000074FF: 4FF2 SBCI R31,0xF2 Subtract immediate with carry |
148 | +00007500: 8314 STD Z+4,R17 Store indirect with displacement |
149 | +00007501: 5F8F SUBI R24,0xFF Subtract immediate |
150 | +00007502: 93800C96 STS 0x0C96,R24 Store direct to data space |
151 | 444: bytes_left--; |
152 | +00007504: 5091 SUBI R25,0x01 Subtract immediate |
153 | +00007505: 93900D1B STS 0x0D1B,R25 Store direct to data space |
154 | 373: while (rx_fifo_ready()) |
155 | +00007507: 940E2CBB CALL 0x00002CBB Call subroutine |
156 | +00007509: 2388 TST R24 Test for Zero or Minus |
157 | +0000750A: F009 BREQ PC+0x02 Branch if equal |
158 | +0000750B: CF81 RJMP PC-0x007E Relative jump |
159 | 473: } |
160 | +0000750C: EF8F SER R24 Set Register |
161 | +0000750D: EF9F SER R25 Set Register |
162 | +0000750E: 91DF POP R29 Pop register from stack |
163 | +0000750F: 91CF POP R28 Pop register from stack |
164 | +00007510: 911F POP R17 Pop register from stack |
165 | +00007511: 910F POP R16 Pop register from stack |
166 | +00007512: 90FF POP R15 Pop register from stack |
167 | +00007513: 90EF POP R14 Pop register from stack |
168 | +00007514: 90DF POP R13 Pop register from stack |
169 | +00007515: 90CF POP R12 Pop register from stack |
170 | +00007516: 90BF POP R11 Pop register from stack |
171 | +00007517: 9508 RET Subroutine return |
Hmmm. Also er hat die C-Codezeilen umgestellt. Soweit aber ok.
Was genau ist das Problem?
>wie ich im Disassembler und an den ausgeführten Codepartikeln sehen, macht >er
auch wirklich Schrott.
Funktioniert das Programm garnicht oder irritiert Dich das herumspringen
nur?
Hallo, das Programm funktioniert. Ich hatte mich wirklich verwirren lassen - im Single-Step von AVR Studio werden sogar Portausgabe innerhalb des switch-statements angezeigt (d.h. die RUN-Markierung steht auf der Anweisung PORTB = 0x35), jedoch werden diese nicht ausgeführt. Gruß Wolfgang
Wolfgang K. schrieb: > Single-Step von AVR Studio werden sogar Portausgabe innerhalb des > switch-statements angezeigt (d.h. die RUN-Markierung steht auf der > Anweisung PORTB = 0x35), jedoch werden diese nicht ausgeführt. Was du woran erkennst?
Wenn ich drüber steppe, ändert der Port seinen Zustand nicht. WOlfgang
Dann wird der Port wohl nicht als Ausgang definiert sein. Jedenfalls hat das erkennbar wenig mit dem Compiler zu tun, allenfalls mit dem Simulator.
Wolfgang K. schrieb:
> Wenn ich drüber steppe, ändert der Port seinen Zustand nicht.
Das sollte sich nach einem Blick ins Assemblerlisting auch geklärt
haben.
Es ist lediglich die Anzeige falsch.
Der Compiler hat die Anweisung
PORTB = 0x35;
in 2 Teile gesplittet. Die 0x35 hat er sich in einem Register
zurechtgelegt und die eigentliche Portausgabe blieb an der korrekten
Stelle.
Unglücklicherweise ist die Source-Code Zeile
PORTB = 0x35;
beim Splitten an die Stelle gerutscht, an der sich der Compiler die 0x35
im Register vorbelegt hat.
Damit siehst du im Debugger zwar die Zeile, aber unter der Tuchent
passiert eigentlich ganz was anderes.
-> Wenn du optimierten Code debuggst, darfst du keinen Jota mehr drauf
geben, was im C-Source Code dort steht. Das kann alles zerpflückt und
umsortiert worden sein. Statements können in sich auseinandergerissen
und in anderer Reihenfolge (auch untereinander gemischt) neu
zusammengesetzt worden sein.
Das habe ich inzwischen auch gemerkt :-) wobei der Optimizer gegenüber früher schon mehr rumrührt. Manchmal ist es schon fast unheimlich, was der so treibt - Hut ab vor den Leuten, die das machen. Servus Wolfgang
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.