Merkwürdige endlosschleife (STM32; GCC4; C)

Gast #2295083
Lesenswert?

Hi
Ich möchte eine sleep-funktion implementieren habe dort allerdings ein 
merkwürdiges Problem.
1
void sleep_10us(int times)
2
{
3
 register unsigned long long oldcv;
4
 oldcv  = counter;
5

6
 oldcv += 23; // <- Diese Zeile macht den unterschied
7

8
 while(oldcv > counter);
9
}

counter ist eine globale Variable die alle 10µs inkrementiert wird. Eine 
Ausgabe der Variable bestätigt auch dass dies geschieht.
Datentyp: volatile unsigned long long

Beim Bau der warteschleife bekam ich allerdings merkwürdige Probleme - 
Die schleife wird nicht verlassen.
Nach einigem rumprobieren (vermutete zunächst das der optimizer da 
Probleme macht) stellte sich heraus, das der obige Code funktioniert, 
wenn ich die Addition auskommentiere, tue ich dies nicht hängt sich das 
Programm auf.

Also habe ich mir mal den assembly-code angeguckt den der Compiler 
erzeugt:

Ohne addition
1
0800ab9c <sleep_10us>:
2
 800ab9c:   4905        ldr r1, [pc, #20]   ; (800abb4 <sleep_10us+0x18>)
3
 800ab9e:   b530        push    {r4, r5, lr}
4
 
5
 800aba0:   e9d1 2306   ldrd    r2, r3, [r1, #24] ; counter laden (in oldcv)
6
 800aba4:   460c        mov r4, r1
7

8
 ; schleife
9
  800aba6:   e9d4 0106   ldrd    r0, r1, [r4, #24] ; counter erneut laden
10
  800abaa:   4290        cmp r0, r2  ; counter und oldcv vergleichen
11
  800abac:   eb71 0503   sbcs.w  r5, r1, r3
12
  800abb0:   d3f9        bcc.n   800aba6 <sleep_10us+0xa>
13
 800abb2:   bd30        pop {r4, r5, pc}
14
 800abb4:   20000988    .word   0x20000988
Soweit ist der code verständlich, auch wenn ich nie in arm-asm 
programmiert habe.

Als nächstes habe ich mir dann den Code mit der Addition angesehen
1
0800ab9c <sleep_10us>:
2
 800ab9c:   b530        push    {r4, r5, lr}
3
 800ab9e:   4c07        ldr r4, [pc, #28]   ; (800abbc <sleep_10us+0x20>)
4

5
 800aba0:   2017        movs    r0, #23 ; konstanter summand
6
 800aba2:   e9d4 2306   ldrd    r2, r3, [r4, #24] ; counter in oldcv laden
7
 800aba6:   2100        movs    r1, #0 ; die oberen 32 bit des summanden
8

9
 800aba8:   1812        adds    r2, r2, r0 ; addition der konstanten auf oldcv
10
 800abaa:   eb43 0301   adc.w   r3, r3, r1
11

12
; Schleifen-anfang 
13
  800abae:   e9d4 0106   ldrd    r0, r1, [r4, #24] ; counter laden
14

15
  800abb2:   4290        cmp r0, r2 ; counter mit oldcv vergleichen
16
  800abb4:   eb71 0503   sbcs.w  r5, r1, r3
17
  800abb8:   d3f9        bcc.n   800abae <sleep_10us+0x12>
18

19
 800abba:   bd30        pop {r4, r5, pc}
20
 800abbc:   20000988    .word   0x20000988
Dieser Code sieht ebenfalls 100% korrekt aus, allerdings wird die 
schleife nie verlassen…

Meine Frage nun: Warum? :D

Controllers: ARM Cortex M3 STM32F103RBT6
Compiler: gcc 4.5.2
1
CFLAGS="-Wall -nostdlib -fno-common -fno-builtin -O0 -g -mcpu=cortex-m3 -mthumb -c"
Gast #2295182
Lesenswert?

Wenn ich die Schleife wie folgt schreibe funktioniert es sporadisch:
1
 while(oldcv > newcv) newcv = counter;
kann es sein dass ich irgend etwas am cache des µCs einstellen muss? 
Habe noch nicht sehr viel Erfahrung mit ARMs
Gast #2297770
Lesenswert?

Bei einem unsigned int würde es schon etwa 11h dauern bis zum overflow, 
so lange wird das Programm nie laufen :)
Und inkrementiert wird auch. Ich habe zunächst einfach den aktuellen 
Stand des Counters zurückgegeben und diesen dann per USB an den PC 
geschickt - dieser wurde steht größer.
Das mit den Interrupts könnte aber tatsächlich ein Problem sein, da ich 
die sleep-funktion inmitten einer USB-Kommunikation anwende.

Ich habe das Problem inzwischen ohne timer lösen können, aber Trotzdem 
danke für den Hinweis.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren