{"record":{"id":"5c5a4978af97c70d","repo":"embassy-rs/embassy","slug":"psc-division-overflow","errorCode":null,"errorMessage":"psc division overflow: {}","messagePattern":"psc division overflow: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-stm32/src/time_driver/tim.rs","lineNumber":159,"sourceCode":"    queue: Mutex::new(RefCell::new(Queue::new()))\n});\n\nimpl RtcDriver {\n    /// initialize the timer, but don't start it.  Used for chips like stm32wle5\n    /// for low power where the timer config is lost in STOP2.\n    pub(crate) fn init_timer(&'static self, cs: critical_section::CriticalSection) {\n        let r = regs_gp16();\n\n        rcc::enable_and_reset_with_cs_no_refcount::<T>(cs);\n\n        let timer_freq = T::frequency();\n\n        r.cr1().modify(|w| w.set_cen(false));\n        write_cnt(0);\n\n        let psc = timer_freq.0 / TICK_HZ as u32 - 1;\n        let psc: u16 = match psc.try_into() {\n            Err(_) => panic!(\"psc division overflow: {}\", psc),\n            Ok(n) => n,\n        };\n\n        r.psc().write_value(psc);\n        write_arr(Counter::MAX);\n\n        // Set URS, generate update and clear URS\n        r.cr1().modify(|w| w.set_urs(vals::Urs::CounterOnly));\n        r.egr().write(|w| w.set_ug(true));\n        r.cr1().modify(|w| w.set_urs(vals::Urs::AnyEvent));\n\n        // Mid-way point\n        write_ccr(0, HALF_COUNTER);\n\n        // Enable overflow and half-overflow interrupts\n        r.dier().write(|w| {\n            w.set_uie(true);\n            w.set_ccie(0, true);","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-stm32/src/time_driver/tim.rs#L141-L177","documentation":"The TIM-based time driver computes psc = timer_freq/TICK_HZ - 1 and stores it in the 16-bit PSC register. If the computed value doesn't fit in u16 (timer clock too fast relative to TICK_HZ, or TICK_HZ = 0 causing underflow/overflow), init_timer panics.","triggerScenarios":"timer_freq / TICK_HZ - 1 > 65535 (e.g. very high timer clock with very low TICK_HZ), or TICK_HZ of 0 making the subtraction underflow on u32.","commonSituations":"Setting an extremely low TICK_HZ with a high-speed timer clock; typo making TICK_HZ 0; running a 480 MHz timer clock with 1 Hz ticks.","solutions":["Increase TICK_HZ so timer_freq/TICK_HZ - 1 fits in a u16 (≤ 65536 division).","Lower the timer input clock via RCC prescalers if you need a very coarse tick.","Fix TICK_HZ so it is nonzero and sensible (typically 1000)."],"exampleFix":"// before (timer_freq = 500 MHz, TICK_HZ = 1000 -> psc = 499999, > u16::MAX)\ntick_hz = 1000\n// after (enable APB prescaler so timer_freq = 64 MHz, psc = 63999 fits u16)\n// or choose tick_hz such that timer_freq/tick_hz <= 65536","handlingStrategy":"validation","validationCode":"fn psc_fits(timer_freq: u32, tick_hz: u32) -> bool {\n    tick_hz > 0 && (timer_freq / tick_hz).saturating_sub(1) <= u16::MAX as u32\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep timer_freq / TICK_HZ - 1 within 0..=65535.","Never set TICK_HZ to 0; define it via a checked constant.","If you need coarse ticks, slow the timer clock with RCC prescalers instead of huge PSC values."],"tags":["tim","time-driver","embedded","panic","overflow"],"backgroundTag":"value-out-of-range","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"}