diff options
| -rw-r--r-- | embassy-nrf/src/pwm.rs | 51 |
1 files changed, 20 insertions, 31 deletions
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index 6387cd997..077a27cd0 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::cell::UnsafeCell; | ||
| 4 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 5 | use core::sync::atomic::{compiler_fence, Ordering}; | 4 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 6 | use embassy::util::Unborrow; | 5 | use embassy::util::Unborrow; |
| @@ -15,6 +14,7 @@ use crate::util::slice_in_ram_or; | |||
| 15 | /// Interface to the PWM peripheral | 14 | /// Interface to the PWM peripheral |
| 16 | pub struct SimplePwm<'d, T: Instance> { | 15 | pub struct SimplePwm<'d, T: Instance> { |
| 17 | phantom: PhantomData<&'d mut T>, | 16 | phantom: PhantomData<&'d mut T>, |
| 17 | duty: [u16; 4], | ||
| 18 | ch0: Option<AnyPin>, | 18 | ch0: Option<AnyPin>, |
| 19 | ch1: Option<AnyPin>, | 19 | ch1: Option<AnyPin>, |
| 20 | ch2: Option<AnyPin>, | 20 | ch2: Option<AnyPin>, |
| @@ -336,7 +336,6 @@ impl<'d, T: Instance> SimplePwm<'d, T> { | |||
| 336 | unborrow!(ch0, ch1, ch2, ch3); | 336 | unborrow!(ch0, ch1, ch2, ch3); |
| 337 | 337 | ||
| 338 | let r = T::regs(); | 338 | let r = T::regs(); |
| 339 | let s = T::state(); | ||
| 340 | 339 | ||
| 341 | if let Some(pin) = ch0.pin_mut() { | 340 | if let Some(pin) = ch0.pin_mut() { |
| 342 | pin.set_low(); | 341 | pin.set_low(); |
| @@ -362,6 +361,15 @@ impl<'d, T: Instance> SimplePwm<'d, T> { | |||
| 362 | r.psel.out[2].write(|w| unsafe { w.bits(ch2.psel_bits()) }); | 361 | r.psel.out[2].write(|w| unsafe { w.bits(ch2.psel_bits()) }); |
| 363 | r.psel.out[3].write(|w| unsafe { w.bits(ch3.psel_bits()) }); | 362 | r.psel.out[3].write(|w| unsafe { w.bits(ch3.psel_bits()) }); |
| 364 | 363 | ||
| 364 | let pwm = Self { | ||
| 365 | phantom: PhantomData, | ||
| 366 | ch0: ch0.degrade_optional(), | ||
| 367 | ch1: ch1.degrade_optional(), | ||
| 368 | ch2: ch2.degrade_optional(), | ||
| 369 | ch3: ch3.degrade_optional(), | ||
| 370 | duty: [0; 4], | ||
| 371 | }; | ||
| 372 | |||
| 365 | // Disable all interrupts | 373 | // Disable all interrupts |
| 366 | r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); | 374 | r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); |
| 367 | r.shorts.reset(); | 375 | r.shorts.reset(); |
| @@ -371,7 +379,8 @@ impl<'d, T: Instance> SimplePwm<'d, T> { | |||
| 371 | 379 | ||
| 372 | r.seq0 | 380 | r.seq0 |
| 373 | .ptr | 381 | .ptr |
| 374 | .write(|w| unsafe { w.bits(&s.duty as *const _ as u32) }); | 382 | .write(|w| unsafe { w.bits(&pwm.duty as *const _ as u32) }); |
| 383 | |||
| 375 | r.seq0.cnt.write(|w| unsafe { w.bits(4) }); | 384 | r.seq0.cnt.write(|w| unsafe { w.bits(4) }); |
| 376 | r.seq0.refresh.write(|w| unsafe { w.bits(0) }); | 385 | r.seq0.refresh.write(|w| unsafe { w.bits(0) }); |
| 377 | r.seq0.enddelay.write(|w| unsafe { w.bits(0) }); | 386 | r.seq0.enddelay.write(|w| unsafe { w.bits(0) }); |
| @@ -385,13 +394,7 @@ impl<'d, T: Instance> SimplePwm<'d, T> { | |||
| 385 | r.countertop.write(|w| unsafe { w.countertop().bits(1000) }); | 394 | r.countertop.write(|w| unsafe { w.countertop().bits(1000) }); |
| 386 | r.loop_.write(|w| w.cnt().disabled()); | 395 | r.loop_.write(|w| w.cnt().disabled()); |
| 387 | 396 | ||
| 388 | Self { | 397 | pwm |
| 389 | phantom: PhantomData, | ||
| 390 | ch0: ch0.degrade_optional(), | ||
| 391 | ch1: ch1.degrade_optional(), | ||
| 392 | ch2: ch2.degrade_optional(), | ||
| 393 | ch3: ch3.degrade_optional(), | ||
| 394 | } | ||
| 395 | } | 398 | } |
| 396 | 399 | ||
| 397 | /// Stop playback | 400 | /// Stop playback |
| @@ -420,10 +423,14 @@ impl<'d, T: Instance> SimplePwm<'d, T> { | |||
| 420 | } | 423 | } |
| 421 | 424 | ||
| 422 | /// Sets duty cycle (15 bit) for a PWM channel. | 425 | /// Sets duty cycle (15 bit) for a PWM channel. |
| 423 | pub fn set_duty(&self, channel: usize, duty: u16) { | 426 | pub fn set_duty(&mut self, channel: usize, duty: u16) { |
| 424 | let r = T::regs(); | 427 | let r = T::regs(); |
| 425 | let s = T::state(); | 428 | |
| 426 | unsafe { (*s.duty.get())[channel] = duty & 0x7FFF }; | 429 | self.duty[channel] = duty & 0x7FFF; |
| 430 | |||
| 431 | r.seq0 | ||
| 432 | .ptr | ||
| 433 | .write(|w| unsafe { w.bits(&self.duty as *const _ as u32) }); | ||
| 427 | 434 | ||
| 428 | // todo justify? should i fence elsehwere we task start? or | 435 | // todo justify? should i fence elsehwere we task start? or |
| 429 | compiler_fence(Ordering::SeqCst); | 436 | compiler_fence(Ordering::SeqCst); |
| @@ -514,22 +521,8 @@ impl<'a, T: Instance> Drop for SimplePwm<'a, T> { | |||
| 514 | pub(crate) mod sealed { | 521 | pub(crate) mod sealed { |
| 515 | use super::*; | 522 | use super::*; |
| 516 | 523 | ||
| 517 | pub struct State { | ||
| 518 | pub duty: UnsafeCell<[u16; 4]>, | ||
| 519 | } | ||
| 520 | unsafe impl Sync for State {} | ||
| 521 | |||
| 522 | impl State { | ||
| 523 | pub const fn new() -> Self { | ||
| 524 | Self { | ||
| 525 | duty: UnsafeCell::new([0; 4]), | ||
| 526 | } | ||
| 527 | } | ||
| 528 | } | ||
| 529 | |||
| 530 | pub trait Instance { | 524 | pub trait Instance { |
| 531 | fn regs() -> &'static pac::pwm0::RegisterBlock; | 525 | fn regs() -> &'static pac::pwm0::RegisterBlock; |
| 532 | fn state() -> &'static State; | ||
| 533 | } | 526 | } |
| 534 | } | 527 | } |
| 535 | 528 | ||
| @@ -543,10 +536,6 @@ macro_rules! impl_pwm { | |||
| 543 | fn regs() -> &'static pac::pwm0::RegisterBlock { | 536 | fn regs() -> &'static pac::pwm0::RegisterBlock { |
| 544 | unsafe { &*pac::$pac_type::ptr() } | 537 | unsafe { &*pac::$pac_type::ptr() } |
| 545 | } | 538 | } |
| 546 | fn state() -> &'static crate::pwm::sealed::State { | ||
| 547 | static STATE: crate::pwm::sealed::State = crate::pwm::sealed::State::new(); | ||
| 548 | &STATE | ||
| 549 | } | ||
| 550 | } | 539 | } |
| 551 | impl crate::pwm::Instance for peripherals::$type { | 540 | impl crate::pwm::Instance for peripherals::$type { |
| 552 | type Interrupt = crate::interrupt::$irq; | 541 | type Interrupt = crate::interrupt::$irq; |
