1#![macro_use]
2
3use core::marker::PhantomData;
19use core::ptr::NonNull;
20
21use embassy_hal_internal::{impl_peripheral, Peri, PeripheralType};
22
23use crate::pac::common::{Reg, RW, W};
24use crate::peripherals;
25
26#[cfg_attr(feature = "_dppi", path = "dppi.rs")]
27#[cfg_attr(feature = "_ppi", path = "ppi.rs")]
28mod _version;
29pub(crate) use _version::*;
30
31pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> {
33 ch: Peri<'d, C>,
34 #[cfg(feature = "_dppi")]
35 events: [Event<'d>; EVENT_COUNT],
36 #[cfg(feature = "_dppi")]
37 tasks: [Task<'d>; TASK_COUNT],
38}
39
40pub struct PpiGroup<'d, G: Group> {
42 g: Peri<'d, G>,
43}
44
45impl<'d, G: Group> PpiGroup<'d, G> {
46 pub fn new(g: Peri<'d, G>) -> Self {
50 let r = regs();
51 let n = g.number();
52 r.chg(n).write(|_| ());
53
54 Self { g }
55 }
56
57 pub fn add_channel<C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize>(
61 &mut self,
62 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>,
63 ) {
64 let r = regs();
65 let ng = self.g.number();
66 let nc = ch.ch.number();
67 r.chg(ng).modify(|w| w.set_ch(nc, true));
68 }
69
70 pub fn remove_channel<C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize>(
74 &mut self,
75 ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>,
76 ) {
77 let r = regs();
78 let ng = self.g.number();
79 let nc = ch.ch.number();
80 r.chg(ng).modify(|w| w.set_ch(nc, false));
81 }
82
83 pub fn enable_all(&mut self) {
85 let n = self.g.number();
86 regs().tasks_chg(n).en().write_value(1);
87 }
88
89 pub fn disable_all(&mut self) {
91 let n = self.g.number();
92 regs().tasks_chg(n).dis().write_value(1);
93 }
94
95 pub fn task_enable_all(&self) -> Task<'d> {
99 let n = self.g.number();
100 Task::from_reg(regs().tasks_chg(n).en())
101 }
102
103 pub fn task_disable_all(&self) -> Task<'d> {
107 let n = self.g.number();
108 Task::from_reg(regs().tasks_chg(n).dis())
109 }
110}
111impl<G: Group> PpiGroup<'static, G> {
112 pub fn persist(self) {
116 core::mem::forget(self);
117 }
118}
119
120impl<'d, G: Group> Drop for PpiGroup<'d, G> {
121 fn drop(&mut self) {
122 let r = regs();
123 let n = self.g.number();
124 r.chg(n).write(|_| ());
125 }
126}
127
128#[cfg(feature = "_dppi")]
129const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::<u32>();
130
131#[derive(PartialEq, Eq, Clone, Copy)]
136pub struct Task<'d>(NonNull<u32>, PhantomData<&'d ()>);
137
138impl<'d> Task<'d> {
139 pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self {
145 Self(ptr, PhantomData)
146 }
147
148 pub fn trigger(&mut self) {
150 unsafe { self.0.as_ptr().write_volatile(1) };
151 }
152
153 pub(crate) fn from_reg(reg: Reg<u32, W>) -> Self {
154 Self(unsafe { NonNull::new_unchecked(reg.as_ptr()) }, PhantomData)
155 }
156
157 #[cfg(feature = "_dppi")]
159 pub fn subscribe_reg(&self) -> *mut u32 {
160 unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) }
161 }
162}
163
164unsafe impl Send for Task<'_> {}
168
169#[derive(PartialEq, Eq, Clone, Copy)]
173pub struct Event<'d>(NonNull<u32>, PhantomData<&'d ()>);
174
175impl<'d> Event<'d> {
176 pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self {
182 Self(ptr, PhantomData)
183 }
184
185 pub(crate) fn from_reg(reg: Reg<u32, RW>) -> Self {
186 Self(unsafe { NonNull::new_unchecked(reg.as_ptr()) }, PhantomData)
187 }
188
189 pub fn is_triggered(&self) -> bool {
191 unsafe { self.0.as_ptr().read_volatile() == 1 }
192 }
193
194 pub fn clear(&mut self) {
196 unsafe { self.0.as_ptr().write_volatile(0) };
197 }
198
199 #[cfg(feature = "_dppi")]
201 pub fn publish_reg(&self) -> *mut u32 {
202 unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) }
203 }
204}
205
206unsafe impl Send for Event<'_> {}
210
211pub(crate) trait SealedChannel {}
215pub(crate) trait SealedGroup {}
216
217#[allow(private_bounds)]
219pub trait Channel: SealedChannel + PeripheralType + Sized + 'static {
220 fn number(&self) -> usize;
222}
223
224pub trait ConfigurableChannel: Channel + Into<AnyConfigurableChannel> {}
226
227pub trait StaticChannel: Channel + Into<AnyStaticChannel> {}
229
230#[allow(private_bounds)]
232pub trait Group: SealedGroup + PeripheralType + Into<AnyGroup> + Sized + 'static {
233 fn number(&self) -> usize;
235}
236
237pub struct AnyStaticChannel {
243 pub(crate) number: u8,
244}
245impl_peripheral!(AnyStaticChannel);
246impl SealedChannel for AnyStaticChannel {}
247impl Channel for AnyStaticChannel {
248 fn number(&self) -> usize {
249 self.number as usize
250 }
251}
252impl StaticChannel for AnyStaticChannel {}
253
254pub struct AnyConfigurableChannel {
257 pub(crate) number: u8,
258}
259impl_peripheral!(AnyConfigurableChannel);
260impl SealedChannel for AnyConfigurableChannel {}
261impl Channel for AnyConfigurableChannel {
262 fn number(&self) -> usize {
263 self.number as usize
264 }
265}
266impl ConfigurableChannel for AnyConfigurableChannel {}
267
268#[cfg(not(feature = "_nrf51"))]
269macro_rules! impl_ppi_channel {
270 ($type:ident, $number:expr) => {
271 impl crate::ppi::SealedChannel for peripherals::$type {}
272 impl crate::ppi::Channel for peripherals::$type {
273 fn number(&self) -> usize {
274 $number
275 }
276 }
277 };
278 ($type:ident, $number:expr => static) => {
279 impl_ppi_channel!($type, $number);
280 impl crate::ppi::StaticChannel for peripherals::$type {}
281 impl From<peripherals::$type> for crate::ppi::AnyStaticChannel {
282 fn from(val: peripherals::$type) -> Self {
283 Self {
284 number: crate::ppi::Channel::number(&val) as u8,
285 }
286 }
287 }
288 };
289 ($type:ident, $number:expr => configurable) => {
290 impl_ppi_channel!($type, $number);
291 impl crate::ppi::ConfigurableChannel for peripherals::$type {}
292 impl From<peripherals::$type> for crate::ppi::AnyConfigurableChannel {
293 fn from(val: peripherals::$type) -> Self {
294 Self {
295 number: crate::ppi::Channel::number(&val) as u8,
296 }
297 }
298 }
299 };
300}
301
302pub struct AnyGroup {
307 number: u8,
308}
309impl_peripheral!(AnyGroup);
310impl SealedGroup for AnyGroup {}
311impl Group for AnyGroup {
312 fn number(&self) -> usize {
313 self.number as usize
314 }
315}
316
317macro_rules! impl_group {
318 ($type:ident, $number:expr) => {
319 impl SealedGroup for peripherals::$type {}
320 impl Group for peripherals::$type {
321 fn number(&self) -> usize {
322 $number
323 }
324 }
325
326 impl From<peripherals::$type> for crate::ppi::AnyGroup {
327 fn from(val: peripherals::$type) -> Self {
328 Self {
329 number: crate::ppi::Group::number(&val) as u8,
330 }
331 }
332 }
333 };
334}
335
336impl_group!(PPI_GROUP0, 0);
337impl_group!(PPI_GROUP1, 1);
338impl_group!(PPI_GROUP2, 2);
339impl_group!(PPI_GROUP3, 3);
340#[cfg(not(feature = "_nrf51"))]
341impl_group!(PPI_GROUP4, 4);
342#[cfg(not(feature = "_nrf51"))]
343impl_group!(PPI_GROUP5, 5);