nrf/gpiote: initialize automatically

This commit is contained in:
Dario Nieuwenhuis 2021-05-12 01:01:08 +02:00
parent 92be72e0e3
commit 97b01f1c47
12 changed files with 21 additions and 55 deletions

View File

@ -18,30 +18,25 @@ use embassy_nrf::{interrupt, Peripherals};
#[embassy::main] #[embassy::main]
async fn main(spawner: Spawner) { async fn main(spawner: Spawner) {
let p = Peripherals::take().unwrap(); let p = Peripherals::take().unwrap();
let g = gpiote::initialize(p.GPIOTE, interrupt::take!(GPIOTE));
info!("Starting!"); info!("Starting!");
let ch1 = InputChannel::new( let ch1 = InputChannel::new(
g,
p.GPIOTE_CH0, p.GPIOTE_CH0,
Input::new(p.P0_11, Pull::Up), Input::new(p.P0_11, Pull::Up),
InputChannelPolarity::HiToLo, InputChannelPolarity::HiToLo,
); );
let ch2 = InputChannel::new( let ch2 = InputChannel::new(
g,
p.GPIOTE_CH1, p.GPIOTE_CH1,
Input::new(p.P0_12, Pull::Up), Input::new(p.P0_12, Pull::Up),
InputChannelPolarity::LoToHi, InputChannelPolarity::LoToHi,
); );
let ch3 = InputChannel::new( let ch3 = InputChannel::new(
g,
p.GPIOTE_CH2, p.GPIOTE_CH2,
Input::new(p.P0_24, Pull::Up), Input::new(p.P0_24, Pull::Up),
InputChannelPolarity::Toggle, InputChannelPolarity::Toggle,
); );
let ch4 = InputChannel::new( let ch4 = InputChannel::new(
g,
p.GPIOTE_CH3, p.GPIOTE_CH3,
Input::new(p.P0_25, Pull::Up), Input::new(p.P0_25, Pull::Up),
InputChannelPolarity::Toggle, InputChannelPolarity::Toggle,

View File

@ -8,12 +8,11 @@
#[path = "../example_common.rs"] #[path = "../example_common.rs"]
mod example_common; mod example_common;
use core::pin::Pin;
use defmt::panic; use defmt::panic;
use embassy::executor::Spawner; use embassy::executor::Spawner;
use embassy::traits::gpio::{WaitForHigh, WaitForLow}; use embassy::traits::gpio::{WaitForHigh, WaitForLow};
use embassy_nrf::gpio::{AnyPin, Input, Pin as _, Pull}; use embassy_nrf::gpio::{AnyPin, Input, Pin as _, Pull};
use embassy_nrf::gpiote::{self, PortInput}; use embassy_nrf::gpiote::PortInput;
use embassy_nrf::interrupt; use embassy_nrf::interrupt;
use embassy_nrf::Peripherals; use embassy_nrf::Peripherals;
use example_common::*; use example_common::*;
@ -32,12 +31,12 @@ async fn button_task(n: usize, mut pin: PortInput<'static, AnyPin>) {
async fn main(spawner: Spawner) { async fn main(spawner: Spawner) {
let p = Peripherals::take().unwrap(); let p = Peripherals::take().unwrap();
let g = gpiote::initialize(p.GPIOTE, interrupt::take!(GPIOTE)); info!("Starting!");
let btn1 = PortInput::new(g, Input::new(p.P0_11.degrade(), Pull::Up)); let btn1 = PortInput::new(Input::new(p.P0_11.degrade(), Pull::Up));
let btn2 = PortInput::new(g, Input::new(p.P0_12.degrade(), Pull::Up)); let btn2 = PortInput::new(Input::new(p.P0_12.degrade(), Pull::Up));
let btn3 = PortInput::new(g, Input::new(p.P0_24.degrade(), Pull::Up)); let btn3 = PortInput::new(Input::new(p.P0_24.degrade(), Pull::Up));
let btn4 = PortInput::new(g, Input::new(p.P0_25.degrade(), Pull::Up)); let btn4 = PortInput::new(Input::new(p.P0_25.degrade(), Pull::Up));
spawner.spawn(button_task(1, btn1)).unwrap(); spawner.spawn(button_task(1, btn1)).unwrap();
spawner.spawn(button_task(2, btn2)).unwrap(); spawner.spawn(button_task(2, btn2)).unwrap();

View File

@ -21,44 +21,37 @@ use gpiote::{OutputChannel, OutputChannelPolarity};
#[embassy::main] #[embassy::main]
async fn main(spawner: Spawner) { async fn main(spawner: Spawner) {
let p = Peripherals::take().unwrap(); let p = Peripherals::take().unwrap();
let g = gpiote::initialize(p.GPIOTE, interrupt::take!(GPIOTE));
info!("Starting!"); info!("Starting!");
let button1 = InputChannel::new( let button1 = InputChannel::new(
g,
p.GPIOTE_CH0, p.GPIOTE_CH0,
Input::new(p.P0_11, Pull::Up), Input::new(p.P0_11, Pull::Up),
InputChannelPolarity::HiToLo, InputChannelPolarity::HiToLo,
); );
let button2 = InputChannel::new( let button2 = InputChannel::new(
g,
p.GPIOTE_CH1, p.GPIOTE_CH1,
Input::new(p.P0_12, Pull::Up), Input::new(p.P0_12, Pull::Up),
InputChannelPolarity::HiToLo, InputChannelPolarity::HiToLo,
); );
let button3 = InputChannel::new( let button3 = InputChannel::new(
g,
p.GPIOTE_CH2, p.GPIOTE_CH2,
Input::new(p.P0_24, Pull::Up), Input::new(p.P0_24, Pull::Up),
InputChannelPolarity::HiToLo, InputChannelPolarity::HiToLo,
); );
let button4 = InputChannel::new( let button4 = InputChannel::new(
g,
p.GPIOTE_CH3, p.GPIOTE_CH3,
Input::new(p.P0_25, Pull::Up), Input::new(p.P0_25, Pull::Up),
InputChannelPolarity::HiToLo, InputChannelPolarity::HiToLo,
); );
let led1 = OutputChannel::new( let led1 = OutputChannel::new(
g,
p.GPIOTE_CH4, p.GPIOTE_CH4,
Output::new(p.P0_13, Level::Low, OutputDrive::Standard), Output::new(p.P0_13, Level::Low, OutputDrive::Standard),
OutputChannelPolarity::Toggle, OutputChannelPolarity::Toggle,
); );
let led2 = OutputChannel::new( let led2 = OutputChannel::new(
g,
p.GPIOTE_CH5, p.GPIOTE_CH5,
Output::new(p.P0_14, Level::Low, OutputDrive::Standard), Output::new(p.P0_14, Level::Low, OutputDrive::Standard),
OutputChannelPolarity::Toggle, OutputChannelPolarity::Toggle,

View File

@ -24,7 +24,6 @@ embassy_extras::peripherals! {
TIMER2, TIMER2,
// GPIOTE // GPIOTE
GPIOTE,
GPIOTE_CH0, GPIOTE_CH0,
GPIOTE_CH1, GPIOTE_CH1,
GPIOTE_CH2, GPIOTE_CH2,

View File

@ -24,7 +24,6 @@ embassy_extras::peripherals! {
TIMER2, TIMER2,
// GPIOTE // GPIOTE
GPIOTE,
GPIOTE_CH0, GPIOTE_CH0,
GPIOTE_CH1, GPIOTE_CH1,
GPIOTE_CH2, GPIOTE_CH2,

View File

@ -24,7 +24,6 @@ embassy_extras::peripherals! {
TIMER2, TIMER2,
// GPIOTE // GPIOTE
GPIOTE,
GPIOTE_CH0, GPIOTE_CH0,
GPIOTE_CH1, GPIOTE_CH1,
GPIOTE_CH2, GPIOTE_CH2,

View File

@ -25,7 +25,6 @@ embassy_extras::peripherals! {
TIMER3, TIMER3,
// GPIOTE // GPIOTE
GPIOTE,
GPIOTE_CH0, GPIOTE_CH0,
GPIOTE_CH1, GPIOTE_CH1,
GPIOTE_CH2, GPIOTE_CH2,

View File

@ -29,7 +29,6 @@ embassy_extras::peripherals! {
TIMER4, TIMER4,
// GPIOTE // GPIOTE
GPIOTE,
GPIOTE_CH0, GPIOTE_CH0,
GPIOTE_CH1, GPIOTE_CH1,
GPIOTE_CH2, GPIOTE_CH2,

View File

@ -30,7 +30,6 @@ embassy_extras::peripherals! {
TIMER4, TIMER4,
// GPIOTE // GPIOTE
GPIOTE,
GPIOTE_CH0, GPIOTE_CH0,
GPIOTE_CH1, GPIOTE_CH1,
GPIOTE_CH2, GPIOTE_CH2,

View File

@ -33,7 +33,6 @@ embassy_extras::peripherals! {
TIMER4, TIMER4,
// GPIOTE // GPIOTE
GPIOTE,
GPIOTE_CH0, GPIOTE_CH0,
GPIOTE_CH1, GPIOTE_CH1,
GPIOTE_CH2, GPIOTE_CH2,

View File

@ -2,7 +2,7 @@ use core::convert::Infallible;
use core::future::Future; use core::future::Future;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::task::{Context, Poll}; use core::task::{Context, Poll};
use embassy::interrupt::InterruptExt; use embassy::interrupt::{Interrupt, InterruptExt};
use embassy::traits::gpio::{WaitForAnyEdge, WaitForHigh, WaitForLow}; use embassy::traits::gpio::{WaitForAnyEdge, WaitForHigh, WaitForLow};
use embassy::util::AtomicWaker; use embassy::util::AtomicWaker;
use embassy_extras::impl_unborrow; use embassy_extras::impl_unborrow;
@ -40,15 +40,7 @@ pub enum OutputChannelPolarity {
Toggle, Toggle,
} }
/// Token indicating GPIOTE has been correctly initialized. pub(crate) fn init() {
///
/// This is not an owned singleton, it is Copy. Drivers that make use of GPIOTE require it.
#[derive(Clone, Copy)]
pub struct Initialized {
_private: (),
}
pub fn initialize(_gpiote: peripherals::GPIOTE, irq: interrupt::GPIOTE) -> Initialized {
#[cfg(any(feature = "nrf52833", feature = "nrf52840"))] #[cfg(any(feature = "nrf52833", feature = "nrf52840"))]
let ports = unsafe { &[&*pac::P0::ptr(), &*pac::P1::ptr()] }; let ports = unsafe { &[&*pac::P0::ptr(), &*pac::P1::ptr()] };
#[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))] #[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))]
@ -62,17 +54,18 @@ pub fn initialize(_gpiote: peripherals::GPIOTE, irq: interrupt::GPIOTE) -> Initi
} }
// Enable interrupts // Enable interrupts
let g = unsafe { &*pac::GPIOTE::ptr() };
g.events_port.write(|w| w); let irq = unsafe { interrupt::GPIOTE::steal() };
g.intenset.write(|w| w.port().set());
irq.set_handler(on_irq);
irq.unpend(); irq.unpend();
irq.enable(); irq.enable();
Initialized { _private: () } let g = unsafe { &*pac::GPIOTE::ptr() };
g.events_port.write(|w| w);
g.intenset.write(|w| w.port().set());
} }
unsafe fn on_irq(_ctx: *mut ()) { #[interrupt]
unsafe fn GPIOTE() {
let g = &*pac::GPIOTE::ptr(); let g = &*pac::GPIOTE::ptr();
for i in 0..CHANNEL_COUNT { for i in 0..CHANNEL_COUNT {
@ -133,12 +126,7 @@ impl<'d, C: Channel, T: GpioPin> Drop for InputChannel<'d, C, T> {
} }
impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> { impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
pub fn new( pub fn new(ch: C, pin: Input<'d, T>, polarity: InputChannelPolarity) -> Self {
_init: Initialized,
ch: C,
pin: Input<'d, T>,
polarity: InputChannelPolarity,
) -> Self {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*pac::GPIOTE::ptr() };
let num = ch.number(); let num = ch.number();
@ -217,12 +205,7 @@ impl<'d, C: Channel, T: GpioPin> Drop for OutputChannel<'d, C, T> {
} }
impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> { impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
pub fn new( pub fn new(ch: C, pin: Output<'d, T>, polarity: OutputChannelPolarity) -> Self {
_init: Initialized,
ch: C,
pin: Output<'d, T>,
polarity: OutputChannelPolarity,
) -> Self {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*pac::GPIOTE::ptr() };
let num = ch.number(); let num = ch.number();
@ -297,7 +280,7 @@ pub struct PortInput<'d, T: GpioPin> {
impl<'d, T: GpioPin> Unpin for PortInput<'d, T> {} impl<'d, T: GpioPin> Unpin for PortInput<'d, T> {}
impl<'d, T: GpioPin> PortInput<'d, T> { impl<'d, T: GpioPin> PortInput<'d, T> {
pub fn new(_init: Initialized, pin: Input<'d, T>) -> Self { pub fn new(pin: Input<'d, T>) -> Self {
Self { pin } Self { pin }
} }
} }

View File

@ -73,4 +73,7 @@ pub unsafe fn configure(config: Config) {
r.events_lfclkstarted.write(|w| unsafe { w.bits(0) }); r.events_lfclkstarted.write(|w| unsafe { w.bits(0) });
r.tasks_lfclkstart.write(|w| unsafe { w.bits(1) }); r.tasks_lfclkstart.write(|w| unsafe { w.bits(1) });
while r.events_lfclkstarted.read().bits() == 0 {} while r.events_lfclkstarted.read().bits() == 0 {}
// Init GPIOTE
crate::gpiote::init();
} }