embassy-rs/embassy · error
take called more than once!
Error message
take called more than once!
What it means
This panic is in the `impl_peri_interpolators`-style `take_with_cs` glue generated by a macro in embassy-rp's interpolator module. Each interpolator peripheral tracks a per-core `[bool; 2]` flag; if `take`/`take_with_cs` is called twice for the same peripheral on the same core, it panics to enforce single ownership of the hardware block.
Solutions
- Ensure `take`/`take_with_cs` for each interpolator is called exactly once per core; store the returned Peri and reuse it
- Pass the already-taken interpolator handle into second consumers instead of stealing again
- If ownership must move between tasks, structure code so the Peri is passed along rather than re-taken
Example fix
// before let interp1 = Interp::<0, 0>::take(); let interp1b = Interp::<0, 0>::take(); // panics // after let interp1 = Interp::<0, 0>::take(); use_interp(&interp1); use_interp(&interp1); // reuse the same handle
Defensive patterns
Strategy: type-guard
Validate before calling
static TAKEN: AtomicBool = AtomicBool::new(false);
if TAKEN.swap(true, Ordering::SeqCst) { /* skip re-take */ } Type guard
fn already_taken(flag: &[bool; 2], core: usize) -> bool { flag[core] } Prevention
- Call peripheral take() once during init and store the handle statically
- Avoid re-running init code paths on retry
- Pass Peri handles by reference instead of re-taking
When it happens
Trigger: Calling the interpolator's `take()` (or take_with_cs) more than once for the same interpolator instance on the same core — e.g. constructing two interpolator wrapper objects from the same static, or re-running init code after it already succeeded.
Common situations: Retry logic that re-runs peripheral setup, shared helper functions called from multiple places, or test harnesses initializing the same interpolator repeatedly on core0/core1.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- Can only take the executor once
- Invalid FilterConfig (TooManyFilters)! A FilterConfig must…
- Invalid FilterConfig (EmptyFilterConfig)! A FilterConfig…
- Clocks have not been initialized
- Clocks initialized, but clk_16k_vsys not active
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/3edc149056e7e647.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-rp/src/interpolator.rs:140
/// Interpolator peripheral type.
#[derive(Copy, Clone)]
pub struct $interp {
not_send: PhantomData<*const ()>,
}
impl $interp {
///Returns the peripheral *once* for each core. Panics if called more than once per core.
pub fn take() -> $crate::Peri<'static, Self> {
critical_section::with(Self::take_with_cs)
}
fn take_with_cs(_cs: critical_section::CriticalSection) -> $crate::Peri<'static, Self> {
#[unsafe(no_mangle)]
static mut $static: [bool; 2] = [false, false];
unsafe {
if $static[current_core()] {
panic!("take called more than once!");
}
$static[current_core()] = true;
Self::steal()
}
}
/// Unsafely create an instance of this peripheral out of thin air.
///
/// # Safety
///
/// You must ensure that you're only using one instance of this type at a time.
#[inline]
pub unsafe fn steal() -> $crate::Peri<'static, Self> {
$crate::Peri::new_unchecked(Self {
not_send: PhantomData,
})
}View on GitHub (pinned to 463a07b963)