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}