avr_device/
asm.rs

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