{"record":{"id":"fc76a90c3303f0ef","repo":"embassy-rs/embassy","slug":"timer-must-be-stopped-before-setting-counter","errorCode":null,"errorMessage":"timer must be stopped before setting counter","messagePattern":"timer must be stopped before setting counter","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-rp/src/aon_timer/mod.rs","lineNumber":391,"sourceCode":"            let upper2 = powman.read_time_upper().read();\n\n            // If upper didn't change, we got a consistent read\n            if upper1 == upper2 {\n                return ((upper1 as u64) << 32) | (lower as u64);\n            }\n            // Otherwise retry (rollover occurred)\n        }\n    }\n\n    /// Set the counter value in milliseconds\n    ///\n    /// This allows you to initialize the counter to any value (e.g., milliseconds since epoch,\n    /// or 0 to start counting from boot).\n    ///\n    /// Note: Timer must be stopped before calling this function.\n    pub fn set_counter(&mut self, value_ms: u64) {\n        if self.is_running() {\n            panic!(\"timer must be stopped before setting counter\");\n        }\n        let powman = pac::POWMAN;\n        powman.set_time_15to0().write(|w| {\n            w.0 = ((value_ms & 0xFFFF) as u32) | POWMAN_PASSWORD;\n        });\n        powman.set_time_31to16().write(|w| {\n            w.0 = (((value_ms >> 16) & 0xFFFF) as u32) | POWMAN_PASSWORD;\n        });\n        powman.set_time_47to32().write(|w| {\n            w.0 = (((value_ms >> 32) & 0xFFFF) as u32) | POWMAN_PASSWORD;\n        });\n        powman.set_time_63to48().write(|w| {\n            w.0 = (((value_ms >> 48) & 0xFFFF) as u32) | POWMAN_PASSWORD;\n        });\n    }\n\n    /// Set an alarm for a specific counter value (in milliseconds)\n    ///","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-rp/src/aon_timer/mod.rs#L373-L409","documentation":"`AonTimer::set_counter` on RP2040/RP2350 writes the POWMAN time registers directly, which the hardware only permits while the always-on timer is halted. The driver guards this and panics if `is_running()` returns true. The doc comment explicitly requires stopping the timer first.","triggerScenarios":"Calling `set_counter(value_ms)` (directly or via `set_datetime`) while the always-on timer is still running, e.g. setting the RTC datetime right after boot without stopping the timer, or updating the clock during operation.","commonSituations":"Initializing the RTC to epoch time at startup before stopping the timer; synchronizing time from NTP while the timer ticks; calling `set_datetime` on an already-running timer in a time-update routine.","solutions":["Call `timer.stop()` (or the driver's stop method) before `set_counter`, then restart it afterwards","Route time updates through a helper that stops, sets, and restarts the timer atomically","Check `is_running()` before calling `set_counter` if the timer's state is uncertain at that call site"],"exampleFix":"// before\ntimer.set_counter(ms_since_epoch); // panics: timer running\n// after\ntimer.stop();\ntimer.set_counter(ms_since_epoch);\ntimer.start();\n","handlingStrategy":"validation","validationCode":"fn set_counter_safe(timer: &mut AonTimer, value_ms: u64) {\n    if timer.is_running() { timer.stop(); }\n    timer.set_counter(value_ms);\n    timer.start();\n}\n","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always stop the aon timer before set_counter/set_datetime","Wrap stop/set/start in one helper so ordering cannot drift","Call is_running() defensively before time updates"],"tags":["rust","embedded","rp2040","timer","rtc","state-error"],"backgroundTag":"invalid-state-transition","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}