{"record":{"id":"753efc255f9f90b6","repo":"embassy-rs/embassy","slug":"event-is-already-in-use","errorCode":null,"errorMessage":"Event is already in use","messagePattern":"Event is already in use","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-nrf/src/ppi/dppi.rs","lineNumber":40,"sourceCode":"        Ppi::new_many_to_many(ch, [event], [task1, task2])\n    }\n}\n\nimpl<'d, C: ConfigurableChannel, const EVENT_COUNT: usize, const TASK_COUNT: usize>\n    Ppi<'d, C, EVENT_COUNT, TASK_COUNT>\n{\n    /// Configure a DPPI channel to trigger all `tasks` when any of the `events` fires.\n    pub fn new_many_to_many(ch: Peri<'d, C>, events: [Event<'d>; EVENT_COUNT], tasks: [Task<'d>; TASK_COUNT]) -> Self {\n        let val = DPPI_ENABLE_BIT | (ch.number() as u32 & DPPI_CHANNEL_MASK);\n        for task in tasks {\n            if unsafe { task.subscribe_reg().read_volatile() } != 0 {\n                panic!(\"Task is already in use\");\n            }\n            unsafe { task.subscribe_reg().write_volatile(val) }\n        }\n        for event in events {\n            if unsafe { event.publish_reg().read_volatile() } != 0 {\n                panic!(\"Event is already in use\");\n            }\n            unsafe { event.publish_reg().write_volatile(val) }\n        }\n\n        Self { ch, events, tasks }\n    }\n}\n\nimpl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> Ppi<'d, C, EVENT_COUNT, TASK_COUNT> {\n    /// Enables the channel.\n    pub fn enable(&mut self) {\n        let n = self.ch.number();\n        self.ch.regs().chenset().write(|w| w.0 = 1 << n);\n    }\n\n    /// Disables the channel.\n    pub fn disable(&mut self) {\n        let n = self.ch.number();","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-nrf/src/ppi/dppi.rs#L22-L58","documentation":"new_many_to_many panics when an event's PUBLISH register already holds a non-zero value, meaning another PPI/DPPI channel already publishes that event. This prevents silently rewiring hardware event routing. The driver volatile-reads the PUBLISH register before writing the new channel configuration.","triggerScenarios":"Calling dppi::ManyToMany::new_many_to_many(ch, events, tasks) with an Event whose PUBLISH register is non-zero — e.g. the event was already published by a previously created channel (new_one_to_one/new_many_to_many) or written manually, and that channel has not been disabled or dropped.","commonSituations":"Two radio peripherals (e.g. TIMER compare and radio READY) feeding two different channels; routing the same GPIOTE event to multiple sink tasks through separate channels; re-running initialization code after a state reset without clearing PUBLISH registers.","solutions":["Drop or disable the existing PPI channel that publishes the same event before creating the new one.","Check for duplicate events in the events array and across existing channel configurations.","If one event must trigger multiple tasks, list multiple tasks on a single channel instead of creating parallel channels for the same event.","After a soft reset, explicitly clear PUBLISH registers before reconfiguration."],"exampleFix":"// before\nlet c1 = ManyToMany::new_many_to_many(p.PPI_CH0, [event], [task_a]);\nlet c2 = ManyToMany::new_many_to_many(p.PPI_CH1, [event], [task_b]); // panics\n// after\nlet c1 = ManyToMany::new_many_to_many(p.PPI_CH0, [event], [task_a, task_b]);","handlingStrategy":"validation","validationCode":"// Check the event's PUBLISH register before configuring a channel.\nlet pub_reg = event.publish_reg().read_volatile();\nif pub_reg != 0 {\n    // event already published by another channel\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Design event routing so each event belongs to exactly one channel; fan out via multiple tasks on one channel.","Centralize PPI setup in a single initialization function.","Clear PUBLISH/SUBSCRIBE registers after soft resets before re-init."],"tags":["embedded","nrf","ppi","hardware-conflict","panic"],"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"}