Skip to content

Commit 04836dd

Browse files
Fix Pwm::set_output_pin soundness, add swap_output_pin
1 parent 22015fc commit 04836dd

File tree

4 files changed

+36
-17
lines changed

4 files changed

+36
-17
lines changed

examples/pwm-blinky-demo/src/main.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33

44
use hal::{gpio, prelude::*, pwm, pwm::Pwm, timer, timer::Timer};
55
use nb::block;
6-
#[cfg(feature = "52840")]
7-
use nrf52840_hal as hal;
86
#[cfg(feature = "52832")]
97
use nrf52832_hal as hal;
8+
#[cfg(feature = "52840")]
9+
use nrf52840_hal as hal;
1010
#[cfg(feature = "9160")]
1111
use nrf9160_hal as hal;
1212
use rtt_target::{rprintln, rtt_init_print};
@@ -29,7 +29,7 @@ fn main() -> ! {
2929
pwm.set_period(500u32.hz());
3030

3131
rprintln!("PWM Blinky demo starting");
32-
32+
3333
let wait_time = 1_000_000u32 / pwm.get_max_duty() as u32;
3434
loop {
3535
for duty in 0..pwm.get_max_duty() {
@@ -46,7 +46,7 @@ fn init_device(p: hal::pac::Peripherals) -> (Pwm<hal::pac::PWM0_NS>, Timer<hal::
4646
let pwm = Pwm::new(p.PWM0_NS);
4747
pwm.set_output_pin(
4848
pwm::Channel::C0,
49-
&p0.p0_02.into_push_pull_output(gpio::Level::High).degrade(),
49+
p0.p0_02.into_push_pull_output(gpio::Level::High).degrade(),
5050
);
5151

5252
let timer = Timer::new(p.TIMER0_NS);
@@ -61,7 +61,7 @@ fn init_device(p: hal::pac::Peripherals) -> (Pwm<hal::pac::PWM0>, Timer<hal::pac
6161
let pwm = Pwm::new(p.PWM0);
6262
pwm.set_output_pin(
6363
pwm::Channel::C0,
64-
&p0.p0_13.into_push_pull_output(gpio::Level::High).degrade(),
64+
p0.p0_13.into_push_pull_output(gpio::Level::High).degrade(),
6565
);
6666

6767
let timer = Timer::new(p.TIMER0);
@@ -76,15 +76,14 @@ fn init_device(p: hal::pac::Peripherals) -> (Pwm<hal::pac::PWM0>, Timer<hal::pac
7676
let pwm = Pwm::new(p.PWM0);
7777
pwm.set_output_pin(
7878
pwm::Channel::C0,
79-
&p0.p0_30.into_push_pull_output(gpio::Level::High).degrade(),
79+
p0.p0_30.into_push_pull_output(gpio::Level::High).degrade(),
8080
);
8181

8282
let timer = Timer::new(p.TIMER0);
8383

8484
(pwm, timer)
8585
}
8686

87-
8887
fn delay<T>(timer: &mut Timer<T>, cycles: u32)
8988
where
9089
T: timer::Instance,

examples/pwm-demo/src/main.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ const APP: () = {
6969

7070
let pwm = Pwm::new(ctx.device.PWM0);
7171
pwm.set_period(500u32.hz())
72-
.set_output_pin(Channel::C0, &led1)
73-
.set_output_pin(Channel::C1, &led2)
74-
.set_output_pin(Channel::C2, &led3)
75-
.set_output_pin(Channel::C3, &led4)
72+
.set_output_pin(Channel::C0, led1)
73+
.set_output_pin(Channel::C1, led2)
74+
.set_output_pin(Channel::C2, led3)
75+
.set_output_pin(Channel::C3, led4)
7676
.enable_interrupt(PwmEvent::Stopped)
7777
.enable();
7878

nrf-hal-common/src/gpio.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ pub enum Port {
5050
// ===============================================================
5151
/// Generic $PX pin
5252
pub struct Pin<MODE> {
53-
// Bit 7: Port, Bits 0-6: Pin
53+
/// 00AB BBBB
54+
/// A: Port
55+
/// B: Pin
5456
pin_port: u8,
5557
_mode: PhantomData<MODE>,
5658
}

nrf-hal-common/src/pwm.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,16 +129,34 @@ where
129129
}
130130
}
131131

132-
/// Sets the associated output pin for the PWM channel and enables it.
132+
/// Sets the associated output pin for the PWM channel.
133133
#[inline(always)]
134-
pub fn set_output_pin(&self, channel: Channel, pin: &Pin<Output<PushPull>>) -> &Self {
134+
pub fn set_output_pin(&self, channel: Channel, pin: Pin<Output<PushPull>>) -> &Self {
135135
self.pwm.psel.out[usize::from(channel)].write(|w| {
136136
unsafe { w.bits(pin.psel_bits()) };
137137
w.connect().connected()
138138
});
139139
self
140140
}
141141

142+
/// Sets the output pin of `channel`, and returns the old pin (if any).
143+
pub fn swap_output_pin(
144+
&mut self,
145+
channel: Channel,
146+
pin: Pin<Output<PushPull>>,
147+
) -> Option<Pin<Output<PushPull>>> {
148+
// (needs `&mut self` because it reads, then writes, to the register)
149+
let psel = &self.pwm.psel.out[usize::from(channel)];
150+
let old = psel.read();
151+
let old = if old.connect().is_connected() {
152+
unsafe { Some(Pin::from_psel_bits(old.bits())) }
153+
} else {
154+
None
155+
};
156+
self.set_output_pin(channel, pin);
157+
old
158+
}
159+
142160
/// Enables the PWM generator.
143161
#[inline(always)]
144162
pub fn enable(&self) {
@@ -228,7 +246,7 @@ where
228246
self
229247
}
230248

231-
/// Returns selected operating mode of the wave counter.
249+
/// Returns selected operating mode of the wave counter.
232250
#[inline(always)]
233251
pub fn counter_mode(&self) -> CounterMode {
234252
match self.pwm.mode.read().updown().bit() {
@@ -351,7 +369,7 @@ where
351369
self.start_seq(Seq::Seq0);
352370
}
353371

354-
/// Returns duty cycle value for a PWM group.
372+
/// Returns duty cycle value for a PWM group.
355373
#[inline(always)]
356374
pub fn duty_on_group(&self, group: Group) -> u16 {
357375
self.duty_on_value(usize::from(group))
@@ -395,7 +413,7 @@ where
395413
self.start_seq(Seq::Seq0);
396414
}
397415

398-
/// Returns the duty cycle value for a PWM channel.
416+
/// Returns the duty cycle value for a PWM channel.
399417
#[inline(always)]
400418
pub fn duty_on(&self, channel: Channel) -> u16 {
401419
self.duty_on_value(usize::from(channel))

0 commit comments

Comments
 (0)