von
Thomas (Gast)
06.03.2009 15:13
Hallo,
ich habe derzeit leider ein Problem mit dem ARM und der Übersetzung bei
eingeschalteter Optimierung. Und zwar mit folgendem Codefragment:
1 #define SPI_MASTER_SR S0PSR
2 extern volatile const unsigned char S0PSR ;
3
4 void spi_send_packet ( unsigned int * packet , unsigned int count ) {
5 unsigned int i ;
6
7 for ( i = 0 ; i < count ; i ++ , packet ++ ) {
8 SPI_MASTER_DR = * packet ;
9 while ( ! ( SPI_MASTER_SR & ( 1 << 7 ))) {
10 //asm volatile("nop\n");
11 }
12 }
13 }
wenn jetzt über SPI das Byte weggesendet wird, dann wird in
SPI_MASTER_SR das high Byte gesetzt und durch das lesen wieder
rückgesetzt. Mit -O0 funktioniert das ganze auch.
Mit jeder Optimierung bleibt die Routine allerdings hängen. Zur
Entwicklung verwende ich yagarto und damit Binutils-2.18, Newlib-1.16.0
und GCC-4.3.2
S0PSR liegt auf 0xe0020004
Mit -O0 kommt das raus aus dem *.lss File:
1 00000828 <spi_send_packet>:
2 828: b580 push {r7, lr}
3 82a: b083 sub sp, #12
4 82c: af00 add r7, sp, #0
5 82e: 6078 str r0, [r7, #4]
6 830: 6039 str r1, [r7, #0]
7 832: 2300 movs r3, #0
8 834: 60bb str r3, [r7, #8]
9 836: e011 b.n 85c <spi_send_packet+0x34>
10 838: 687b ldr r3, [r7, #4]
11 83a: 781b ldrb r3, [r3, #0]
12 83c: 4a0c ldr r2, [pc, #48] (870 <spi_send_packet+0x48>)
13 83e: 7013 strb r3, [r2, #0]
14 840: 4b0c ldr r3, [pc, #48] (874 <spi_send_packet+0x4c>)
15 842: 781b ldrb r3, [r3, #0]
16 844: 061b lsls r3, r3, #24
17 846: 0e1b lsrs r3, r3, #24
18 848: 061b lsls r3, r3, #24
19 84a: 161b asrs r3, r3, #24
20 84c: 2b00 cmp r3, #0
21 84e: daf7 bge.n 840 <spi_send_packet+0x18>
22 850: 68bb ldr r3, [r7, #8]
23 852: 3301 adds r3, #1
24 854: 60bb str r3, [r7, #8]
25 856: 687b ldr r3, [r7, #4]
26 858: 3301 adds r3, #1
27 85a: 607b str r3, [r7, #4]
28 85c: 68ba ldr r2, [r7, #8]
29 85e: 683b ldr r3, [r7, #0]
30 860: 429a cmp r2, r3
31 862: d3e9 bcc.n 838 <spi_send_packet+0x10>
32 864: 46bd mov sp, r7
33 866: b003 add sp, #12
34 868: bc80 pop {r7}
35 86a: bc01 pop {r0}
36 86c: 4700 bx r0
37 86e: 46c0 nop (mov r8, r8)
38 870: e0020008 .word 0xe0020008
39 874: e0020004 .word 0xe0020004
mit -01 das: 1 00000570 <spi_send_packet>:
2 570: b5f0 push {r4, r5, r6, r7, lr}
3 572: 465f mov r7, fp
4 574: 4656 mov r6, sl
5 576: 464d mov r5, r9
6 578: 4644 mov r4, r8
7 57a: b4f0 push {r4, r5, r6, r7}
8 57c: 4683 mov fp, r0
9 57e: 4689 mov r9, r1
10 580: 2900 cmp r1, #0
11 582: d012 beq.n 5aa <spi_send_packet+0x3a>
12 584: 2300 movs r3, #0
13 586: 469a mov sl, r3
14 588: 4b0c ldr r3, [pc, #48] (5bc <spi_send_packet+0x4c>)
15 58a: 781f ldrb r7, [r3, #0]
16 58c: 063d lsls r5, r7, #24
17 58e: 0e2c lsrs r4, r5, #24
18 590: 0620 lsls r0, r4, #24
19 592: 1601 asrs r1, r0, #24
20 594: 465b mov r3, fp
21 596: 4453 add r3, sl
22 598: 781a ldrb r2, [r3, #0]
23 59a: 4b09 ldr r3, [pc, #36] (5c0 <spi_send_packet+0x50>)
24 59c: 701a strb r2, [r3, #0]
25 59e: 2900 cmp r1, #0
26 5a0: dafd bge.n 59e <spi_send_packet+0x2e>
27 5a2: 2301 movs r3, #1
28 5a4: 449a add sl, r3
29 5a6: 45d1 cmp r9, sl
30 5a8: d8f4 bhi.n 594 <spi_send_packet+0x24>
31 5aa: bc3c pop {r2, r3, r4, r5}
32 5ac: 4690 mov r8, r2
33 5ae: 4699 mov r9, r3
34 5b0: 46a2 mov sl, r4
35 5b2: 46ab mov fp, r5
36 5b4: bcf0 pop {r4, r5, r6, r7}
37 5b6: bc01 pop {r0}
38 5b8: 4700 bx r0
39 5ba: 46c0 nop (mov r8, r8)
40 5bc: e0020004 .word 0xe0020004
41 5c0: e0020008 .word 0xe0020008
diese Routine bleibt dann bei 59e und 5a0 hängen
So nun stellt sich natürlich die Frage, warum kommt das aus dem Compiler
raus?
mit
asm volatile("nop\n");
in der Schleife und -O1 kommt folgendes raus, was aber nur beim Debuggen
mit Single Step funktioniert, sonst läuft der Code auch nicht durch.
1 00000570 <spi_send_packet>:
2 570: b5f0 push {r4, r5, r6, r7, lr}
3 572: 465f mov r7, fp
4 574: 4656 mov r6, sl
5 576: 464d mov r5, r9
6 578: 4644 mov r4, r8
7 57a: b4f0 push {r4, r5, r6, r7}
8 57c: b08f sub sp, #60
9 57e: 900d str r0, [sp, #52]
10 580: 910c str r1, [sp, #48]
11 582: 2900 cmp r1, #0
12 584: d02e beq.n 5e4 <spi_send_packet+0x74>
13 586: 2600 movs r6, #0
14 588: 4a1b ldr r2, [pc, #108] (5f8 <spi_send_packet+0x88>)
15 58a: 4692 mov sl, r2
16 58c: 4b1b ldr r3, [pc, #108] (5fc <spi_send_packet+0x8c>)
17 58e: 9305 str r3, [sp, #20]
18 590: 781f ldrb r7, [r3, #0]
19 592: 9704 str r7, [sp, #16]
20 594: 466a mov r2, sp
21 596: 7317 strb r7, [r2, #12]
22 598: 7b17 ldrb r7, [r2, #12]
23 59a: 063f lsls r7, r7, #24
24 59c: 9702 str r7, [sp, #8]
25 59e: 0e3f lsrs r7, r7, #24
26 5a0: 063f lsls r7, r7, #24
27 5a2: 9701 str r7, [sp, #4]
28 5a4: 163f asrs r7, r7, #24
29 5a6: 46b8 mov r8, r7
30 5a8: 9300 str r3, [sp, #0]
31 5aa: 9f0d ldr r7, [sp, #52]
32 5ac: 5dbb ldrb r3, [r7, r6]
33 5ae: 4652 mov r2, sl
34 5b0: 7013 strb r3, [r2, #0]
35 5b2: 4642 mov r2, r8
36 5b4: 2a00 cmp r2, #0
37 5b6: db11 blt.n 5dc <spi_send_packet+0x6c>
38 5b8: 9b00 ldr r3, [sp, #0]
39 5ba: 781d ldrb r5, [r3, #0]
40 5bc: 1c2c adds r4, r5, #0
41 5be: 0628 lsls r0, r5, #24
42 5c0: 0e01 lsrs r1, r0, #24
43 5c2: 060a lsls r2, r1, #24
44 5c4: 1613 asrs r3, r2, #24
45 5c6: 46c0 nop (mov r8, r8)
46 5c8: 9509 str r5, [sp, #36]
47 5ca: 272b movs r7, #43
48 5cc: 446f add r7, sp
49 5ce: 703c strb r4, [r7, #0]
50 5d0: 9008 str r0, [sp, #32]
51 5d2: 910e str r1, [sp, #56]
52 5d4: 9206 str r2, [sp, #24]
53 5d6: 9307 str r3, [sp, #28]
54 5d8: 2b00 cmp r3, #0
55 5da: daf4 bge.n 5c6 <spi_send_packet+0x56>
56 5dc: 3601 adds r6, #1
57 5de: 9a0c ldr r2, [sp, #48]
58 5e0: 42b2 cmp r2, r6
59 5e2: d8e2 bhi.n 5aa <spi_send_packet+0x3a>
60 5e4: b00f add sp, #60
61 5e6: bc3c pop {r2, r3, r4, r5}
62 5e8: 4690 mov r8, r2
63 5ea: 4699 mov r9, r3
64 5ec: 46a2 mov sl, r4
65 5ee: 46ab mov fp, r5
66 5f0: bcf0 pop {r4, r5, r6, r7}
67 5f2: bc01 pop {r0}
68 5f4: 4700 bx r0
69 5f6: 46c0 nop (mov r8, r8)
70 5f8: e0020008 .word 0xe0020008
71 5fc: e0020004 .word 0xe0020004
irgendwie sehr eigenartig das ganze für mich, so richtig fällt mir
leider nichts ein was ich da gerade falsch mache? Ich hoffe mir kann wer
zumindest etwas helfen.
gr
thomas
von
Thomas (Gast)
09.03.2009 10:23
Hallo nochmal, nun bin ich etwas weiter mit meinem Problem, aber schlau
werd ich daraus noch immer nicht. Und zwar hat das Problem anscheinend
mit der const Deklaration vom SPI Status Register zu tun, denn wenn ich
das ohne const deklariere funktionierts mit -O1, -O2 und -Os mit -O3 hab
ichs nicht probiert.
Also so geht das ganze:
1 #define SPI_MASTER_SR S0PSR
2 #define SPI_MASTER_DR S0PDR
3
4 extern volatile /*const*/ unsigned char S0PSR ;
5 extern volatile unsigned char S0PDR ;
6
7
8 void spi_send_packet ( unsigned int * packet , unsigned int count ) {
9 unsigned int i ;
10
11 for ( i = 0 ; i < count ; i ++ , packet ++ ) {
12 SPI_MASTER_DR = * packet ;
13 while ( ! ( SPI_MASTER_SR & ( 1 << 7 ))) {
14 //asm volatile("nop\n");
15 }
16 }
17 }
und so nicht: 1 #define SPI_MASTER_SR S0PSR
2 #define SPI_MASTER_DR S0PDR
3
4 extern volatile const unsigned char S0PSR ;
5 extern volatile unsigned char S0PDR ;
6
7
8 void spi_send_packet ( unsigned int * packet , unsigned int count ) {
9 unsigned int i ;
10
11 for ( i = 0 ; i < count ; i ++ , packet ++ ) {
12 SPI_MASTER_DR = * packet ;
13 while ( ! ( SPI_MASTER_SR & ( 1 << 7 ))) {
14 //asm volatile("nop\n");
15 }
16 }
17 }
Das ganze ist Teil eines Bootloaders für einen LPC2114 und holt sich von
einem Flash über SPI die neue Firmware, im Anhang habe ich auch noch ein
zusammengestriktes Projekt gestellt das mit yagarto kompilieren sollte.
Würde mich ziemlich interessieren warum das mit const nicht geht?
gr
thomas
Thomas wrote:
> Würde mich ziemlich interessieren warum das mit const nicht geht?
Sieht mir nach einem Optimizerfehler aus.
Der Optimizer dürfte das const höher bewerten als volatile. Und da sich
eine Konstante nicht verändern kann, ....
Versuch mal -Os, allein schon damit der erzeugte Code nicht ganz so
grauslich aussieht. Der gepostete Moloch riecht zu sehr nach Arbeit. ;-)
von
Thomas (Gast)
09.03.2009 11:15
hier sind nochmal die Assembler Listings aus dem *.lss File mit -Os
mit const, so bleibt die Routine bei bei 2f8 bzw 2fa hängen 1 000002e0 <spi_send_packet>:
2 2e0: b530 push {r4, r5, lr}
3 2e2: 1c05 adds r5, r0, #0
4 2e4: 1c0c adds r4, r1, #0
5 2e6: 2200 movs r2, #0
6 2e8: 4807 ldr r0, [pc, #28] (308 <spi_send_packet+0x28>)
7 2ea: 4908 ldr r1, [pc, #32] (30c <spi_send_packet+0x2c>)
8 2ec: e007 b.n 2fe <spi_send_packet+0x1e>
9 2ee: 5cab ldrb r3, [r5, r2]
10 2f0: 7003 strb r3, [r0, #0]
11 2f2: 780b ldrb r3, [r1, #0]
12 2f4: 061b lsls r3, r3, #24
13 2f6: 161b asrs r3, r3, #24
14 2f8: 2b00 cmp r3, #0
15 2fa: dafd bge.n 2f8 <spi_send_packet+0x18>
16 2fc: 3201 adds r2, #1
17 2fe: 42a2 cmp r2, r4
18 300: d3f5 bcc.n 2ee <spi_send_packet+0xe>
19 302: bc30 pop {r4, r5}
20 304: bc01 pop {r0}
21 306: 4700 bx r0
22 308: e0020008 .word 0xe0020008
23 30c: e0020004 .word 0xe0020004
hier ohne const dieses Version funktioniert: 1 000002d8 <spi_send_packet>:
2 2d8: b530 push {r4, r5, lr}
3 2da: 1c05 adds r5, r0, #0
4 2dc: 1c0c adds r4, r1, #0
5 2de: 2200 movs r2, #0
6 2e0: 4807 ldr r0, [pc, #28] (300 <spi_send_packet+0x28>)
7 2e2: 4908 ldr r1, [pc, #32] (304 <spi_send_packet+0x2c>)
8 2e4: e006 b.n 2f4 <spi_send_packet+0x1c>
9 2e6: 5cab ldrb r3, [r5, r2]
10 2e8: 7003 strb r3, [r0, #0]
11 2ea: 780b ldrb r3, [r1, #0]
12 2ec: 061b lsls r3, r3, #24
13 2ee: 2b00 cmp r3, #0
14 2f0: dafb bge.n 2ea <spi_send_packet+0x12>
15 2f2: 3201 adds r2, #1
16 2f4: 42a2 cmp r2, r4
17 2f6: d3f6 bcc.n 2e6 <spi_send_packet+0xe>
18 2f8: bc30 pop {r4, r5}
19 2fa: bc01 pop {r0}
20 2fc: 4700 bx r0
21 2fe: 46c0 nop (mov r8, r8)
22 300: e0020008 .word 0xe0020008
23 304: e0020004 .word 0xe0020004
Danke, wesentlich übersichtlicher :-) Vom GCC für ARM generierter Code
sieht immer etwas konfus aus.
1 2f8: 2b00 cmp r3, #0
2 2fa: dafd bge.n 2f8 <spi_send_packet+0x18>
1. Vergleiche r3 mit 0.
2. Wenn r3 positiv (Bit7==0), gehe zu 1.
Das ergibt ja überhaupt keinen Sinn. Wird da auf ein kosmisches Teilchen
gewartet welches das Vorzeichen von r3 ändert?
Ich vermute ebenfalls einen Compilerbug.
Gruß
Marcus
http://www.doulos.com/arm/
Yep, das sieht schwer nach einem Compilerfehler aus. "const" und
"volatile" sind in C wie in C++ unabhängig voneinander. GCC scheint das
anders zu sehen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.