Skip to content

Commit

Permalink
Merge #318 #319
Browse files Browse the repository at this point in the history
318: Enable PWM for nrf52832 r=jonathanpallant a=Dirbaio

It compiles cleanly, except for the PAC missing fields for the tasks registers. Replaced those with `.bits(1)`, which works on all chips.

Untested on hardware as I don't have a nrf52832 at hand.

319: Apply the UARTE workaround for nrf91 and nrf53 r=Dirbaio a=jonathanpallant

See ttps://github.com/NordicSemiconductor/nrfx/blob/master/drivers/src/nrfx_uarte.c#L197

Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Co-authored-by: Jonathan Pallant (42 Technology) <jonathan.pallant@42technology.com>
  • Loading branch information
3 people authored May 14, 2021
3 parents ed5d87d + d044dad + 60a3c09 commit 39c0b8f
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 69 deletions.
6 changes: 6 additions & 0 deletions examples/pwm-blinky-demo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ features = ["rt"]
path = "../../nrf9160-hal"
optional = true

[dependencies.nrf52832-hal]
features = ["rt"]
path = "../../nrf52832-hal"
optional = true

[dependencies.nrf52840-hal]
features = ["rt"]
path = "../../nrf52840-hal"
Expand All @@ -29,3 +34,4 @@ optional = true
[features]
9160 = ["nrf9160-hal"]
52840 = ["nrf52840-hal"]
52832 = ["nrf52832-hal"]
28 changes: 24 additions & 4 deletions examples/pwm-blinky-demo/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use hal::{gpio, prelude::*, pwm, pwm::Pwm, timer, timer::Timer};
use nb::block;
#[cfg(feature = "52840")]
use nrf52840_hal as hal;
#[cfg(feature = "52832")]
use nrf52832_hal as hal;
#[cfg(feature = "9160")]
use nrf9160_hal as hal;
use rtt_target::{rprintln, rtt_init_print};
Expand All @@ -27,11 +29,13 @@ fn main() -> ! {
pwm.set_period(500u32.hz());

rprintln!("PWM Blinky demo starting");

let wait_time = 1_000_000u32 / pwm.get_max_duty() as u32;
loop {
pwm.set_duty_on_common(pwm.get_max_duty());
delay(&mut timer, 250_000); // 250ms
pwm.set_duty_on_common(0);
delay(&mut timer, 1_000_000); // 1s
for duty in 0..pwm.get_max_duty() {
pwm.set_duty_on_common(duty);
delay(&mut timer, wait_time);
}
}
}

Expand Down Expand Up @@ -65,6 +69,22 @@ fn init_device(p: hal::pac::Peripherals) -> (Pwm<hal::pac::PWM0>, Timer<hal::pac
(pwm, timer)
}

#[cfg(feature = "52832")]
fn init_device(p: hal::pac::Peripherals) -> (Pwm<hal::pac::PWM0>, Timer<hal::pac::TIMER0>) {
let p0 = gpio::p0::Parts::new(p.P0);

let pwm = Pwm::new(p.PWM0);
pwm.set_output_pin(
pwm::Channel::C0,
&p0.p0_30.into_push_pull_output(gpio::Level::High).degrade(),
);

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

(pwm, timer)
}


fn delay<T>(timer: &mut Timer<T>, cycles: u32)
where
T: timer::Instance,
Expand Down
2 changes: 1 addition & 1 deletion nrf-hal-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub mod ieee802154;
pub mod lpcomp;
#[cfg(not(feature = "9160"))]
pub mod ppi;
#[cfg(not(any(feature = "51", feature = "52832")))]
#[cfg(not(feature = "51"))]
pub mod pwm;
#[cfg(not(any(feature = "51", feature = "9160")))]
pub mod qdec;
Expand Down
96 changes: 51 additions & 45 deletions nrf-hal-common/src/pwm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,9 @@
//! The pulse with modulation (PWM) module enables the generation of pulse width modulated signals on GPIO.

#[cfg(not(any(feature = "9160")))]
use crate::pac::{
pwm0::*, PWM0,
};
use crate::pac::pwm0::*;
#[cfg(any(feature = "9160"))]
use crate::pac::{
pwm0_ns::*, PWM0_NS, PWM1_NS, PWM2_NS, PWM3_NS,
};
#[cfg(not(any(feature = "52810", feature = "52811", feature = "9160")))]
use crate::pac::{
PWM1, PWM2, PWM3,
};
use crate::pac::pwm0_ns::*;
use crate::{
gpio::{Output, Pin, PushPull},
pac::{generic::Reg, Interrupt},
Expand Down Expand Up @@ -379,9 +371,12 @@ where
T::buffer().set(buffer);
self.one_shot();
self.set_load_mode(LoadMode::Individual);
self.pwm.seq0.ptr.write(|w| unsafe { w.bits(T::buffer().as_ptr() as u32) });
self.pwm
.seq0
.ptr
.write(|w| unsafe { w.bits(T::buffer().as_ptr() as u32) });
self.pwm.seq0.cnt.write(|w| unsafe { w.bits(4) });
self.start_seq(Seq::Seq0);
self.start_seq(Seq::Seq0);
}

/// Sets inverted duty cycle (15 bit) for a PWM channel.
Expand All @@ -392,9 +387,12 @@ where
T::buffer().set(buffer);
self.one_shot();
self.set_load_mode(LoadMode::Individual);
self.pwm.seq0.ptr.write(|w| unsafe { w.bits(T::buffer().as_ptr() as u32) });
self.pwm
.seq0
.ptr
.write(|w| unsafe { w.bits(T::buffer().as_ptr() as u32) });
self.pwm.seq0.cnt.write(|w| unsafe { w.bits(4) });
self.start_seq(Seq::Seq0);
self.start_seq(Seq::Seq0);
}

/// Returns the duty cycle value for a PWM channel.
Expand Down Expand Up @@ -470,7 +468,7 @@ where
pub fn start_seq(&self, seq: Seq) {
compiler_fence(Ordering::SeqCst);
self.pwm.enable.write(|w| w.enable().enabled());
self.pwm.tasks_seqstart[usize::from(seq)].write(|w| w.tasks_seqstart().set_bit());
self.pwm.tasks_seqstart[usize::from(seq)].write(|w| unsafe { w.bits(1) });
while self.pwm.events_seqstarted[usize::from(seq)].read().bits() == 0 {}
self.pwm.events_seqend[0].write(|w| w);
self.pwm.events_seqend[1].write(|w| w);
Expand All @@ -480,16 +478,14 @@ where
/// Does not cause PWM generation to start if not running.
#[inline(always)]
pub fn next_step(&self) {
self.pwm
.tasks_nextstep
.write(|w| w.tasks_nextstep().set_bit());
self.pwm.tasks_nextstep.write(|w| unsafe { w.bits(1) });
}

/// Stops PWM pulse generation on all channels at the end of current PWM period, and stops sequence playback.
#[inline(always)]
pub fn stop(&self) {
compiler_fence(Ordering::SeqCst);
self.pwm.tasks_stop.write(|w| w.tasks_stop().set_bit());
self.pwm.tasks_stop.write(|w| unsafe { w.bits(1) });
while self.pwm.events_stopped.read().bits() == 0 {}
}

Expand Down Expand Up @@ -1082,94 +1078,104 @@ static mut BUF2: Cell<[u16; 4]> = Cell::new([0; 4]);
static mut BUF3: Cell<[u16; 4]> = Cell::new([0; 4]);

#[cfg(not(any(feature = "9160")))]
impl Instance for PWM0 {
impl Instance for crate::pac::PWM0 {
const INTERRUPT: Interrupt = Interrupt::PWM0;
#[inline(always)]
fn buffer() -> &'static Cell<[u16; 4]> {
unsafe { &BUF0 }
unsafe { &BUF0 }
}
}

#[cfg(not(any(feature = "52810", feature = "52811", feature = "9160")))]
impl Instance for PWM1 {
impl Instance for crate::pac::PWM1 {
const INTERRUPT: Interrupt = Interrupt::PWM1;
fn buffer() -> &'static Cell<[u16; 4]> {
unsafe { &BUF1 }
unsafe { &BUF1 }
}
}

#[cfg(not(any(feature = "52810", feature = "52811", feature = "9160")))]
impl Instance for PWM2 {
impl Instance for crate::pac::PWM2 {
const INTERRUPT: Interrupt = Interrupt::PWM2;
fn buffer() -> &'static Cell<[u16; 4]> {
unsafe { &BUF2 }
unsafe { &BUF2 }
}
}

#[cfg(not(any(feature = "52810", feature = "52811", feature = "52832", feature = "9160")))]
impl Instance for PWM3 {
#[cfg(not(any(
feature = "52810",
feature = "52811",
feature = "52832",
feature = "9160"
)))]
impl Instance for crate::pac::PWM3 {
const INTERRUPT: Interrupt = Interrupt::PWM3;
fn buffer() -> &'static Cell<[u16; 4]> {
unsafe { &BUF3 }
unsafe { &BUF3 }
}
}

#[cfg(any(feature = "9160"))]
impl Instance for PWM0_NS {
impl Instance for crate::pac::PWM0_NS {
const INTERRUPT: Interrupt = Interrupt::PWM0;
#[inline(always)]
fn buffer() -> &'static Cell<[u16; 4]> {
unsafe { &BUF0 }
unsafe { &BUF0 }
}
}

#[cfg(any(feature = "9160"))]
impl Instance for PWM1_NS {
impl Instance for crate::pac::PWM1_NS {
const INTERRUPT: Interrupt = Interrupt::PWM1;
fn buffer() -> &'static Cell<[u16; 4]> {
unsafe { &BUF1 }
unsafe { &BUF1 }
}
}

#[cfg(any(feature = "9160"))]
impl Instance for PWM2_NS {
impl Instance for crate::pac::PWM2_NS {
const INTERRUPT: Interrupt = Interrupt::PWM2;
fn buffer() -> &'static Cell<[u16; 4]> {
unsafe { &BUF2 }
unsafe { &BUF2 }
}
}

#[cfg(any(feature = "9160"))]
impl Instance for PWM3_NS {
impl Instance for crate::pac::PWM3_NS {
const INTERRUPT: Interrupt = Interrupt::PWM3;
fn buffer() -> &'static Cell<[u16; 4]> {
unsafe { &BUF3 }
unsafe { &BUF3 }
}
}
mod sealed {
pub trait Sealed {}

#[cfg(not(any(feature = "9160")))]
impl Sealed for crate::pwm::PWM0 {}
impl Sealed for crate::pac::PWM0 {}

#[cfg(not(any(feature = "52810", feature = "52811", feature = "9160")))]
impl Sealed for crate::pwm::PWM1 {}
impl Sealed for crate::pac::PWM1 {}

#[cfg(not(any(feature = "52810", feature = "52811", feature = "9160")))]
impl Sealed for crate::pwm::PWM2 {}
impl Sealed for crate::pac::PWM2 {}

#[cfg(not(any(feature = "52810", feature = "52811", feature = "52832", feature = "9160")))]
impl Sealed for crate::pwm::PWM3 {}
#[cfg(not(any(
feature = "52810",
feature = "52811",
feature = "52832",
feature = "9160"
)))]
impl Sealed for crate::pac::PWM3 {}

#[cfg(any(feature = "9160"))]
impl Sealed for crate::pwm::PWM0_NS {}
impl Sealed for crate::pac::PWM0_NS {}

#[cfg(any(feature = "9160"))]
impl Sealed for crate::pwm::PWM1_NS {}
impl Sealed for crate::pac::PWM1_NS {}

#[cfg(any(feature = "9160"))]
impl Sealed for crate::pwm::PWM2_NS {}
impl Sealed for crate::pac::PWM2_NS {}

#[cfg(any(feature = "9160"))]
impl Sealed for crate::pwm::PWM3_NS {}
impl Sealed for crate::pac::PWM3_NS {}
}
Loading

0 comments on commit 39c0b8f

Please sign in to comment.