diff options
-rw-r--r-- | asm/delay.s | 8 | ||||
-rw-r--r-- | build.rs | 1 | ||||
-rw-r--r-- | src/asm.rs | 35 |
3 files changed, 44 insertions, 0 deletions
diff --git a/asm/delay.s b/asm/delay.s new file mode 100644 index 0000000..2bf92f1 --- /dev/null +++ b/asm/delay.s @@ -0,0 +1,8 @@ + .global __delay + .syntax unified + .thumb_func +__delay: + nop + subs r0, #1 + bne __delay + bx lr @@ -15,6 +15,7 @@ fn main() { .file("asm/control.s") .file("asm/cpsid.s") .file("asm/cpsie.s") + .file("asm/delay.s") .file("asm/dmb.s") .file("asm/dsb.s") .file("asm/faultmask.s") @@ -24,6 +24,41 @@ pub fn bkpt() { } } +/// Blocks the program for *at least* `n` instruction cycles +/// +/// This is implemented in assembly so its execution time is the same regardless of the optimization +/// level. +/// +/// NOTE that the delay can take much longer if interrupts are serviced during its execution. +#[inline] +pub fn delay(_n: u32) { + match () { + #[cfg(all(cortex_m, feature = "inline-asm"))] + () => unsafe { + asm!("1: + nop + subs $0, $$1 + bne.n 1b" + : "+r"(_n / 4 + 1) + : + : + : "volatile"); + }, + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __delay(n: u32); + } + + __delay(_n / 4 + 1); + }, + + #[cfg(not(cortex_m))] + () => unimplemented!(), + } +} + /// A no-operation. Useful to prevent delay loops from being optimized away. #[inline] pub fn nop() { |