aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/pwm.rs51
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
3use core::cell::UnsafeCell;
4use core::marker::PhantomData; 3use core::marker::PhantomData;
5use core::sync::atomic::{compiler_fence, Ordering}; 4use core::sync::atomic::{compiler_fence, Ordering};
6use embassy::util::Unborrow; 5use 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
16pub struct SimplePwm<'d, T: Instance> { 15pub 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> {
514pub(crate) mod sealed { 521pub(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;