Skip to content

Document asm::delay() behaviour more thoroughly #597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 7, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions cortex-m/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,18 @@ pub fn bkpt() {

/// Blocks the program for *at least* `cycles` CPU cycles.
///
/// This is implemented in assembly so its execution time is independent of the optimization
/// level, however it is dependent on the specific architecture and core configuration.
/// This is implemented in assembly as a fixed number of iterations of a loop, so that execution
/// time is independent of the optimization level.
///
/// NOTE that the delay can take much longer if interrupts are serviced during its execution
/// and the execution time may vary with other factors. This delay is mainly useful for simple
/// timer-less initialization of peripherals if and only if accurate timing is not essential. In
/// any other case please use a more accurate method to produce a delay.
/// The loop code is the same for all architectures, however the number of CPU cycles required for
/// one iteration varies substantially between architectures. This means that with a 48MHz CPU
/// clock, a call to `delay(48_000_000)` is guaranteed to take at least 1 second, but for example
/// could take 2 seconds.
///
/// NOTE that the delay can take much longer if interrupts are serviced during its execution and the
/// execution time may vary with other factors. This delay is mainly useful for simple timer-less
/// initialization of peripherals if and only if accurate timing is not essential. In any other case
/// please use a more accurate method to produce a delay.
#[cfg(cortex_m)]
#[inline]
pub fn delay(cycles: u32) {
Expand All @@ -33,9 +38,9 @@ pub fn delay(cycles: u32) {
let real_cycles = 1 + cycles / 2;
unsafe {
asm!(
// The `bne` on some cores (eg Cortex-M4) will take a different number of instructions
// The `bne` on some cores (eg Cortex-M4) will take a different number of cycles
// depending on the alignment of the branch target. Set the alignment of the top of the
// loop to prevent surprising timing changes when the alignment of the delay() changes.
// loop to prevent surprising timing changes when the alignment of `fn delay()` changes.
".p2align 3",
// Use local labels to avoid R_ARM_THM_JUMP8 relocations which fail on thumbv6m.
"1:",
Expand Down