Initial support for nrf9160

This commit is contained in:
Dion Dokter 2021-10-11 10:39:38 +02:00
parent 009b77c1b9
commit 20674f7126
16 changed files with 458 additions and 87 deletions

View File

@ -25,6 +25,7 @@ nrf52820 = ["nrf52820-pac"]
nrf52832 = ["nrf52832-pac"] nrf52832 = ["nrf52832-pac"]
nrf52833 = ["nrf52833-pac"] nrf52833 = ["nrf52833-pac"]
nrf52840 = ["nrf52840-pac"] nrf52840 = ["nrf52840-pac"]
nrf9160 = ["nrf9160-pac"]
# Features starting with `_` are for internal use only. They're not intended # Features starting with `_` are for internal use only. They're not intended
# to be enabled by other crates, and are not covered by semver guarantees. # to be enabled by other crates, and are not covered by semver guarantees.
@ -55,3 +56,4 @@ nrf52820-pac = { version = "0.10.1", optional = true, features = [ "rt" ] }
nrf52832-pac = { version = "0.10.1", optional = true, features = [ "rt" ] } nrf52832-pac = { version = "0.10.1", optional = true, features = [ "rt" ] }
nrf52833-pac = { version = "0.10.1", optional = true, features = [ "rt" ] } nrf52833-pac = { version = "0.10.1", optional = true, features = [ "rt" ] }
nrf52840-pac = { version = "0.10.1", optional = true, features = [ "rt" ] } nrf52840-pac = { version = "0.10.1", optional = true, features = [ "rt" ] }
nrf9160-pac = { version = "0.10.1", optional = true, features = [ "rt" ] }

View File

@ -14,14 +14,13 @@ use embassy_hal_common::{low_power_wait_until, unborrow};
use crate::gpio::sealed::Pin as _; use crate::gpio::sealed::Pin as _;
use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin}; use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin};
use crate::pac;
use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
use crate::timer::Instance as TimerInstance; use crate::timer::Instance as TimerInstance;
use crate::timer::{Frequency, Timer}; use crate::timer::{Frequency, Timer};
use crate::uarte::{Config, Instance as UarteInstance}; use crate::uarte::{Config, Instance as UarteInstance, uarte0};
// Re-export SVD variants to allow user to directly set values // Re-export SVD variants to allow user to directly set values
pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; pub use uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
enum RxState { enum RxState {

View File

@ -0,0 +1,209 @@
pub use nrf9160_pac as pac;
/// The maximum buffer size that the EasyDMA can send/recv in one operation.
pub const EASY_DMA_SIZE: usize = (1 << 12) - 1;
pub const FORCE_COPY_BUFFER_SIZE: usize = 1024;
embassy_hal_common::peripherals! {
// RTC
RTC0,
RTC1,
// WDT
WDT,
// UARTE
UARTE0,
UARTE1,
UARTE2,
UARTE3,
// TWI
TWI0,
TWI1,
TWI2,
TWI3,
// SPI
SPI0,
SPI1,
SPI2,
SPI3,
// SAADC
SAADC,
// PWM
PWM0,
PWM1,
PWM2,
PWM3,
// TIMER
TIMER0,
TIMER1,
TIMER2,
// GPIOTE
GPIOTE_CH0,
GPIOTE_CH1,
GPIOTE_CH2,
GPIOTE_CH3,
GPIOTE_CH4,
GPIOTE_CH5,
GPIOTE_CH6,
GPIOTE_CH7,
// PPI
PPI_CH0,
PPI_CH1,
PPI_CH2,
PPI_CH3,
PPI_CH4,
PPI_CH5,
PPI_CH6,
PPI_CH7,
PPI_CH8,
PPI_CH9,
PPI_CH10,
PPI_CH11,
PPI_CH12,
PPI_CH13,
PPI_CH14,
PPI_CH15,
PPI_GROUP0,
PPI_GROUP1,
PPI_GROUP2,
PPI_GROUP3,
PPI_GROUP4,
PPI_GROUP5,
// GPIO port 0
P0_00,
P0_01,
P0_02,
P0_03,
P0_04,
P0_05,
P0_06,
P0_07,
P0_08,
P0_09,
P0_10,
P0_11,
P0_12,
P0_13,
P0_14,
P0_15,
P0_16,
P0_17,
P0_18,
P0_19,
P0_20,
P0_21,
P0_22,
P0_23,
P0_24,
P0_25,
P0_26,
P0_27,
P0_28,
P0_29,
P0_30,
P0_31,
}
impl_uarte!(UARTE0, UARTE0_NS, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0);
impl_uarte!(UARTE1, UARTE1_NS, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
impl_uarte!(UARTE2, UARTE2_NS, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
impl_uarte!(UARTE3, UARTE3_NS, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
impl_spim!(SPI0, SPIM0_NS, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0);
impl_spim!(SPI1, SPIM1_NS, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
impl_spim!(SPI2, SPIM2_NS, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
impl_spim!(SPI3, SPIM3_NS, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
impl_twim!(TWI0, TWIM0_NS, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0);
impl_twim!(TWI1, TWIM1_NS, UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
impl_twim!(TWI2, TWIM2_NS, UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
impl_twim!(TWI3, TWIM3_NS, UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
impl_pwm!(PWM0, PWM0_NS, PWM0);
impl_pwm!(PWM1, PWM1_NS, PWM1);
impl_pwm!(PWM2, PWM2_NS, PWM2);
impl_pwm!(PWM3, PWM3_NS, PWM3);
impl_timer!(TIMER0, TIMER0_NS, TIMER0);
impl_timer!(TIMER1, TIMER1_NS, TIMER1);
impl_timer!(TIMER2, TIMER2_NS, TIMER2);
impl_pin!(P0_00, 0, 0);
impl_pin!(P0_01, 0, 1);
impl_pin!(P0_02, 0, 2);
impl_pin!(P0_03, 0, 3);
impl_pin!(P0_04, 0, 4);
impl_pin!(P0_05, 0, 5);
impl_pin!(P0_06, 0, 6);
impl_pin!(P0_07, 0, 7);
impl_pin!(P0_08, 0, 8);
impl_pin!(P0_09, 0, 9);
impl_pin!(P0_10, 0, 10);
impl_pin!(P0_11, 0, 11);
impl_pin!(P0_12, 0, 12);
impl_pin!(P0_13, 0, 13);
impl_pin!(P0_14, 0, 14);
impl_pin!(P0_15, 0, 15);
impl_pin!(P0_16, 0, 16);
impl_pin!(P0_17, 0, 17);
impl_pin!(P0_18, 0, 18);
impl_pin!(P0_19, 0, 19);
impl_pin!(P0_20, 0, 20);
impl_pin!(P0_21, 0, 21);
impl_pin!(P0_22, 0, 22);
impl_pin!(P0_23, 0, 23);
impl_pin!(P0_24, 0, 24);
impl_pin!(P0_25, 0, 25);
impl_pin!(P0_26, 0, 26);
impl_pin!(P0_27, 0, 27);
impl_pin!(P0_28, 0, 28);
impl_pin!(P0_29, 0, 29);
impl_pin!(P0_30, 0, 30);
impl_pin!(P0_31, 0, 31);
pub mod irqs {
use crate::pac::Interrupt as InterruptEnum;
use embassy_macros::interrupt_declare as declare;
declare!(SPU);
declare!(CLOCK_POWER);
declare!(UARTE0_SPIM0_SPIS0_TWIM0_TWIS0);
declare!(UARTE1_SPIM1_SPIS1_TWIM1_TWIS1);
declare!(UARTE2_SPIM2_SPIS2_TWIM2_TWIS2);
declare!(UARTE3_SPIM3_SPIS3_TWIM3_TWIS3);
declare!(GPIOTE0);
declare!(SAADC);
declare!(TIMER0);
declare!(TIMER1);
declare!(TIMER2);
declare!(RTC0);
declare!(RTC1);
declare!(WDT);
declare!(EGU0);
declare!(EGU1);
declare!(EGU2);
declare!(EGU3);
declare!(EGU4);
declare!(EGU5);
declare!(PWM0);
declare!(PWM1);
declare!(PWM2);
declare!(PDM);
declare!(PWM3);
declare!(I2S);
declare!(IPC);
declare!(FPU);
declare!(GPIOTE1);
declare!(KMU);
declare!(CRYPTOCELL);
}

View File

@ -10,7 +10,11 @@ use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
use gpio::pin_cnf::DRIVE_A; use gpio::pin_cnf::DRIVE_A;
use crate::pac; use crate::pac;
#[cfg(not(feature = "nrf9160"))]
use crate::pac::p0 as gpio; use crate::pac::p0 as gpio;
#[cfg(feature = "nrf9160")]
use crate::pac::p0_ns as gpio;
use self::sealed::Pin as _; use self::sealed::Pin as _;
@ -299,7 +303,10 @@ pub(crate) mod sealed {
fn block(&self) -> &gpio::RegisterBlock { fn block(&self) -> &gpio::RegisterBlock {
unsafe { unsafe {
match self.pin_port() / 32 { match self.pin_port() / 32 {
#[cfg(not(feature = "nrf9160"))]
0 => &*pac::P0::ptr(), 0 => &*pac::P0::ptr(),
#[cfg(feature = "nrf9160")]
0 => &*pac::P0_NS::ptr(),
#[cfg(any(feature = "nrf52833", feature = "nrf52840"))] #[cfg(any(feature = "nrf52833", feature = "nrf52840"))]
1 => &*pac::P1::ptr(), 1 => &*pac::P1::ptr(),
_ => unreachable_unchecked(), _ => unreachable_unchecked(),

View File

@ -22,6 +22,18 @@ pub const PIN_COUNT: usize = 48;
#[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))] #[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))]
pub const PIN_COUNT: usize = 32; pub const PIN_COUNT: usize = 32;
#[cfg(not(feature = "nrf9160"))]
pub(crate) use pac::P0;
#[cfg(feature = "nrf9160")]
pub(crate) use pac::P0_NS as P0;
#[cfg(not(feature = "nrf9160"))]
pub(crate) use pac::P1;
#[cfg(not(feature = "nrf9160"))]
pub(crate) use pac::GPIOTE;
#[cfg(feature = "nrf9160")]
pub(crate) use pac::GPIOTE1_NS as GPIOTE;
const NEW_AW: AtomicWaker = AtomicWaker::new(); const NEW_AW: AtomicWaker = AtomicWaker::new();
static CHANNEL_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [NEW_AW; CHANNEL_COUNT]; static CHANNEL_WAKERS: [AtomicWaker; CHANNEL_COUNT] = [NEW_AW; CHANNEL_COUNT];
static PORT_WAKERS: [AtomicWaker; PIN_COUNT] = [NEW_AW; PIN_COUNT]; static PORT_WAKERS: [AtomicWaker; PIN_COUNT] = [NEW_AW; PIN_COUNT];
@ -42,9 +54,9 @@ pub enum OutputChannelPolarity {
pub(crate) fn init(irq_prio: crate::interrupt::Priority) { pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
#[cfg(any(feature = "nrf52833", feature = "nrf52840"))] #[cfg(any(feature = "nrf52833", feature = "nrf52840"))]
let ports = unsafe { &[&*pac::P0::ptr(), &*pac::P1::ptr()] }; let ports = unsafe { &[&*P0::ptr(), &*P1::ptr()] };
#[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))] #[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))]
let ports = unsafe { &[&*pac::P0::ptr()] }; let ports = unsafe { &[&*P0::ptr()] };
for &p in ports { for &p in ports {
// Enable latched detection // Enable latched detection
@ -55,19 +67,34 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
// Enable interrupts // Enable interrupts
#[cfg(not(feature = "nrf9160"))]
let irq = unsafe { interrupt::GPIOTE::steal() }; let irq = unsafe { interrupt::GPIOTE::steal() };
#[cfg(feature = "nrf9160")]
let irq = unsafe { interrupt::GPIOTE1::steal() };
irq.unpend(); irq.unpend();
irq.set_priority(irq_prio); irq.set_priority(irq_prio);
irq.enable(); irq.enable();
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*GPIOTE::ptr() };
g.events_port.write(|w| w); g.events_port.write(|w| w);
g.intenset.write(|w| w.port().set()); g.intenset.write(|w| w.port().set());
} }
#[cfg(not(feature = "nrf9160"))]
#[interrupt] #[interrupt]
unsafe fn GPIOTE() { fn GPIOTE() {
let g = &*pac::GPIOTE::ptr(); unsafe { handle_gpiote_interrupt() };
}
#[cfg(feature = "nrf9160")]
#[interrupt]
fn GPIOTE1() {
unsafe { handle_gpiote_interrupt() };
}
unsafe fn handle_gpiote_interrupt() {
let g = &*GPIOTE::ptr();
for i in 0..CHANNEL_COUNT { for i in 0..CHANNEL_COUNT {
if g.events_in[i].read().bits() != 0 { if g.events_in[i].read().bits() != 0 {
@ -80,9 +107,9 @@ unsafe fn GPIOTE() {
g.events_port.write(|w| w); g.events_port.write(|w| w);
#[cfg(any(feature = "nrf52833", feature = "nrf52840"))] #[cfg(any(feature = "nrf52833", feature = "nrf52840"))]
let ports = &[&*pac::P0::ptr(), &*pac::P1::ptr()]; let ports = &[&*P0::ptr(), &*P1::ptr()];
#[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))] #[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))]
let ports = &[&*pac::P0::ptr()]; let ports = &[&*P0::ptr()];
for (port, &p) in ports.iter().enumerate() { for (port, &p) in ports.iter().enumerate() {
let bits = p.latch.read().bits(); let bits = p.latch.read().bits();
@ -119,7 +146,7 @@ pub struct InputChannel<'d, C: Channel, T: GpioPin> {
impl<'d, C: Channel, T: GpioPin> Drop for InputChannel<'d, C, T> { impl<'d, C: Channel, T: GpioPin> Drop for InputChannel<'d, C, T> {
fn drop(&mut self) { fn drop(&mut self) {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*GPIOTE::ptr() };
let num = self.ch.number(); let num = self.ch.number();
g.config[num].write(|w| w.mode().disabled()); g.config[num].write(|w| w.mode().disabled());
g.intenclr.write(|w| unsafe { w.bits(1 << num) }); g.intenclr.write(|w| unsafe { w.bits(1 << num) });
@ -128,7 +155,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(ch: C, pin: Input<'d, T>, polarity: InputChannelPolarity) -> Self { pub fn new(ch: C, pin: Input<'d, T>, polarity: InputChannelPolarity) -> Self {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*GPIOTE::ptr() };
let num = ch.number(); let num = ch.number();
g.config[num].write(|w| { g.config[num].write(|w| {
@ -152,7 +179,7 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
} }
pub async fn wait(&self) { pub async fn wait(&self) {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*GPIOTE::ptr() };
let num = self.ch.number(); let num = self.ch.number();
// Enable interrupt // Enable interrupt
@ -173,7 +200,7 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
/// Returns the IN event, for use with PPI. /// Returns the IN event, for use with PPI.
pub fn event_in(&self) -> Event { pub fn event_in(&self) -> Event {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*GPIOTE::ptr() };
Event::from_reg(&g.events_in[self.ch.number()]) Event::from_reg(&g.events_in[self.ch.number()])
} }
} }
@ -198,7 +225,7 @@ pub struct OutputChannel<'d, C: Channel, T: GpioPin> {
impl<'d, C: Channel, T: GpioPin> Drop for OutputChannel<'d, C, T> { impl<'d, C: Channel, T: GpioPin> Drop for OutputChannel<'d, C, T> {
fn drop(&mut self) { fn drop(&mut self) {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*GPIOTE::ptr() };
let num = self.ch.number(); let num = self.ch.number();
g.config[num].write(|w| w.mode().disabled()); g.config[num].write(|w| w.mode().disabled());
g.intenclr.write(|w| unsafe { w.bits(1 << num) }); g.intenclr.write(|w| unsafe { w.bits(1 << num) });
@ -207,7 +234,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(ch: C, pin: Output<'d, T>, polarity: OutputChannelPolarity) -> Self { pub fn new(ch: C, pin: Output<'d, T>, polarity: OutputChannelPolarity) -> Self {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*GPIOTE::ptr() };
let num = ch.number(); let num = ch.number();
g.config[num].write(|w| { g.config[num].write(|w| {
@ -234,41 +261,41 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
/// Triggers `task out` (as configured with task_out_polarity, defaults to Toggle). /// Triggers `task out` (as configured with task_out_polarity, defaults to Toggle).
pub fn out(&self) { pub fn out(&self) {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*GPIOTE::ptr() };
g.tasks_out[self.ch.number()].write(|w| unsafe { w.bits(1) }); g.tasks_out[self.ch.number()].write(|w| unsafe { w.bits(1) });
} }
/// Triggers `task set` (set associated pin high). /// Triggers `task set` (set associated pin high).
#[cfg(not(feature = "51"))] #[cfg(not(feature = "51"))]
pub fn set(&self) { pub fn set(&self) {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*GPIOTE::ptr() };
g.tasks_set[self.ch.number()].write(|w| unsafe { w.bits(1) }); g.tasks_set[self.ch.number()].write(|w| unsafe { w.bits(1) });
} }
/// Triggers `task clear` (set associated pin low). /// Triggers `task clear` (set associated pin low).
#[cfg(not(feature = "51"))] #[cfg(not(feature = "51"))]
pub fn clear(&self) { pub fn clear(&self) {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*GPIOTE::ptr() };
g.tasks_clr[self.ch.number()].write(|w| unsafe { w.bits(1) }); g.tasks_clr[self.ch.number()].write(|w| unsafe { w.bits(1) });
} }
/// Returns the OUT task, for use with PPI. /// Returns the OUT task, for use with PPI.
pub fn task_out(&self) -> Task { pub fn task_out(&self) -> Task {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*GPIOTE::ptr() };
Task::from_reg(&g.tasks_out[self.ch.number()]) Task::from_reg(&g.tasks_out[self.ch.number()])
} }
/// Returns the CLR task, for use with PPI. /// Returns the CLR task, for use with PPI.
#[cfg(not(feature = "51"))] #[cfg(not(feature = "51"))]
pub fn task_clr(&self) -> Task { pub fn task_clr(&self) -> Task {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*GPIOTE::ptr() };
Task::from_reg(&g.tasks_clr[self.ch.number()]) Task::from_reg(&g.tasks_clr[self.ch.number()])
} }
/// Returns the SET task, for use with PPI. /// Returns the SET task, for use with PPI.
#[cfg(not(feature = "51"))] #[cfg(not(feature = "51"))]
pub fn task_set(&self) -> Task { pub fn task_set(&self) -> Task {
let g = unsafe { &*pac::GPIOTE::ptr() }; let g = unsafe { &*GPIOTE::ptr() };
Task::from_reg(&g.tasks_set[self.ch.number()]) Task::from_reg(&g.tasks_set[self.ch.number()])
} }
} }

View File

@ -34,6 +34,7 @@ pub mod ppi;
pub mod pwm; pub mod pwm;
#[cfg(feature = "nrf52840")] #[cfg(feature = "nrf52840")]
pub mod qspi; pub mod qspi;
#[cfg(not(feature = "nrf9160"))]
pub mod rng; pub mod rng;
#[cfg(not(feature = "nrf52820"))] #[cfg(not(feature = "nrf52820"))]
pub mod saadc; pub mod saadc;
@ -65,6 +66,9 @@ mod chip;
#[cfg(feature = "nrf52840")] #[cfg(feature = "nrf52840")]
#[path = "chips/nrf52840.rs"] #[path = "chips/nrf52840.rs"]
mod chip; mod chip;
#[cfg(feature = "nrf9160")]
#[path = "chips/nrf9160.rs"]
mod chip;
pub use chip::EASY_DMA_SIZE; pub use chip::EASY_DMA_SIZE;
@ -75,6 +79,11 @@ pub(crate) use chip::pac;
pub use chip::{peripherals, Peripherals}; pub use chip::{peripherals, Peripherals};
#[cfg(feature = "nrf9160")]
use crate::pac::CLOCK_NS as CLOCK;
#[cfg(not(feature = "nrf9160"))]
use crate::pac::CLOCK;
pub mod interrupt { pub mod interrupt {
pub use crate::chip::irqs::*; pub use crate::chip::irqs::*;
pub use cortex_m::interrupt::{CriticalSection, Mutex}; pub use cortex_m::interrupt::{CriticalSection, Mutex};
@ -91,9 +100,12 @@ pub mod config {
pub enum LfclkSource { pub enum LfclkSource {
InternalRC, InternalRC,
#[cfg(not(feature = "nrf9160"))]
Synthesized, Synthesized,
ExternalXtal, ExternalXtal,
#[cfg(not(feature = "nrf9160"))]
ExternalLowSwing, ExternalLowSwing,
#[cfg(not(feature = "nrf9160"))]
ExternalFullSwing, ExternalFullSwing,
} }
@ -129,7 +141,7 @@ pub fn init(config: config::Config) -> Peripherals {
// before doing anything important. // before doing anything important.
let peripherals = Peripherals::take(); let peripherals = Peripherals::take();
let r = unsafe { &*pac::CLOCK::ptr() }; let r = unsafe { &*CLOCK::ptr() };
// Start HFCLK. // Start HFCLK.
match config.hfclk_source { match config.hfclk_source {
@ -143,6 +155,7 @@ pub fn init(config: config::Config) -> Peripherals {
} }
// Configure LFCLK. // Configure LFCLK.
#[cfg(not(feature = "nrf9160"))]
match config.lfclk_source { match config.lfclk_source {
config::LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().rc()), config::LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().rc()),
config::LfclkSource::Synthesized => r.lfclksrc.write(|w| w.src().synth()), config::LfclkSource::Synthesized => r.lfclksrc.write(|w| w.src().synth()),
@ -162,6 +175,11 @@ pub fn init(config: config::Config) -> Peripherals {
w w
}), }),
} }
#[cfg(feature = "nrf9160")]
match config.lfclk_source {
config::LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().lfrc()),
config::LfclkSource::ExternalXtal => r.lfclksrc.write(|w| w.src().lfxo()),
}
// Start LFCLK. // Start LFCLK.
// Datasheet says this could take 100us from synth source // Datasheet says this could take 100us from synth source

View File

@ -16,6 +16,11 @@ use embassy_hal_common::{unborrow, unsafe_impl_unborrow};
use crate::{pac, peripherals}; use crate::{pac, peripherals};
#[cfg(not(feature = "nrf9160"))]
pub(crate) use pac::PPI;
#[cfg(feature = "nrf9160")]
pub(crate) use pac::DPPIC_NS as PPI;
// ====================== // ======================
// driver // driver
@ -27,45 +32,60 @@ pub struct Ppi<'d, C: Channel> {
impl<'d, C: Channel> Ppi<'d, C> { impl<'d, C: Channel> Ppi<'d, C> {
pub fn new(ch: impl Unborrow<Target = C> + 'd) -> Self { pub fn new(ch: impl Unborrow<Target = C> + 'd) -> Self {
unborrow!(ch); unborrow!(ch);
#[allow(unused_mut)]
let mut this = Self { let mut this = Self {
ch, ch,
phantom: PhantomData, phantom: PhantomData,
}; };
#[cfg(not(feature = "51"))] #[cfg(not(any(feature = "51", feature = "nrf9160")))]
this.clear_fork_task(); this.clear_fork_task();
this this
} }
/// Enables the channel. /// Enables the channel.
pub fn enable(&mut self) { pub fn enable(&mut self) {
let r = unsafe { &*pac::PPI::ptr() }; let r = unsafe { &*PPI::ptr() };
r.chenset r.chenset
.write(|w| unsafe { w.bits(1 << self.ch.number()) }); .write(|w| unsafe { w.bits(1 << self.ch.number()) });
} }
/// Disables the channel. /// Disables the channel.
pub fn disable(&mut self) { pub fn disable(&mut self) {
let r = unsafe { &*pac::PPI::ptr() }; let r = unsafe { &*PPI::ptr() };
r.chenclr r.chenclr
.write(|w| unsafe { w.bits(1 << self.ch.number()) }); .write(|w| unsafe { w.bits(1 << self.ch.number()) });
} }
#[cfg(not(feature = "51"))] #[cfg(not(any(feature = "51", feature = "nrf9160")))]
/// Sets the fork task that must be triggered when the configured event occurs. The user must /// Sets the fork task that must be triggered when the configured event occurs. The user must
/// provide a reference to the task. /// provide a reference to the task.
pub fn set_fork_task(&mut self, task: Task) { pub fn set_fork_task(&mut self, task: Task) {
let r = unsafe { &*pac::PPI::ptr() }; let r = unsafe { &*PPI::ptr() };
r.fork[self.ch.number()] r.fork[self.ch.number()]
.tep .tep
.write(|w| unsafe { w.bits(task.0.as_ptr() as u32) }) .write(|w| unsafe { w.bits(task.0.as_ptr() as u32) })
} }
#[cfg(not(feature = "51"))] #[cfg(not(any(feature = "51", feature = "nrf9160")))]
/// Clear the fork task endpoint. Previously set task will no longer be triggered. /// Clear the fork task endpoint. Previously set task will no longer be triggered.
pub fn clear_fork_task(&mut self) { pub fn clear_fork_task(&mut self) {
let r = unsafe { &*pac::PPI::ptr() }; let r = unsafe { &*PPI::ptr() };
r.fork[self.ch.number()].tep.write(|w| unsafe { w.bits(0) }) r.fork[self.ch.number()].tep.write(|w| unsafe { w.bits(0) })
} }
#[cfg(feature = "nrf9160")]
/// Sets the fork task that must be triggered when the configured event occurs. The user must
/// provide a reference to the task.
pub fn set_fork_task(&mut self, _task: Task) {
todo!("Tasks not yet implemented for nrf9160");
}
#[cfg(feature = "nrf9160")]
/// Clear the fork task endpoint. Previously set task will no longer be triggered.
pub fn clear_fork_task(&mut self) {
todo!("Tasks not yet implemented for nrf9160");
}
} }
impl<'d, C: Channel> Drop for Ppi<'d, C> { impl<'d, C: Channel> Drop for Ppi<'d, C> {
@ -74,10 +94,11 @@ impl<'d, C: Channel> Drop for Ppi<'d, C> {
} }
} }
#[cfg(not(feature = "nrf9160"))]
impl<'d, C: ConfigurableChannel> Ppi<'d, C> { impl<'d, C: ConfigurableChannel> Ppi<'d, C> {
/// Sets the task to be triggered when the configured event occurs. /// Sets the task to be triggered when the configured event occurs.
pub fn set_task(&mut self, task: Task) { pub fn set_task(&mut self, task: Task) {
let r = unsafe { &*pac::PPI::ptr() }; let r = unsafe { &*PPI::ptr() };
r.ch[self.ch.number()] r.ch[self.ch.number()]
.tep .tep
.write(|w| unsafe { w.bits(task.0.as_ptr() as u32) }) .write(|w| unsafe { w.bits(task.0.as_ptr() as u32) })
@ -85,13 +106,26 @@ impl<'d, C: ConfigurableChannel> Ppi<'d, C> {
/// Sets the event that will trigger the chosen task(s). /// Sets the event that will trigger the chosen task(s).
pub fn set_event(&mut self, event: Event) { pub fn set_event(&mut self, event: Event) {
let r = unsafe { &*pac::PPI::ptr() }; let r = unsafe { &*PPI::ptr() };
r.ch[self.ch.number()] r.ch[self.ch.number()]
.eep .eep
.write(|w| unsafe { w.bits(event.0.as_ptr() as u32) }) .write(|w| unsafe { w.bits(event.0.as_ptr() as u32) })
} }
} }
#[cfg(feature = "nrf9160")]
impl<'d, C: ConfigurableChannel> Ppi<'d, C> {
/// Sets the task to be triggered when the configured event occurs.
pub fn set_task(&mut self, _task: Task) {
todo!("Tasks not yet implemented for nrf9160")
}
/// Sets the event that will trigger the chosen task(s).
pub fn set_event(&mut self, _event: Event) {
todo!("Events not yet implemented for nrf9160")
}
}
// ====================== // ======================
// traits // traits
@ -183,6 +217,11 @@ macro_rules! impl_channel {
}; };
} }
pub use channel_impl::*;
#[cfg(not(feature = "nrf9160"))]
mod channel_impl {
use super::*;
impl_channel!(PPI_CH0, 0, configurable); impl_channel!(PPI_CH0, 0, configurable);
impl_channel!(PPI_CH1, 1, configurable); impl_channel!(PPI_CH1, 1, configurable);
impl_channel!(PPI_CH2, 2, configurable); impl_channel!(PPI_CH2, 2, configurable);
@ -199,7 +238,7 @@ impl_channel!(PPI_CH12, 12, configurable);
impl_channel!(PPI_CH13, 13, configurable); impl_channel!(PPI_CH13, 13, configurable);
impl_channel!(PPI_CH14, 14, configurable); impl_channel!(PPI_CH14, 14, configurable);
impl_channel!(PPI_CH15, 15, configurable); impl_channel!(PPI_CH15, 15, configurable);
#[cfg(not(feature = "51"))] #[cfg(not(feature = "51",))]
impl_channel!(PPI_CH16, 16, configurable); impl_channel!(PPI_CH16, 16, configurable);
#[cfg(not(feature = "51"))] #[cfg(not(feature = "51"))]
impl_channel!(PPI_CH17, 17, configurable); impl_channel!(PPI_CH17, 17, configurable);
@ -219,6 +258,28 @@ impl_channel!(PPI_CH28, 28);
impl_channel!(PPI_CH29, 29); impl_channel!(PPI_CH29, 29);
impl_channel!(PPI_CH30, 30); impl_channel!(PPI_CH30, 30);
impl_channel!(PPI_CH31, 31); impl_channel!(PPI_CH31, 31);
}
#[cfg(feature = "nrf9160")] // TODO: Implement configurability for nrf9160 and then remove these channel_impl modules
mod channel_impl {
use super::*;
impl_channel!(PPI_CH0, 0, configurable);
impl_channel!(PPI_CH1, 1, configurable);
impl_channel!(PPI_CH2, 2, configurable);
impl_channel!(PPI_CH3, 3, configurable);
impl_channel!(PPI_CH4, 4, configurable);
impl_channel!(PPI_CH5, 5, configurable);
impl_channel!(PPI_CH6, 6, configurable);
impl_channel!(PPI_CH7, 7, configurable);
impl_channel!(PPI_CH8, 8, configurable);
impl_channel!(PPI_CH9, 9, configurable);
impl_channel!(PPI_CH10, 10, configurable);
impl_channel!(PPI_CH11, 11, configurable);
impl_channel!(PPI_CH12, 12, configurable);
impl_channel!(PPI_CH13, 13, configurable);
impl_channel!(PPI_CH14, 14, configurable);
impl_channel!(PPI_CH15, 15, configurable);
}
// ====================== // ======================
// groups // groups

View File

@ -11,6 +11,12 @@ use crate::gpio::OptionalPin as GpioOptionalPin;
use crate::interrupt::Interrupt; use crate::interrupt::Interrupt;
use crate::pac; use crate::pac;
#[cfg(not(feature = "nrf9160"))]
pub(crate) use pac::pwm0;
#[cfg(feature = "nrf9160")]
pub(crate) use pac::pwm0_ns as pwm0;
#[derive(Debug, Eq, PartialEq, Clone, Copy)] #[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum Prescaler { pub enum Prescaler {
Div1, Div1,
@ -203,7 +209,7 @@ pub(crate) mod sealed {
} }
pub trait Instance { pub trait Instance {
fn regs() -> &'static pac::pwm0::RegisterBlock; fn regs() -> &'static pwm0::RegisterBlock;
fn state() -> &'static State; fn state() -> &'static State;
} }
} }
@ -215,7 +221,7 @@ pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static {
macro_rules! impl_pwm { macro_rules! impl_pwm {
($type:ident, $pac_type:ident, $irq:ident) => { ($type:ident, $pac_type:ident, $irq:ident) => {
impl crate::pwm::sealed::Instance for peripherals::$type { impl crate::pwm::sealed::Instance for peripherals::$type {
fn regs() -> &'static pac::pwm0::RegisterBlock { fn regs() -> &'static crate::pwm::pwm0::RegisterBlock {
unsafe { &*pac::$pac_type::ptr() } unsafe { &*pac::$pac_type::ptr() }
} }
fn state() -> &'static crate::pwm::sealed::State { fn state() -> &'static crate::pwm::sealed::State {

View File

@ -10,7 +10,10 @@ use futures::future::poll_fn;
use crate::interrupt; use crate::interrupt;
use crate::{pac, peripherals}; use crate::{pac, peripherals};
#[cfg(not(feature = "nrf9160"))]
use pac::{saadc, SAADC}; use pac::{saadc, SAADC};
#[cfg(feature = "nrf9160")]
use pac::{saadc_ns as saadc, SAADC_NS as SAADC};
pub use saadc::{ pub use saadc::{
ch::{ ch::{
@ -200,7 +203,7 @@ macro_rules! positive_pin_mappings {
// TODO the variant names are unchecked // TODO the variant names are unchecked
// the pins are copied from nrf hal // the pins are copied from nrf hal
#[cfg(feature = "9160")] #[cfg(feature = "nrf9160")]
positive_pin_mappings! { positive_pin_mappings! {
ANALOGINPUT0 => P0_13, ANALOGINPUT0 => P0_13,
ANALOGINPUT1 => P0_14, ANALOGINPUT1 => P0_14,
@ -212,7 +215,7 @@ positive_pin_mappings! {
ANALOGINPUT7 => P0_20, ANALOGINPUT7 => P0_20,
} }
#[cfg(not(feature = "9160"))] #[cfg(not(feature = "nrf9160"))]
positive_pin_mappings! { positive_pin_mappings! {
ANALOGINPUT0 => P0_02, ANALOGINPUT0 => P0_02,
ANALOGINPUT1 => P0_03, ANALOGINPUT1 => P0_03,

View File

@ -17,8 +17,13 @@ use crate::gpio::{OptionalPin, Pin as GpioPin};
use crate::interrupt::Interrupt; use crate::interrupt::Interrupt;
use crate::{pac, util::slice_in_ram_or}; use crate::{pac, util::slice_in_ram_or};
#[cfg(not(feature = "nrf9160"))]
pub(crate) use pac::spim0;
#[cfg(feature = "nrf9160")]
pub(crate) use pac::spim0_ns as spim0;
pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
pub use pac::spim0::frequency::FREQUENCY_A as Frequency; pub use spim0::frequency::FREQUENCY_A as Frequency;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -376,7 +381,7 @@ pub(crate) mod sealed {
} }
pub trait Instance { pub trait Instance {
fn regs() -> &'static pac::spim0::RegisterBlock; fn regs() -> &'static spim0::RegisterBlock;
fn state() -> &'static State; fn state() -> &'static State;
} }
} }
@ -388,7 +393,7 @@ pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static {
macro_rules! impl_spim { macro_rules! impl_spim {
($type:ident, $pac_type:ident, $irq:ident) => { ($type:ident, $pac_type:ident, $irq:ident) => {
impl crate::spim::sealed::Instance for peripherals::$type { impl crate::spim::sealed::Instance for peripherals::$type {
fn regs() -> &'static pac::spim0::RegisterBlock { fn regs() -> &'static crate::spim::spim0::RegisterBlock {
unsafe { &*pac::$pac_type::ptr() } unsafe { &*pac::$pac_type::ptr() }
} }
fn state() -> &'static crate::spim::sealed::State { fn state() -> &'static crate::spim::sealed::State {

View File

@ -9,8 +9,16 @@ use embassy::time::driver::{AlarmHandle, Driver};
use crate::interrupt; use crate::interrupt;
use crate::pac; use crate::pac;
fn rtc() -> &'static pac::rtc0::RegisterBlock { #[cfg(not(feature = "nrf9160"))]
pub(crate) use pac::rtc0;
#[cfg(feature = "nrf9160")]
pub(crate) use pac::rtc0_ns as rtc0;
fn rtc() -> &'static rtc0::RegisterBlock {
#[cfg(not(feature = "nrf9160"))]
unsafe { &*pac::RTC1::ptr() } unsafe { &*pac::RTC1::ptr() }
#[cfg(feature = "nrf9160")]
unsafe { &*pac::RTC1_NS::ptr() }
} }
// RTC timekeeping works with something we call "periods", which are time intervals // RTC timekeeping works with something we call "periods", which are time intervals

View File

@ -15,6 +15,11 @@ use crate::pac;
use crate::ppi::Event; use crate::ppi::Event;
use crate::ppi::Task; use crate::ppi::Task;
#[cfg(not(feature = "nrf9160"))]
pub(crate) use pac::timer0;
#[cfg(feature = "nrf9160")]
pub(crate) use pac::timer0_ns as timer0;
pub(crate) mod sealed { pub(crate) mod sealed {
use super::*; use super::*;
@ -22,7 +27,7 @@ pub(crate) mod sealed {
pub trait Instance { pub trait Instance {
/// The number of CC registers this instance has. /// The number of CC registers this instance has.
const CCS: usize; const CCS: usize;
fn regs() -> &'static pac::timer0::RegisterBlock; fn regs() -> &'static timer0::RegisterBlock;
/// Storage for the waker for CC register `n`. /// Storage for the waker for CC register `n`.
fn waker(n: usize) -> &'static AtomicWaker; fn waker(n: usize) -> &'static AtomicWaker;
} }
@ -40,8 +45,8 @@ macro_rules! impl_timer {
($type:ident, $pac_type:ident, $irq:ident, $ccs:literal) => { ($type:ident, $pac_type:ident, $irq:ident, $ccs:literal) => {
impl crate::timer::sealed::Instance for peripherals::$type { impl crate::timer::sealed::Instance for peripherals::$type {
const CCS: usize = $ccs; const CCS: usize = $ccs;
fn regs() -> &'static pac::timer0::RegisterBlock { fn regs() -> &'static crate::timer::timer0::RegisterBlock {
unsafe { &*(pac::$pac_type::ptr() as *const pac::timer0::RegisterBlock) } unsafe { &*(pac::$pac_type::ptr() as *const crate::timer::timer0::RegisterBlock) }
} }
fn waker(n: usize) -> &'static ::embassy::waitqueue::AtomicWaker { fn waker(n: usize) -> &'static ::embassy::waitqueue::AtomicWaker {
use ::embassy::waitqueue::AtomicWaker; use ::embassy::waitqueue::AtomicWaker;

View File

@ -24,6 +24,11 @@ use crate::gpio::Pin as GpioPin;
use crate::pac; use crate::pac;
use crate::util::{slice_in_ram, slice_in_ram_or}; use crate::util::{slice_in_ram, slice_in_ram_or};
#[cfg(not(feature = "nrf9160"))]
pub(crate) use pac::twim0;
#[cfg(feature = "nrf9160")]
pub(crate) use pac::twim0_ns as twim0;
pub enum Frequency { pub enum Frequency {
#[doc = "26738688: 100 kbps"] #[doc = "26738688: 100 kbps"]
K100 = 26738688, K100 = 26738688,
@ -721,7 +726,7 @@ pub(crate) mod sealed {
} }
pub trait Instance { pub trait Instance {
fn regs() -> &'static pac::twim0::RegisterBlock; fn regs() -> &'static twim0::RegisterBlock;
fn state() -> &'static State; fn state() -> &'static State;
} }
} }
@ -733,7 +738,7 @@ pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static {
macro_rules! impl_twim { macro_rules! impl_twim {
($type:ident, $pac_type:ident, $irq:ident) => { ($type:ident, $pac_type:ident, $irq:ident) => {
impl crate::twim::sealed::Instance for peripherals::$type { impl crate::twim::sealed::Instance for peripherals::$type {
fn regs() -> &'static pac::twim0::RegisterBlock { fn regs() -> &'static crate::twim::twim0::RegisterBlock {
unsafe { &*pac::$pac_type::ptr() } unsafe { &*pac::$pac_type::ptr() }
} }
fn state() -> &'static crate::twim::sealed::State { fn state() -> &'static crate::twim::sealed::State {

View File

@ -22,8 +22,13 @@ use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
use crate::timer::Instance as TimerInstance; use crate::timer::Instance as TimerInstance;
use crate::timer::{Frequency, Timer}; use crate::timer::{Frequency, Timer};
#[cfg(not(feature = "nrf9160"))]
pub(crate) use pac::uarte0;
#[cfg(feature = "nrf9160")]
pub(crate) use pac::uarte0_ns as uarte0;
// Re-export SVD variants to allow user to directly set values. // Re-export SVD variants to allow user to directly set values.
pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; pub use uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
#[non_exhaustive] #[non_exhaustive]
pub struct Config { pub struct Config {
@ -458,7 +463,7 @@ pub(crate) mod sealed {
} }
pub trait Instance { pub trait Instance {
fn regs() -> &'static pac::uarte0::RegisterBlock; fn regs() -> &'static uarte0::RegisterBlock;
fn state() -> &'static State; fn state() -> &'static State;
} }
} }
@ -470,7 +475,7 @@ pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static + Send
macro_rules! impl_uarte { macro_rules! impl_uarte {
($type:ident, $pac_type:ident, $irq:ident) => { ($type:ident, $pac_type:ident, $irq:ident) => {
impl crate::uarte::sealed::Instance for peripherals::$type { impl crate::uarte::sealed::Instance for peripherals::$type {
fn regs() -> &'static pac::uarte0::RegisterBlock { fn regs() -> &'static crate::uarte::uarte0::RegisterBlock {
unsafe { &*pac::$pac_type::ptr() } unsafe { &*pac::$pac_type::ptr() }
} }
fn state() -> &'static crate::uarte::sealed::State { fn state() -> &'static crate::uarte::sealed::State {

View File

@ -3,7 +3,13 @@
//! This HAL implements a basic watchdog timer with 1..=8 handles. //! This HAL implements a basic watchdog timer with 1..=8 handles.
//! Once the watchdog has been started, it cannot be stopped. //! Once the watchdog has been started, it cannot be stopped.
use crate::pac::WDT; use crate::pac;
#[cfg(not(feature = "nrf9160"))]
pub(crate) use pac::WDT;
#[cfg(feature = "nrf9160")]
pub(crate) use pac::WDT_NS as WDT;
use crate::peripherals; use crate::peripherals;
const MIN_TICKS: u32 = 15; const MIN_TICKS: u32 = 15;
@ -58,7 +64,12 @@ impl Watchdog {
let crv = config.timeout_ticks.max(MIN_TICKS); let crv = config.timeout_ticks.max(MIN_TICKS);
let rren = (1u32 << N) - 1; let rren = (1u32 << N) - 1;
if r.runstatus.read().runstatus().bit() { #[cfg(not(feature = "nrf9160"))]
let runstatus = r.runstatus.read().runstatus().bit();
#[cfg(feature = "nrf9160")]
let runstatus = r.runstatus.read().runstatuswdt().bit();
if runstatus {
let curr_config = r.config.read(); let curr_config = r.config.read();
if curr_config.halt().bit() != config.run_during_debug_halt if curr_config.halt().bit() != config.run_during_debug_halt
|| curr_config.sleep().bit() != config.run_during_sleep || curr_config.sleep().bit() != config.run_during_sleep

View File

@ -3,4 +3,4 @@
[toolchain] [toolchain]
channel = "nightly-2021-08-18" channel = "nightly-2021-08-18"
components = [ "rust-src", "rustfmt" ] components = [ "rust-src", "rustfmt" ]
targets = [ "thumbv7em-none-eabi", "thumbv7m-none-eabi", "thumbv6m-none-eabi", "thumbv7em-none-eabihf", "wasm32-unknown-unknown" ] targets = [ "thumbv7em-none-eabi", "thumbv7m-none-eabi", "thumbv6m-none-eabi", "thumbv7em-none-eabihf", "thumbv8m.main-none-eabihf", "wasm32-unknown-unknown" ]