Skip to content

Commit

Permalink
feat: add basic support for nRF51 chips to embassy-nrf
Browse files Browse the repository at this point in the history
  • Loading branch information
lulf committed Jan 20, 2024
1 parent 686069b commit df774b1
Show file tree
Hide file tree
Showing 13 changed files with 311 additions and 7 deletions.
8 changes: 8 additions & 0 deletions embassy-nrf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-nrf/s

features = ["time", "defmt", "unstable-pac", "gpiote", "time-driver-rtc1"]
flavors = [
{ regex_feature = "nrf51", target = "thumbv6m-none-eabi" },
{ regex_feature = "nrf52.*", target = "thumbv7em-none-eabihf" },
{ regex_feature = "nrf53.*", target = "thumbv8m.main-none-eabihf" },
{ regex_feature = "nrf91.*", target = "thumbv8m.main-none-eabihf" },
Expand All @@ -28,6 +29,7 @@ rustdoc-args = ["--cfg", "docsrs"]
default = ["rt"]
## Cortex-M runtime (enabled by default)
rt = [
"nrf51-pac?/rt",
"nrf52805-pac?/rt",
"nrf52810-pac?/rt",
"nrf52811-pac?/rt",
Expand Down Expand Up @@ -71,6 +73,8 @@ reset-pin-as-gpio = []
qspi-multiwrite-flash = []

#! ### Chip selection features
## nRF51
nrf51 = ["nrf51-pac", "_nrf51", "portable-atomic/unsafe-assume-single-core"]
## nRF52805
nrf52805 = ["nrf52805-pac", "_nrf52"]
## nRF52810
Expand Down Expand Up @@ -104,6 +108,7 @@ _nrf5340-net = ["_nrf5340", "nrf5340-net-pac"]
_nrf5340 = ["_gpio-p1", "_dppi"]
_nrf9160 = ["nrf9160-pac", "_dppi"]
_nrf52 = ["_ppi"]
_nrf51 = ["_ppi"]

_time-driver = ["dep:embassy-time-driver", "embassy-time-driver?/tick-hz-32_768"]

Expand Down Expand Up @@ -132,6 +137,8 @@ embedded-hal-async = { version = "1.0" }
embedded-io = { version = "0.6.0" }
embedded-io-async = { version = "0.6.1" }

portable-atomic = { version = "1", default-features = false, features = ["require-cas"] }

defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }
cortex-m-rt = ">=0.6.15,<0.8"
Expand All @@ -144,6 +151,7 @@ embedded-storage-async = "0.4.0"
cfg-if = "1.0.0"
document-features = "0.2.7"

nrf51-pac = { version = "0.12.0", optional = true }
nrf52805-pac = { version = "0.12.0", optional = true }
nrf52810-pac = { version = "0.12.0", optional = true }
nrf52811-pac = { version = "0.12.0", optional = true }
Expand Down
168 changes: 168 additions & 0 deletions embassy-nrf/src/chips/nrf51.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
pub use nrf51_pac as pac;

/// The maximum buffer size that the EasyDMA can send/recv in one operation.
pub const EASY_DMA_SIZE: usize = (1 << 14) - 1;
pub const FORCE_COPY_BUFFER_SIZE: usize = 256;

pub const FLASH_SIZE: usize = 128 * 1024;

embassy_hal_internal::peripherals! {
// RTC
RTC0,
RTC1,

// WDT
WDT,

// NVMC
NVMC,

// RNG
RNG,

// UARTE
UART0,

// SPI/TWI
TWI0,
SPI0,

// ADC
ADC,

// TIMER
TIMER0,
TIMER1,
TIMER2,

// GPIOTE
GPIOTE_CH0,
GPIOTE_CH1,
GPIOTE_CH2,
GPIOTE_CH3,

// 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,

// 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,

// TEMP
TEMP,
}

// impl_timer!(TIMER0, TIMER0, TIMER0);
// impl_timer!(TIMER1, TIMER1, TIMER1);
// impl_timer!(TIMER2, TIMER2, 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);

embassy_hal_internal::interrupt_mod!(
POWER_CLOCK,
RADIO,
UART0,
SPI0_TWI0,
SPI1_TWI1,
GPIOTE,
ADC,
TIMER0,
TIMER1,
TIMER2,
RTC0,
TEMP,
RNG,
ECB,
CCM_AAR,
WDT,
RTC1,
QDEC,
LPCOMP,
SWI0,
SWI1,
SWI2,
SWI3,
SWI4,
SWI5,
);
12 changes: 12 additions & 0 deletions embassy-nrf/src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,17 @@ use cfg_if::cfg_if;
use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};

use self::sealed::Pin as _;

#[cfg(not(feature = "nrf51"))]
use crate::pac::p0 as gpio;
#[cfg(not(feature = "nrf51"))]
use crate::pac::p0::pin_cnf::{DRIVE_A, PULL_A};

#[cfg(feature = "nrf51")]
use crate::pac::gpio;
#[cfg(feature = "nrf51")]
use crate::pac::gpio::pin_cnf::{DRIVE_A, PULL_A};

use crate::{pac, Peripheral};

/// A GPIO port with up to 32 pins.
Expand Down Expand Up @@ -376,6 +385,9 @@ pub(crate) mod sealed {
fn block(&self) -> &gpio::RegisterBlock {
unsafe {
match self.pin_port() / 32 {
#[cfg(feature = "nrf51")]
0 => &*pac::GPIO::ptr(),
#[cfg(not(feature = "nrf51"))]
0 => &*pac::P0::ptr(),
#[cfg(feature = "_gpio-p1")]
1 => &*pac::P1::ptr(),
Expand Down
19 changes: 16 additions & 3 deletions embassy-nrf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub(crate) mod util;
#[cfg(feature = "_time-driver")]
mod time_driver;

#[cfg(not(feature = "nrf51"))]
pub mod buffered_uarte;
pub mod gpio;
#[cfg(feature = "gpiote")]
Expand All @@ -58,23 +59,33 @@ pub mod nvmc;
))]
pub mod pdm;
pub mod ppi;
#[cfg(not(any(feature = "nrf52805", feature = "nrf52820", feature = "_nrf5340-net")))]
#[cfg(not(any(
feature = "nrf51",
feature = "nrf52805",
feature = "nrf52820",
feature = "_nrf5340-net"
)))]
pub mod pwm;
#[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340-net")))]
pub mod qdec;
#[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))]
pub mod qspi;
#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf9160")))]
pub mod rng;
#[cfg(not(any(feature = "nrf52820", feature = "_nrf5340-net")))]
#[cfg(not(any(feature = "nrf51", feature = "nrf52820", feature = "_nrf5340-net")))]
pub mod saadc;
#[cfg(not(feature = "nrf51"))]
pub mod spim;
#[cfg(not(feature = "nrf51"))]
pub mod spis;
#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
pub mod temp;
pub mod timer;
#[cfg(not(feature = "nrf51"))]
pub mod twim;
#[cfg(not(feature = "nrf51"))]
pub mod twis;
#[cfg(not(feature = "nrf51"))]
pub mod uarte;
#[cfg(any(
feature = "_nrf5340-app",
Expand All @@ -87,6 +98,7 @@ pub mod usb;
pub mod wdt;

// This mod MUST go last, so that it sees all the `impl_foo!` macros
#[cfg_attr(feature = "nrf51", path = "chips/nrf51.rs")]
#[cfg_attr(feature = "nrf52805", path = "chips/nrf52805.rs")]
#[cfg_attr(feature = "nrf52810", path = "chips/nrf52810.rs")]
#[cfg_attr(feature = "nrf52811", path = "chips/nrf52811.rs")]
Expand Down Expand Up @@ -374,6 +386,7 @@ pub fn init(config: config::Config) -> Peripherals {
let mut needs_reset = false;

// Setup debug protection.
#[cfg(not(feature = "nrf51"))]
match config.debug {
config::Debug::Allowed => {
#[cfg(feature = "_nrf52")]
Expand Down Expand Up @@ -489,7 +502,7 @@ pub fn init(config: config::Config) -> Peripherals {
}

// Configure LFCLK.
#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
#[cfg(not(any(feature = "nrf51", feature = "_nrf5340", feature = "_nrf9160")))]
match config.lfclk_source {
config::LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().rc()),
config::LfclkSource::Synthesized => r.lfclksrc.write(|w| w.src().synth()),
Expand Down
1 change: 1 addition & 0 deletions embassy-nrf/src/ppi/ppi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> Drop for
let n = self.ch.number();
r.ch[n].eep.write(|w| unsafe { w.bits(0) });
r.ch[n].tep.write(|w| unsafe { w.bits(0) });
#[cfg(not(feature = "nrf51"))]
r.fork[n].tep.write(|w| unsafe { w.bits(0) });
}
}
2 changes: 1 addition & 1 deletion embassy-nrf/src/rng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use core::future::poll_fn;
use core::marker::PhantomData;
use core::ptr;
use core::sync::atomic::{AtomicPtr, Ordering};
use portable_atomic::{AtomicPtr, Ordering};
use core::task::Poll;

use embassy_hal_internal::drop::OnDrop;
Expand Down
2 changes: 1 addition & 1 deletion embassy-nrf/src/time_driver.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core::cell::Cell;
use core::sync::atomic::{compiler_fence, AtomicU32, AtomicU8, Ordering};
use core::{mem, ptr};
use portable_atomic::{compiler_fence, AtomicU32, AtomicU8, Ordering};

use critical_section::CriticalSection;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
Expand Down
16 changes: 14 additions & 2 deletions embassy-nrf/src/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,16 @@ impl<'d, T: Instance> Timer<'d, T> {
// since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification.
this.stop();

#[cfg(not(feature = "nrf51"))]
if is_counter {
regs.mode.write(|w| w.mode().low_power_counter());
} else {
regs.mode.write(|w| w.mode().timer());
}

#[cfg(feature = "nrf51")]
regs.mode.write(|w| w.mode().timer());

// Make the counter's max value as high as possible.
// TODO: is there a reason someone would want to set this lower?
regs.bitmode.write(|w| w.bitmode()._32bit());
Expand Down Expand Up @@ -238,15 +242,23 @@ pub struct Cc<'d, T: Instance> {
impl<'d, T: Instance> Cc<'d, T> {
/// Get the current value stored in the register.
pub fn read(&self) -> u32 {
T::regs().cc[self.n].read().cc().bits()
#[cfg(not(feature = "nrf51"))]
return T::regs().cc[self.n].read().cc().bits();

#[cfg(feature = "nrf51")]
return T::regs().cc[self.n].read().bits();
}

/// Set the value stored in the register.
///
/// `event_compare` will fire when the timer's counter reaches this value.
pub fn write(&self, value: u32) {
// SAFETY: there are no invalid values for the CC register.
T::regs().cc[self.n].write(|w| unsafe { w.cc().bits(value) })
#[cfg(not(feature = "nrf51"))]
T::regs().cc[self.n].write(|w| unsafe { w.cc().bits(value) });

#[cfg(feature = "nrf51")]
T::regs().cc[self.n].write(|w| unsafe { w.bits(value) });
}

/// Capture the current value of the timer's counter in this register, and return it.
Expand Down
9 changes: 9 additions & 0 deletions examples/nrf51/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
# replace nRF82840_xxAA with your chip as listed in `probe-rs chip list`
runner = "probe-rs run --chip nRF51822_xxAA"

[build]
target = "thumbv6m-none-eabi"

[env]
DEFMT_LOG = "trace"
Loading

0 comments on commit df774b1

Please sign in to comment.