aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asm/delay.s8
-rw-r--r--build.rs1
-rw-r--r--src/asm.rs35
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
diff --git a/build.rs b/build.rs
index 4866ed2..87e082e 100644
--- a/build.rs
+++ b/build.rs
@@ -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")
diff --git a/src/asm.rs b/src/asm.rs
index 6e90f09..fd1ce7c 100644
--- a/src/asm.rs
+++ b/src/asm.rs
@@ -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() {