Paras tapa on käyttää sirun ajastimia. Systick-, RTC- tai oheislaitteiden ajastimet. Näillä on se etu, että ajoitus on tarkka, deterministinen ja se voidaan helposti mukauttaa, jos prosessorin kellotaajuutta muutetaan. Vaihtoehtoisesti voit jopa antaa CPU: n nukkua ja käyttää herätyskeskeytystä.
Likaiset "varattu-viive" -silmukat ovat toisaalta harvoin tarkkoja ja niissä on erilaisia ongelmia, kuten "tiukka kytkentä" tiettyyn suorittimen käskyjoukkoon ja kelloon.
Joitakin huomioitavia asioita:
- GPIO-nastan vaihtaminen toistuvasti on huono idea, koska se vetää virtaa tarpeettomasti ja aiheuttaa myös EMC-ongelmia, jos tappi on kytketty jälkiin.
- NOP-ohjeiden käyttäminen ei välttämättä toimi. Monet arkkitehtuurit (kuten Cortex M, iirc) voivat vapaasti ohittaa NOP: n suorittimen tasolla eivätkä itse suorita niitä.
Jos haluat vaatia likainen kiireisen silmukan luomista, riittää, että vain volatile
hyväksytään silmukka-iteraattori. Esimerkiksi:
void dirty_delay (mitätöity)
{
for (haihtuva uint32_t i = 0; i<50000u; i ++)
;
}
Tämän avulla voidaan taata erilaisia roskakoodeja. Esimerkiksi ARM gcc -O3 -vapaasti seisova
antaa:
likainen_viive:
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]
lisää r3, r3, # 1
str r3, [sp, # 4]
ldr r3, [sp, # 4]
cmp r3, r2
bls. L3
.L1:
lisää sp, sp, # 8
bx lr
.L7:
.sana 49999
Siitä lähtien voit teoriassa laskea, kuinka monta punkkia kukin käsky vie, ja muuttaa taikuuslukua 50000 vastaavasti. Putkilinja, haaraennuste jne. Tarkoittaa, että koodi saattaa kuitenkin suorittaa nopeammin kuin vain kellojaksojen summa. Koska kääntäjä päätti ottaa pinon mukaan, myös tietojen välimuistilla voi olla merkitystä.
Koko ajatukseni on, että on vaikeaa laskea tarkasti kuinka paljon aikaa tämä koodi todella vie.Kokeiluversioiden vertailuanalyysi &ista on todennäköisesti järkevämpi idea kuin teoreettisten laskelmien yrittäminen.