#![no_std] #![feature(generic_associated_types)] #![feature(asm)] #![feature(type_alias_impl_trait)] #[cfg(not(any( feature = "nrf51", feature = "nrf52805", feature = "nrf52810", feature = "nrf52811", feature = "nrf52820", feature = "nrf52832", feature = "nrf52833", feature = "nrf52840", feature = "nrf5340-app-s", feature = "nrf5340-app-ns", feature = "nrf5340-net", feature = "nrf9160-s", feature = "nrf9160-ns", )))] compile_error!("No chip feature activated. You must activate exactly one of the following features: nrf52810, nrf52811, nrf52832, nrf52833, nrf52840"); // This mod MUST go first, so that the others see its macros. pub(crate) mod fmt; pub(crate) mod util; #[cfg(feature = "_time-driver")] mod time_driver; pub mod buffered_uarte; pub mod gpio; #[cfg(feature = "gpiote")] pub mod gpiote; #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] pub mod nvmc; pub mod ppi; #[cfg(not(any(feature = "nrf52805", feature = "nrf52820", feature = "_nrf5340-net")))] pub mod pwm; #[cfg(feature = "nrf52840")] pub mod qspi; #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] pub mod rng; #[cfg(not(any(feature = "nrf52820", feature = "_nrf5340-net")))] pub mod saadc; pub mod spim; #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] pub mod temp; pub mod timer; pub mod twim; pub mod uarte; #[cfg(not(feature = "_nrf5340"))] pub mod wdt; // This mod MUST go last, so that it sees all the `impl_foo!` macros #[cfg_attr(feature = "nrf52805", path = "chips/nrf52805.rs")] #[cfg_attr(feature = "nrf52810", path = "chips/nrf52810.rs")] #[cfg_attr(feature = "nrf52811", path = "chips/nrf52811.rs")] #[cfg_attr(feature = "nrf52820", path = "chips/nrf52820.rs")] #[cfg_attr(feature = "nrf52832", path = "chips/nrf52832.rs")] #[cfg_attr(feature = "nrf52833", path = "chips/nrf52833.rs")] #[cfg_attr(feature = "nrf52840", path = "chips/nrf52840.rs")] #[cfg_attr(feature = "_nrf5340-app", path = "chips/nrf5340_app.rs")] #[cfg_attr(feature = "_nrf5340-net", path = "chips/nrf5340_net.rs")] #[cfg_attr(feature = "_nrf9160", path = "chips/nrf9160.rs")] mod chip; pub use chip::EASY_DMA_SIZE; #[cfg(feature = "unstable-pac")] pub use chip::pac; #[cfg(not(feature = "unstable-pac"))] pub(crate) use chip::pac; pub use chip::{peripherals, Peripherals}; #[cfg(any(feature = "nrf52820", feature = "nrf52833", feature = "nrf52840"))] pub mod usb { use nrf_usbd::{UsbPeripheral, Usbd}; use usb_device::bus::UsbBusAllocator; pub struct UsbBus; unsafe impl UsbPeripheral for UsbBus { const REGISTERS: *const () = crate::pac::USBD::ptr() as *const (); } impl UsbBus { pub fn new() -> UsbBusAllocator> { Usbd::new(UsbBus) } } unsafe impl embassy_hal_common::usb::USBInterrupt for crate::interrupt::USBD {} } pub mod interrupt { pub use crate::chip::irqs::*; pub use cortex_m::interrupt::{CriticalSection, Mutex}; pub use embassy::interrupt::{declare, take, Interrupt}; pub use embassy_hal_common::interrupt::Priority3 as Priority; } pub use embassy_macros::interrupt; pub mod config { pub enum HfclkSource { Internal, ExternalXtal, } pub enum LfclkSource { InternalRC, #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] Synthesized, ExternalXtal, #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] ExternalLowSwing, #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] ExternalFullSwing, } #[non_exhaustive] pub struct Config { pub hfclk_source: HfclkSource, pub lfclk_source: LfclkSource, #[cfg(feature = "gpiote")] pub gpiote_interrupt_priority: crate::interrupt::Priority, #[cfg(feature = "_time-driver")] pub time_interrupt_priority: crate::interrupt::Priority, } impl Default for Config { fn default() -> Self { Self { // There are hobby nrf52 boards out there without external XTALs... // Default everything to internal so it Just Works. User can enable external // xtals if they know they have them. hfclk_source: HfclkSource::Internal, lfclk_source: LfclkSource::InternalRC, #[cfg(feature = "gpiote")] gpiote_interrupt_priority: crate::interrupt::Priority::P0, #[cfg(feature = "_time-driver")] time_interrupt_priority: crate::interrupt::Priority::P0, } } } } pub fn init(config: config::Config) -> Peripherals { // Do this first, so that it panics if user is calling `init` a second time // before doing anything important. let peripherals = Peripherals::take(); let r = unsafe { &*pac::CLOCK::ptr() }; // Start HFCLK. match config.hfclk_source { config::HfclkSource::Internal => {} config::HfclkSource::ExternalXtal => { // Datasheet says this is likely to take 0.36ms r.events_hfclkstarted.write(|w| unsafe { w.bits(0) }); r.tasks_hfclkstart.write(|w| unsafe { w.bits(1) }); while r.events_hfclkstarted.read().bits() == 0 {} } } // Configure LFCLK. #[cfg(not(any(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()), config::LfclkSource::ExternalXtal => r.lfclksrc.write(|w| w.src().xtal()), config::LfclkSource::ExternalLowSwing => r.lfclksrc.write(|w| { w.src().xtal(); w.external().enabled(); w.bypass().disabled(); w }), config::LfclkSource::ExternalFullSwing => r.lfclksrc.write(|w| { w.src().xtal(); w.external().enabled(); w.bypass().enabled(); 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. // Datasheet says this could take 100us from synth source // 600us from rc source, 0.25s from an external source. r.events_lfclkstarted.write(|w| unsafe { w.bits(0) }); r.tasks_lfclkstart.write(|w| unsafe { w.bits(1) }); while r.events_lfclkstarted.read().bits() == 0 {} // Init GPIOTE #[cfg(feature = "gpiote")] gpiote::init(config.gpiote_interrupt_priority); // init RTC time driver #[cfg(feature = "_time-driver")] time_driver::init(config.time_interrupt_priority); peripherals }