Der beste Weg ist die Verwendung von On-Chip-Timern. Systick-, RTC- oder Peripherie-Timer. Diese haben den Vorteil, dass das Timing präzise und deterministisch ist und leicht angepasst werden kann, wenn die CPU-Taktrate geändert wird. Optional können Sie die CPU sogar in den Ruhezustand versetzen und einen Weckinterrupt verwenden.
Schmutzige "Busy-Delay" -Schleifen hingegen sind selten genau und weisen verschiedene Probleme auf, z. B. eine "enge Kopplung" an einen bestimmten CPU-Befehlssatz und eine bestimmte Uhr.
Einige bemerkenswerte Dinge:
- Das wiederholte Umschalten eines GPIO-Pins ist eine schlechte Idee, da dies unnötig Strom zieht und möglicherweise auch EMV-Probleme verursacht, wenn der Pin mit Leiterbahnen verbunden ist.
- Die Verwendung von NOP-Anweisungen funktioniert möglicherweise nicht. Viele Architekturen (wie Cortex M, iirc) können NOP auf CPU-Ebene überspringen und tatsächlich nicht ausführen.
Wenn Sie darauf bestehen möchten, eine schmutzige Besetztschleife zu generieren, reicht es aus, nur volatile
den Schleifeniterator zu qualifizieren. Zum Beispiel:
void dirty_delay (void)
{
for(volatile uint32_t i=0; i<50000u; i++)
;
}
Dies erzeugt garantiert verschiedene Mistcodes. Zum Beispiel -O3 -ffreestanding
gibt ARM gcc :
dirty_delay:
mov r3, #0
sub sp, sp, #8
str r3, [sp, #4]
ldr r3, [sp, #4]
ldr r2, .L7
cmp r3, r2
bhi .L1
.L3:
ldr r3, [sp, #4]
add r3, r3, #1
str r3, [sp, #4]
ldr r3, [sp, #4]
cmp r3, r2
bls .L3
.L1:
add sp, sp, #8
bx lr
.L7:
.word 49999
Von da an können Sie theoretisch berechnen, wie viele Ticks jeder Befehl benötigt, und die magische Zahl 50000 entsprechend ändern. Pipelining, Verzweigungsvorhersage usw. bedeuten jedoch, dass der Code möglicherweise schneller als nur die Summe der Taktzyklen ausgeführt wird. Da der Compiler beschlossen hat, den Stack einzubeziehen, könnte auch das Zwischenspeichern von Daten eine Rolle spielen.
Mein ganzer Punkt hier ist, dass es schwierig ist, genau zu berechnen, wie viel Zeit dieser Code tatsächlich benötigt. Trial & Error-Benchmarking mit einem Scope ist wahrscheinlich eine sinnvollere Idee als theoretische Berechnungen.