NOP

You might wonder what that nop() call is doing in the wait() loop in src/bin/spin-wait.rs.

The answer is that it literally does nothing. The nop() function causes the compiler to put a NOP ARM machine instruction at that point in the program. NOP is a special instruction that causes the CPU to skip it. To ignore it. To literally do No OPeration with it (hence the name).

So get rid of that line and recompile the program. Don't forget --release mode. Then run it.

We're back to a slightly darker solid LED again. With no loop body, the compiler's optimizer decided that wait() function wasn't doing anything. So it just removed it for you at compile time. Thanks optimizer. You have made my wait loop infinitely fast.

How does nop() do its job? Well, if you look at the implementation of nop() you will find (after a bunch of digging around) that it is implemented like this:

#![allow(unused)]
fn main() {
asm!("nop", options(nomem, nostack, preserves_flags));
}

The nop() function is "inlined", so when you "call" it an actual ARM NOP assembly instruction is inserted into your program's code at that point. Because details, this NOP will not be removed or moved around by the compiler: it will stay right there where you put it.

The ability to insert assembly code into your program where needed is sometimes quite important in embedded programming. Sometime a CPU will have instructions the compiler doesn't know about, but that you still need in order to use the CPU effectively. Rust's asm!() directive gives you a way to do that.

Our spin-wait is still terrible. Let's talk about doing better.