embassy-rs/embassy · error
Cannot get CC register
Error message
Cannot get CC register {} of timer with {} CC registers. What it means
Timer::cc panics when asked for a CC (capture/compare) register index n that is greater than or equal to the number of CC registers the timer instance actually has — 4 for a normal timer, 6 for an extended timer (e.g. TIMER0 on some SoCs). This guards against out-of-bounds register access on hardware.
Solutions
- Use the timer's actual channel count — iterate with 0..timer.cc_count() (or the ccs value) instead of a hardcoded bound.
- Assign the code needing 6 CC channels to an extended timer instance (e.g. one with 6 CC registers on your SoC).
- Check the embassy-nrf timer bindings for your chip to confirm which instances are extended before indexing.
Example fix
// before
for i in 0..6 {
let cc = timer.cc(i); // panics on 4-CC timers
}
// after
let ccs = timer.cc_count();
for i in 0..ccs {
let cc = timer.cc(i);
} Defensive patterns
Strategy: validation
Validate before calling
let ccs: usize = timer.cc_count();
if n < ccs {
let cc = timer.cc(n);
} Type guard
fn has_cc(timer: &Timer<'_, T>, n: usize) -> bool { n < timer.cc_count() } Prevention
- Never hardcode CC indices; derive loop bounds from the timer's channel count.
- Only use CC channels 4-5 on timer instances that are extended (6 CC registers).
- Check your SoC's embassy-nrf peripheral bindings to know which timers are extended.
When it happens
Trigger: Calling timer.cc(n) with n >= self.ccs, e.g. timer.cc(4) on a 4-channel timer, or looping 0..6 over every timer instance instead of only extended ones; also occurs when code assuming extended-timer behavior runs against a normal timer peripheral.
Common situations: Shared timer-driver code written for an extended timer reused with a plain TIMER instance; hardcoding cc(5) or cc(4); iterating a fixed count of CC channels for PWM capture/compare setup on multiple timers.
Related errors
- Bad 802.15.4 channel
- Boot prepare error
- Consecutive read operations are not supported!
- Could not find any timer
- Event is already in use
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/d14808b46e1141d1.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-nrf/src/timer.rs:225
/// This will stop the timer if it isn't already stopped,
/// because the timer may exhibit 'unpredictable behaviour' if it's frequency is changed while it's running.
pub fn set_frequency(&self, frequency: Frequency) {
self.stop();
self.r
.prescaler()
// SAFETY: `frequency` is a variant of `Frequency`,
// whose values are all in the range of 0-9 (the valid range of `prescaler`).
.write(|w| w.set_prescaler(frequency as u8))
}
/// Returns this timer's `n`th CC register.
///
/// # Panics
/// Panics if `n` >= the number of CC registers this timer has (4 for a normal timer, 6 for an extended timer).
pub fn cc(&self, n: usize) -> Cc<'d> {
if n >= self.ccs {
panic!("Cannot get CC register {} of timer with {} CC registers.", n, self.ccs);
}
Cc {
n,
r: self.r,
_p: PhantomData,
}
}
}
impl Timer<'static> {
/// Persist the timer's configuration for the rest of the program's lifetime. This method
/// should be preferred over [`core::mem::forget()`] because the `'static` bound prevents
/// accidental reuse of the underlying peripheral.
pub fn persist(self) {
core::mem::forget(self);
}
}
View on GitHub (pinned to 463a07b963)