Hi
Ich möchte eine sleep-funktion implementieren habe dort allerdings ein
merkwürdiges Problem.
1
voidsleep_10us(inttimes)
2
{
3
registerunsignedlonglongoldcv;
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
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
Hallo,
sage mir doch bitte wozu die Variable "times" übergeben wird, wenn sie
doch nicht in der Funktion verwendet wird. Ist die Funktion wirklich
komplett?
Gruß
Timer können überlaufen. Da sind schon Generationen an Programmierern
dran gescheitert.
Nur Differenzen stimmen auch bei einem Überlauf.
Vergleiche die Differenz:
Die Warteschleife sieht in beiden Fällen doch absolut gleich aus.
Der Grund kann also nur sein, daß "counter" nicht weit genug hochgezählt
wird, zB vorher wieder zurückgesetzt wird.
Die Glaskugel sagt, du rufst die sleep_10us() Funktion auf während
Interrupts gesperrt sind, deshalb wird counter hier nicht inkrementiert.
Ohne Addition ist die Bedingung in der while Schleife übrigens immer
falsch.
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.