embassy-rp

Crates

git

Versions

rp235xb

Flavors

Module aon_timer

Module aon_timer 

Source
Expand description

AON (Always-On) Timer driver for RP2350

The AON Timer is a 64-bit counter that typically runs at 1 kHz (1ms resolution) and can operate during low-power modes. It’s part of the POWMAN peripheral and provides:

  • Millisecond resolution counter
  • Alarm support for wakeup from low-power modes (WFI/WFE and DORMANT)
  • Async alarm waiting with interrupt support (POWMAN_IRQ_TIMER)
  • Choice of XOSC or LPOSC clock sources

§Alarm Wake Modes

The AON Timer supports multiple wake modes via the AlarmWakeMode enum:

  • WfiOnly (default): Alarm triggers POWMAN_IRQ_TIMER interrupt to wake from WFI/WFE (light sleep). Use wait_for_alarm().await for async waiting. Works with both XOSC and LPOSC clock sources.

  • DormantOnly: Hardware power-up wake from DORMANT (deep sleep). Sets the PWRUP_ON_ALARM bit to trigger hardware power-up event (no interrupt, since CPU clock is stopped). Requirements:

    • Must use LPOSC clock source (XOSC is powered down in DORMANT)
    • Requires Secure privilege level (TIMER register is Secure-only)
  • Both: Enables both interrupt wake (WFI/WFE) and hardware power-up wake (DORMANT). Subject to the same requirements as DormantOnly for DORMANT support.

  • Disabled: Alarm flag is set but no wake mechanisms are enabled. Use alarm_fired() to manually poll the alarm status.

You can set the wake mode either in Config at initialization, or at runtime via AonTimer::set_wake_mode().

§Security Considerations

The TIMER register (including the PWRUP_ON_ALARM bit) is Secure-only per the RP2350 datasheet. Setting wake modes that involve DORMANT wake (DormantOnly or Both) may fail silently or have no effect when running in Non-secure contexts. Methods enable_dormant_wake(), disable_dormant_wake(), and set_wake_mode() that configure DORMANT wake are subject to this restriction.

§Important Notes

  • All POWMAN registers require password 0x5AFE in upper 16 bits for writes
  • Timer must be stopped before setting the counter value
  • Resolution is 1ms (1 kHz tick rate)

§Example - WFI/WFE Wake (Default)

use embassy_rp::aon_timer::{AonTimer, Config, ClockSource, AlarmWakeMode};
use embassy_rp::bind_interrupts;
use embassy_time::Duration;

// Bind the interrupt handler
bind_interrupts!(struct Irqs {
    POWMAN_IRQ_TIMER => embassy_rp::aon_timer::InterruptHandler;
});

let config = Config {
    clock_source: ClockSource::Xosc,
    clock_freq_khz: 12000, // 12 MHz
    alarm_wake_mode: AlarmWakeMode::WfiOnly, // Default
};

let mut timer = AonTimer::new(p.POWMAN, Irqs, config);
timer.set_counter(0);
timer.start();

// Set an alarm and wait asynchronously (interrupt-based wake)
timer.set_alarm_after(Duration::from_secs(5)).unwrap();
timer.wait_for_alarm().await;  // CPU enters WFI low-power mode

§Example - DORMANT Wake

use embassy_rp::aon_timer::{AonTimer, Config, ClockSource, AlarmWakeMode};
use embassy_rp::bind_interrupts;
use embassy_time::Duration;

bind_interrupts!(struct Irqs {
    POWMAN_IRQ_TIMER => embassy_rp::aon_timer::InterruptHandler;
});

let config = Config {
    clock_source: ClockSource::Lposc,  // Required for DORMANT
    clock_freq_khz: 32,                // ~32 kHz LPOSC
    alarm_wake_mode: AlarmWakeMode::DormantOnly,
};

let mut timer = AonTimer::new(p.POWMAN, Irqs, config);
timer.set_counter(0);
timer.start();

// Set alarm for DORMANT wake (hardware power-up)
timer.set_alarm_after(Duration::from_secs(10)).unwrap();
// Enter DORMANT mode here - alarm will wake via power-up event

§Example - Runtime Wake Mode Change

use embassy_rp::aon_timer::{AonTimer, Config, ClockSource, AlarmWakeMode};
use embassy_rp::bind_interrupts;
use embassy_time::Duration;

bind_interrupts!(struct Irqs {
    POWMAN_IRQ_TIMER => embassy_rp::aon_timer::InterruptHandler;
});

let mut timer = AonTimer::new(p.POWMAN, Irqs, Config::default());
timer.set_counter(0);
timer.start();

// Use WFI wake initially
timer.set_alarm_after(Duration::from_secs(5)).unwrap();
timer.wait_for_alarm().await;

// Switch to both wake modes at runtime
timer.set_wake_mode(AlarmWakeMode::Both);
timer.set_alarm_after(Duration::from_secs(10)).unwrap();
// Now supports both WFI and DORMANT wake

§Example - Using DateTime with AON Timer

use embassy_rp::aon_timer::{AonTimer, Config, DateTime, DayOfWeek};
use embassy_rp::bind_interrupts;

bind_interrupts!(struct Irqs {
    POWMAN_IRQ_TIMER => embassy_rp::aon_timer::InterruptHandler;
});

let mut timer = AonTimer::new(p.POWMAN, Irqs, Config::default());

// Set timer to a specific DateTime (e.g., 2024-06-15 12:30:00 UTC)
let start_time = DateTime {
    year: 2024,
    month: 6,
    day: 15,
    day_of_week: DayOfWeek::Saturday,
    hour: 12,
    minute: 30,
    second: 0,
};
timer.set_datetime(start_time).unwrap();
timer.start();

// Later, read current DateTime
let current = timer.now_as_datetime().unwrap();
info!("Current time: {}-{:02}-{:02} {:02}:{:02}:{:02}",
      current.year, current.month, current.day,
      current.hour, current.minute, current.second);

// Set alarm for specific DateTime (1 hour later)
let alarm_time = DateTime {
    year: 2024,
    month: 6,
    day: 15,
    day_of_week: DayOfWeek::Saturday,
    hour: 13,
    minute: 30,
    second: 0,
};
timer.set_alarm_at_datetime(alarm_time).unwrap();
timer.wait_for_alarm().await;

Structs§

AonTimer
AON Timer driver
Config
AON Timer configuration
DateTime
Structure containing date and time information
InterruptHandler
Interrupt handler for AON Timer alarms

Enums§

AlarmWakeMode
Alarm wake mode configuration
ClockSource
Clock source for the AON Timer
DateTimeError
Errors regarding the DateTime struct.
DayOfWeek
A day of the week
Error
AON Timer errors