NOP
If in the previous section you compiled the program in release mode and actually looked at thedisassembly, you probably noticed that the delay
function is optimized away and never gets calledfrom within main
.
LLVM decided that the function wasn’t doing anything worthwhile and just removed it.
There is a way to prevent LLVM from optimizing the for
loop delay: add a volatile assemblyinstruction. Any instruction will do but NOP (No OPeration) is a particular good choice in this casebecause it has no side effect.
Your for
loop delay would become:
#[inline(never)]
fn delay(_tim6: &tim6::RegisterBlock, ms: u16) {
const K: u16 = 3; // this value needs to be tweaked
for _ in 0..(K * ms) {
aux9::nop()
}
}
And this time delay
won’t be compiled away by LLVM when you compile your program in release mode:
$ cargo objdump --bin clocks-and-timers --release -- -d -no-show-raw-insn
clocks-and-timers: file format ELF32-arm-little
Disassembly of section .text:
clocks_and_timers::delay::h711ce9bd68a6328f:
8000188: push {r4, r5, r7, lr}
800018a: movs r4, #0
800018c: adds r4, #1
800018e: uxth r5, r4
8000190: bl #4666
8000194: cmp r5, #150
8000196: blo #-14 <clocks_and_timers::delay::h711ce9bd68a6328f+0x4>
8000198: pop {r4, r5, r7, pc}
Now, test this: Compile the program in debug mode and run it, then compile the program in releasemode and run it. What’s the difference between them? What do you think is the main cause of thedifference? Can you think of a way to make them equivalent or at least more similar again?