1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
//! Assembly instructions
#[cfg(target_arch = "avr")]
use core::arch::asm;
/// No Operation
#[inline(always)]
pub fn nop() {
cfg_if::cfg_if! {
if #[cfg(target_arch = "avr")] {
unsafe { asm!("nop") }
} else {
unimplemented!()
}
}
}
/// Sleep / Wait For Interrupt
#[inline(always)]
pub fn sleep() {
cfg_if::cfg_if! {
if #[cfg(target_arch = "avr")] {
unsafe { asm!("sleep") }
} else {
unimplemented!()
}
}
}
/// Watchdog Reset
#[inline(always)]
pub fn wdr() {
cfg_if::cfg_if! {
if #[cfg(target_arch = "avr")] {
unsafe { asm!("wdr") }
} else {
unimplemented!()
}
}
}
/// Blocks the program for at least `cycles` CPU cycles.
///
/// This is intended for very simple delays in low-level drivers, but it
/// has some caveats:
///
/// - The delay may be significantly longer if an interrupt is serviced at the
/// same time, since the delay loop will not be executing during the interrupt.
/// If you need precise timing, use a hardware timer peripheral instead.
///
/// - The real-time delay depends on the CPU clock frequency. If you want to
/// conveniently specify a delay value in real-time units like microseconds,
/// then use the `delay` module in the HAL crate for your platform.
#[inline(always)]
pub fn delay_cycles(cycles: u32) {
cfg_if::cfg_if! {
if #[cfg(target_arch = "avr")] {
let mut cycles_bytes = cycles.to_le_bytes();
// Each loop iteration takes 6 cycles when the branch is taken,
// and 5 cycles when the branch is not taken.
// So, this loop is guaranteed to run for at least `cycles - 1`
// cycles, and there will be approximately 4 cycles before the
// loop to initialize the counting registers.
unsafe {
asm!(
"1:",
"subi {r0}, 6",
"sbci {r1}, 0",
"sbci {r2}, 0",
"sbci {r3}, 0",
"brcc 1b",
r0 = inout(reg_upper) cycles_bytes[0],
r1 = inout(reg_upper) cycles_bytes[1],
r2 = inout(reg_upper) cycles_bytes[2],
r3 = inout(reg_upper) cycles_bytes[3],
)
}
} else {
let _ = cycles;
unimplemented!()
}
}
}