mikrocontroller.net

Forum: Compiler & IDEs ARM Problem mit Optimierung


Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe derzeit leider ein Problem mit dem ARM und der Übersetzung bei 
eingeschalteter Optimierung. Und zwar mit folgendem Codefragment:
#define SPI_MASTER_SR        S0PSR
extern volatile const unsigned char S0PSR;

void spi_send_packet(unsigned int* packet, unsigned int count) {
  unsigned int i;

  for (i = 0; i < count; i++, packet++) {
    SPI_MASTER_DR = *packet;
    while(!(SPI_MASTER_SR & (1<<7))) {
      //asm volatile("nop\n");
    }
  }
}

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:
00000828 <spi_send_packet>:
 828:  b580        push  {r7, lr}
 82a:  b083        sub  sp, #12
 82c:  af00        add  r7, sp, #0
 82e:  6078        str  r0, [r7, #4]
 830:  6039        str  r1, [r7, #0]
 832:  2300        movs  r3, #0
 834:  60bb        str  r3, [r7, #8]
 836:  e011        b.n  85c <spi_send_packet+0x34>
 838:  687b        ldr  r3, [r7, #4]
 83a:  781b        ldrb  r3, [r3, #0]
 83c:  4a0c        ldr  r2, [pc, #48]  (870 <spi_send_packet+0x48>)
 83e:  7013        strb  r3, [r2, #0]
 840:  4b0c        ldr  r3, [pc, #48]  (874 <spi_send_packet+0x4c>)
 842:  781b        ldrb  r3, [r3, #0]
 844:  061b        lsls  r3, r3, #24
 846:  0e1b        lsrs  r3, r3, #24
 848:  061b        lsls  r3, r3, #24
 84a:  161b        asrs  r3, r3, #24
 84c:  2b00        cmp  r3, #0
 84e:  daf7        bge.n  840 <spi_send_packet+0x18>
 850:  68bb        ldr  r3, [r7, #8]
 852:  3301        adds  r3, #1
 854:  60bb        str  r3, [r7, #8]
 856:  687b        ldr  r3, [r7, #4]
 858:  3301        adds  r3, #1
 85a:  607b        str  r3, [r7, #4]
 85c:  68ba        ldr  r2, [r7, #8]
 85e:  683b        ldr  r3, [r7, #0]
 860:  429a        cmp  r2, r3
 862:  d3e9        bcc.n  838 <spi_send_packet+0x10>
 864:  46bd        mov  sp, r7
 866:  b003        add  sp, #12
 868:  bc80        pop  {r7}
 86a:  bc01        pop  {r0}
 86c:  4700        bx  r0
 86e:  46c0        nop      (mov r8, r8)
 870:  e0020008   .word  0xe0020008
 874:  e0020004   .word  0xe0020004

mit -01 das:
00000570 <spi_send_packet>:
 570:  b5f0        push  {r4, r5, r6, r7, lr}
 572:  465f        mov  r7, fp
 574:  4656        mov  r6, sl
 576:  464d        mov  r5, r9
 578:  4644        mov  r4, r8
 57a:  b4f0        push  {r4, r5, r6, r7}
 57c:  4683        mov  fp, r0
 57e:  4689        mov  r9, r1
 580:  2900        cmp  r1, #0
 582:  d012        beq.n  5aa <spi_send_packet+0x3a>
 584:  2300        movs  r3, #0
 586:  469a        mov  sl, r3
 588:  4b0c        ldr  r3, [pc, #48]  (5bc <spi_send_packet+0x4c>)
 58a:  781f        ldrb  r7, [r3, #0]
 58c:  063d        lsls  r5, r7, #24
 58e:  0e2c        lsrs  r4, r5, #24
 590:  0620        lsls  r0, r4, #24
 592:  1601        asrs  r1, r0, #24
 594:  465b        mov  r3, fp
 596:  4453        add  r3, sl
 598:  781a        ldrb  r2, [r3, #0]
 59a:  4b09        ldr  r3, [pc, #36]  (5c0 <spi_send_packet+0x50>)
 59c:  701a        strb  r2, [r3, #0]
 59e:  2900        cmp  r1, #0
 5a0:  dafd        bge.n  59e <spi_send_packet+0x2e>
 5a2:  2301        movs  r3, #1
 5a4:  449a        add  sl, r3
 5a6:  45d1        cmp  r9, sl
 5a8:  d8f4        bhi.n  594 <spi_send_packet+0x24>
 5aa:  bc3c        pop  {r2, r3, r4, r5}
 5ac:  4690        mov  r8, r2
 5ae:  4699        mov  r9, r3
 5b0:  46a2        mov  sl, r4
 5b2:  46ab        mov  fp, r5
 5b4:  bcf0        pop  {r4, r5, r6, r7}
 5b6:  bc01        pop  {r0}
 5b8:  4700        bx  r0
 5ba:  46c0        nop      (mov r8, r8)
 5bc:  e0020004   .word  0xe0020004
 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.
00000570 <spi_send_packet>:
 570:  b5f0        push  {r4, r5, r6, r7, lr}
 572:  465f        mov  r7, fp
 574:  4656        mov  r6, sl
 576:  464d        mov  r5, r9
 578:  4644        mov  r4, r8
 57a:  b4f0        push  {r4, r5, r6, r7}
 57c:  b08f        sub  sp, #60
 57e:  900d        str  r0, [sp, #52]
 580:  910c        str  r1, [sp, #48]
 582:  2900        cmp  r1, #0
 584:  d02e        beq.n  5e4 <spi_send_packet+0x74>
 586:  2600        movs  r6, #0
 588:  4a1b        ldr  r2, [pc, #108]  (5f8 <spi_send_packet+0x88>)
 58a:  4692        mov  sl, r2
 58c:  4b1b        ldr  r3, [pc, #108]  (5fc <spi_send_packet+0x8c>)
 58e:  9305        str  r3, [sp, #20]
 590:  781f        ldrb  r7, [r3, #0]
 592:  9704        str  r7, [sp, #16]
 594:  466a        mov  r2, sp
 596:  7317        strb  r7, [r2, #12]
 598:  7b17        ldrb  r7, [r2, #12]
 59a:  063f        lsls  r7, r7, #24
 59c:  9702        str  r7, [sp, #8]
 59e:  0e3f        lsrs  r7, r7, #24
 5a0:  063f        lsls  r7, r7, #24
 5a2:  9701        str  r7, [sp, #4]
 5a4:  163f        asrs  r7, r7, #24
 5a6:  46b8        mov  r8, r7
 5a8:  9300        str  r3, [sp, #0]
 5aa:  9f0d        ldr  r7, [sp, #52]
 5ac:  5dbb        ldrb  r3, [r7, r6]
 5ae:  4652        mov  r2, sl
 5b0:  7013        strb  r3, [r2, #0]
 5b2:  4642        mov  r2, r8
 5b4:  2a00        cmp  r2, #0
 5b6:  db11        blt.n  5dc <spi_send_packet+0x6c>
 5b8:  9b00        ldr  r3, [sp, #0]
 5ba:  781d        ldrb  r5, [r3, #0]
 5bc:  1c2c        adds  r4, r5, #0
 5be:  0628        lsls  r0, r5, #24
 5c0:  0e01        lsrs  r1, r0, #24
 5c2:  060a        lsls  r2, r1, #24
 5c4:  1613        asrs  r3, r2, #24
 5c6:  46c0        nop      (mov r8, r8)
 5c8:  9509        str  r5, [sp, #36]
 5ca:  272b        movs  r7, #43
 5cc:  446f        add  r7, sp
 5ce:  703c        strb  r4, [r7, #0]
 5d0:  9008        str  r0, [sp, #32]
 5d2:  910e        str  r1, [sp, #56]
 5d4:  9206        str  r2, [sp, #24]
 5d6:  9307        str  r3, [sp, #28]
 5d8:  2b00        cmp  r3, #0
 5da:  daf4        bge.n  5c6 <spi_send_packet+0x56>
 5dc:  3601        adds  r6, #1
 5de:  9a0c        ldr  r2, [sp, #48]
 5e0:  42b2        cmp  r2, r6
 5e2:  d8e2        bhi.n  5aa <spi_send_packet+0x3a>
 5e4:  b00f        add  sp, #60
 5e6:  bc3c        pop  {r2, r3, r4, r5}
 5e8:  4690        mov  r8, r2
 5ea:  4699        mov  r9, r3
 5ec:  46a2        mov  sl, r4
 5ee:  46ab        mov  fp, r5
 5f0:  bcf0        pop  {r4, r5, r6, r7}
 5f2:  bc01        pop  {r0}
 5f4:  4700        bx  r0
 5f6:  46c0        nop      (mov r8, r8)
 5f8:  e0020008   .word  0xe0020008
 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

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
#define SPI_MASTER_SR        S0PSR
#define SPI_MASTER_DR        S0PDR

extern volatile /*const*/ unsigned char S0PSR;
extern volatile unsigned char S0PDR;


void spi_send_packet(unsigned int* packet, unsigned int count) {
  unsigned int i;

  for (i = 0; i < count; i++, packet++) {
    SPI_MASTER_DR = *packet;
    while(!(SPI_MASTER_SR & (1<<7))) {
      //asm volatile("nop\n");
    }
  }
}

und so nicht:
#define SPI_MASTER_SR        S0PSR
#define SPI_MASTER_DR        S0PDR

extern volatile const unsigned char S0PSR;
extern volatile unsigned char S0PDR;


void spi_send_packet(unsigned int* packet, unsigned int count) {
  unsigned int i;

  for (i = 0; i < count; i++, packet++) {
    SPI_MASTER_DR = *packet;
    while(!(SPI_MASTER_SR & (1<<7))) {
      //asm volatile("nop\n");
    }
  }
}

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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, ....

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuch mal -Os, allein schon damit der erzeugte Code nicht ganz so 
grauslich aussieht. Der gepostete Moloch riecht zu sehr nach Arbeit. ;-)

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
000002e0 <spi_send_packet>:
 2e0:  b530        push  {r4, r5, lr}
 2e2:  1c05        adds  r5, r0, #0
 2e4:  1c0c        adds  r4, r1, #0
 2e6:  2200        movs  r2, #0
 2e8:  4807        ldr  r0, [pc, #28]  (308 <spi_send_packet+0x28>)
 2ea:  4908        ldr  r1, [pc, #32]  (30c <spi_send_packet+0x2c>)
 2ec:  e007        b.n  2fe <spi_send_packet+0x1e>
 2ee:  5cab        ldrb  r3, [r5, r2]
 2f0:  7003        strb  r3, [r0, #0]
 2f2:  780b        ldrb  r3, [r1, #0]
 2f4:  061b        lsls  r3, r3, #24
 2f6:  161b        asrs  r3, r3, #24
 2f8:  2b00        cmp  r3, #0
 2fa:  dafd        bge.n  2f8 <spi_send_packet+0x18>
 2fc:  3201        adds  r2, #1
 2fe:  42a2        cmp  r2, r4
 300:  d3f5        bcc.n  2ee <spi_send_packet+0xe>
 302:  bc30        pop  {r4, r5}
 304:  bc01        pop  {r0}
 306:  4700        bx  r0
 308:  e0020008   .word  0xe0020008
 30c:  e0020004   .word  0xe0020004

hier ohne const dieses Version funktioniert:
000002d8 <spi_send_packet>:
 2d8:  b530        push  {r4, r5, lr}
 2da:  1c05        adds  r5, r0, #0
 2dc:  1c0c        adds  r4, r1, #0
 2de:  2200        movs  r2, #0
 2e0:  4807        ldr  r0, [pc, #28]  (300 <spi_send_packet+0x28>)
 2e2:  4908        ldr  r1, [pc, #32]  (304 <spi_send_packet+0x2c>)
 2e4:  e006        b.n  2f4 <spi_send_packet+0x1c>
 2e6:  5cab        ldrb  r3, [r5, r2]
 2e8:  7003        strb  r3, [r0, #0]
 2ea:  780b        ldrb  r3, [r1, #0]
 2ec:  061b        lsls  r3, r3, #24
 2ee:  2b00        cmp  r3, #0
 2f0:  dafb        bge.n  2ea <spi_send_packet+0x12>
 2f2:  3201        adds  r2, #1
 2f4:  42a2        cmp  r2, r4
 2f6:  d3f6        bcc.n  2e6 <spi_send_packet+0xe>
 2f8:  bc30        pop  {r4, r5}
 2fa:  bc01        pop  {r0}
 2fc:  4700        bx  r0
 2fe:  46c0        nop      (mov r8, r8)
 300:  e0020008   .word  0xe0020008
 304:  e0020004   .word  0xe0020004

Autor: Marcus Harnisch (mharnisch) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, wesentlich übersichtlicher :-) Vom GCC für ARM generierter Code 
sieht immer etwas konfus aus.
 2f8:  2b00        cmp  r3, #0
 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/

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

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.