From 0310e4d458b86df31f1765104eb3aa9a6ee09bfc Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 12 May 2021 01:57:01 +0200 Subject: [PATCH] Add `init` fn. Initializes hw and returns Peripherals. --- embassy-extras/src/macros.rs | 13 +-- embassy-macros/src/chip/nrf.rs | 2 +- embassy-macros/src/chip/rp.rs | 2 +- embassy-macros/src/lib.rs | 6 +- embassy-nrf-examples/src/bin/blinky.rs | 3 +- embassy-nrf-examples/src/bin/buffered_uart.rs | 4 +- .../src/bin/executor_fairness_test.rs | 4 +- .../src/bin/gpiote_channel.rs | 6 +- embassy-nrf-examples/src/bin/gpiote_port.rs | 4 +- embassy-nrf-examples/src/bin/multiprio.rs | 3 +- embassy-nrf-examples/src/bin/ppi.rs | 4 +- embassy-nrf-examples/src/bin/qspi.rs | 4 +- embassy-nrf-examples/src/bin/raw_spawn.rs | 3 +- embassy-nrf-examples/src/bin/spim.rs | 4 +- embassy-nrf-examples/src/bin/timer.rs | 3 +- embassy-nrf-examples/src/bin/uart.rs | 32 +----- embassy-nrf-examples/src/bin/uart_idle.rs | 4 +- embassy-nrf/src/lib.rs | 86 ++++++++++++++- embassy-nrf/src/system.rs | 79 -------------- embassy-rp-examples/src/bin/blinky.rs | 4 +- embassy-rp-examples/src/bin/button.rs | 4 +- embassy-rp-examples/src/bin/uart.rs | 4 +- embassy-rp/src/lib.rs | 103 +++++++++++++++++- embassy-rp/src/system.rs | 94 ---------------- 24 files changed, 217 insertions(+), 258 deletions(-) delete mode 100644 embassy-nrf/src/system.rs delete mode 100644 embassy-rp/src/system.rs diff --git a/embassy-extras/src/macros.rs b/embassy-extras/src/macros.rs index 860c0795..fba75261 100644 --- a/embassy-extras/src/macros.rs +++ b/embassy-extras/src/macros.rs @@ -46,18 +46,17 @@ macro_rules! peripherals { impl Peripherals { ///Returns all the peripherals *once* #[inline] - pub fn take() -> Option { + pub(crate) fn take() -> Self { #[no_mangle] static mut _EMBASSY_DEVICE_PERIPHERALS: bool = false; - critical_section::with(|_| { - if unsafe { _EMBASSY_DEVICE_PERIPHERALS } { - None - } else { - unsafe { _EMBASSY_DEVICE_PERIPHERALS = true }; - Some(unsafe { ::steal() }) + critical_section::with(|_| unsafe { + if _EMBASSY_DEVICE_PERIPHERALS { + panic!("init called more than once!") } + _EMBASSY_DEVICE_PERIPHERALS = true; + ::steal() }) } } diff --git a/embassy-macros/src/chip/nrf.rs b/embassy-macros/src/chip/nrf.rs index aba4c004..503a8ba5 100644 --- a/embassy-macros/src/chip/nrf.rs +++ b/embassy-macros/src/chip/nrf.rs @@ -9,7 +9,7 @@ pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream quote!( use #embassy_nrf_path::{interrupt, peripherals, rtc}; - unsafe { #embassy_nrf_path::system::configure(#config) }; + let p = #embassy_nrf_path::init(#config); let mut rtc = rtc::RTC::new(unsafe { ::steal() }, interrupt::take!(RTC1)); let rtc = unsafe { make_static(&mut rtc) }; diff --git a/embassy-macros/src/chip/rp.rs b/embassy-macros/src/chip/rp.rs index 33863de8..04211f8f 100644 --- a/embassy-macros/src/chip/rp.rs +++ b/embassy-macros/src/chip/rp.rs @@ -7,6 +7,6 @@ pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream quote!( use #embassy_rp_path::{interrupt, peripherals}; - unsafe { #embassy_rp_path::system::configure(#config) }; + let p = #embassy_rp_path::init(#config); ) } diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index d91549ca..dc234cd6 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs @@ -315,12 +315,12 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream { let args = task_fn.sig.inputs.clone(); - if args.len() != 1 { + if args.len() != 2 { task_fn .sig .span() .unwrap() - .error("main function must have one argument") + .error("main function must have 2 arguments") .emit(); fail = true; } @@ -364,7 +364,7 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream { #chip_setup executor.run(|spawner| { - spawner.spawn(__embassy_main(spawner)).unwrap(); + spawner.spawn(__embassy_main(spawner, p)).unwrap(); }) } diff --git a/embassy-nrf-examples/src/bin/blinky.rs b/embassy-nrf-examples/src/bin/blinky.rs index 4cb09bee..e6fc854b 100644 --- a/embassy-nrf-examples/src/bin/blinky.rs +++ b/embassy-nrf-examples/src/bin/blinky.rs @@ -17,8 +17,7 @@ use embassy_nrf::Peripherals; use embedded_hal::digital::v2::OutputPin; #[embassy::main] -async fn main(spawner: Spawner) { - let p = Peripherals::take().unwrap(); +async fn main(spawner: Spawner, p: Peripherals) { let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); loop { diff --git a/embassy-nrf-examples/src/bin/buffered_uart.rs b/embassy-nrf-examples/src/bin/buffered_uart.rs index 8f5d9fb2..b3a621c6 100644 --- a/embassy-nrf-examples/src/bin/buffered_uart.rs +++ b/embassy-nrf-examples/src/bin/buffered_uart.rs @@ -17,9 +17,7 @@ use example_common::*; use futures::pin_mut; #[embassy::main] -async fn main(spawner: Spawner) { - let p = Peripherals::take().unwrap(); - +async fn main(spawner: Spawner, p: Peripherals) { let mut config = uarte::Config::default(); config.parity = uarte::Parity::EXCLUDED; config.baudrate = uarte::Baudrate::BAUD115200; diff --git a/embassy-nrf-examples/src/bin/executor_fairness_test.rs b/embassy-nrf-examples/src/bin/executor_fairness_test.rs index 3ea74316..ca9bcc1e 100644 --- a/embassy-nrf-examples/src/bin/executor_fairness_test.rs +++ b/embassy-nrf-examples/src/bin/executor_fairness_test.rs @@ -13,7 +13,7 @@ use core::task::Poll; use defmt::panic; use embassy::executor::Spawner; use embassy::time::{Duration, Instant, Timer}; -use embassy_nrf::interrupt; +use embassy_nrf::{interrupt, Peripherals}; #[embassy::task] async fn run1() { @@ -40,7 +40,7 @@ async fn run3() { } #[embassy::main] -async fn main(spawner: Spawner) { +async fn main(spawner: Spawner, p: Peripherals) { unwrap!(spawner.spawn(run1())); unwrap!(spawner.spawn(run2())); unwrap!(spawner.spawn(run3())); diff --git a/embassy-nrf-examples/src/bin/gpiote_channel.rs b/embassy-nrf-examples/src/bin/gpiote_channel.rs index ee670acd..d52ed776 100644 --- a/embassy-nrf-examples/src/bin/gpiote_channel.rs +++ b/embassy-nrf-examples/src/bin/gpiote_channel.rs @@ -12,13 +12,11 @@ use example_common::*; use defmt::panic; use embassy::executor::Spawner; use embassy_nrf::gpio::{Input, Pull}; -use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity}; +use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; use embassy_nrf::{interrupt, Peripherals}; #[embassy::main] -async fn main(spawner: Spawner) { - let p = Peripherals::take().unwrap(); - +async fn main(spawner: Spawner, p: Peripherals) { info!("Starting!"); let ch1 = InputChannel::new( diff --git a/embassy-nrf-examples/src/bin/gpiote_port.rs b/embassy-nrf-examples/src/bin/gpiote_port.rs index 717d3398..4a7951cd 100644 --- a/embassy-nrf-examples/src/bin/gpiote_port.rs +++ b/embassy-nrf-examples/src/bin/gpiote_port.rs @@ -28,9 +28,7 @@ async fn button_task(n: usize, mut pin: PortInput<'static, AnyPin>) { } #[embassy::main] -async fn main(spawner: Spawner) { - let p = Peripherals::take().unwrap(); - +async fn main(spawner: Spawner, p: Peripherals) { info!("Starting!"); let btn1 = PortInput::new(Input::new(p.P0_11.degrade(), Pull::Up)); diff --git a/embassy-nrf-examples/src/bin/multiprio.rs b/embassy-nrf-examples/src/bin/multiprio.rs index 9ed5c136..79fa029b 100644 --- a/embassy-nrf-examples/src/bin/multiprio.rs +++ b/embassy-nrf-examples/src/bin/multiprio.rs @@ -126,9 +126,8 @@ static EXECUTOR_LOW: Forever = Forever::new(); fn main() -> ! { info!("Hello World!"); - let p = unwrap!(embassy_nrf::Peripherals::take()); + let p = embassy_nrf::init(Default::default()); - unsafe { embassy_nrf::system::configure(Default::default()) }; let rtc = RTC.put(rtc::RTC::new(p.RTC1, interrupt::take!(RTC1))); rtc.start(); unsafe { embassy::time::set_clock(rtc) }; diff --git a/embassy-nrf-examples/src/bin/ppi.rs b/embassy-nrf-examples/src/bin/ppi.rs index 3c39e032..47782ed2 100644 --- a/embassy-nrf-examples/src/bin/ppi.rs +++ b/embassy-nrf-examples/src/bin/ppi.rs @@ -19,9 +19,7 @@ use embassy_nrf::{interrupt, Peripherals}; use gpiote::{OutputChannel, OutputChannelPolarity}; #[embassy::main] -async fn main(spawner: Spawner) { - let p = Peripherals::take().unwrap(); - +async fn main(spawner: Spawner, p: Peripherals) { info!("Starting!"); let button1 = InputChannel::new( diff --git a/embassy-nrf-examples/src/bin/qspi.rs b/embassy-nrf-examples/src/bin/qspi.rs index 28cde6e5..3dc027f6 100644 --- a/embassy-nrf-examples/src/bin/qspi.rs +++ b/embassy-nrf-examples/src/bin/qspi.rs @@ -23,9 +23,7 @@ const PAGE_SIZE: usize = 4096; struct AlignedBuf([u8; 4096]); #[embassy::main] -async fn main(spawner: Spawner) { - let p = Peripherals::take().unwrap(); - +async fn main(spawner: Spawner, p: Peripherals) { let csn = p.P0_17; let sck = p.P0_19; let io0 = p.P0_20; diff --git a/embassy-nrf-examples/src/bin/raw_spawn.rs b/embassy-nrf-examples/src/bin/raw_spawn.rs index f8e021d9..78de7b10 100644 --- a/embassy-nrf-examples/src/bin/raw_spawn.rs +++ b/embassy-nrf-examples/src/bin/raw_spawn.rs @@ -37,9 +37,8 @@ static EXECUTOR: Forever = Forever::new(); fn main() -> ! { info!("Hello World!"); - let p = unwrap!(embassy_nrf::Peripherals::take()); + let p = embassy_nrf::init(Default::default()); - unsafe { embassy_nrf::system::configure(Default::default()) }; let rtc = RTC.put(rtc::RTC::new(p.RTC1, interrupt::take!(RTC1))); rtc.start(); unsafe { embassy::time::set_clock(rtc) }; diff --git a/embassy-nrf-examples/src/bin/spim.rs b/embassy-nrf-examples/src/bin/spim.rs index ccda7576..df921fc8 100644 --- a/embassy-nrf-examples/src/bin/spim.rs +++ b/embassy-nrf-examples/src/bin/spim.rs @@ -19,11 +19,9 @@ use embedded_hal::digital::v2::*; use example_common::*; #[embassy::main] -async fn main(spawner: Spawner) { +async fn main(spawner: Spawner, p: Peripherals) { info!("running!"); - let p = unsafe { Peripherals::steal() }; - let mut config = spim::Config::default(); config.frequency = spim::Frequency::M16; diff --git a/embassy-nrf-examples/src/bin/timer.rs b/embassy-nrf-examples/src/bin/timer.rs index a2b717bc..ffbbb784 100644 --- a/embassy-nrf-examples/src/bin/timer.rs +++ b/embassy-nrf-examples/src/bin/timer.rs @@ -7,6 +7,7 @@ #[path = "../example_common.rs"] mod example_common; +use embassy_nrf::Peripherals; use example_common::*; use defmt::panic; @@ -30,7 +31,7 @@ async fn run2() { } #[embassy::main] -async fn main(spawner: Spawner) { +async fn main(spawner: Spawner, p: Peripherals) { unwrap!(spawner.spawn(run1())); unwrap!(spawner.spawn(run2())); } diff --git a/embassy-nrf-examples/src/bin/uart.rs b/embassy-nrf-examples/src/bin/uart.rs index 23fc8931..9a0e65d3 100644 --- a/embassy-nrf-examples/src/bin/uart.rs +++ b/embassy-nrf-examples/src/bin/uart.rs @@ -17,9 +17,7 @@ use embassy_nrf::gpio::NoPin; use embassy_nrf::{interrupt, uarte, Peripherals}; #[embassy::main] -async fn main(spawner: Spawner) { - let p = unsafe { Peripherals::steal() }; - +async fn main(spawner: Spawner, p: Peripherals) { let mut config = uarte::Config::default(); config.parity = uarte::Parity::EXCLUDED; config.baudrate = uarte::Baudrate::BAUD115200; @@ -42,33 +40,5 @@ async fn main(spawner: Spawner) { unwrap!(uart.read(&mut buf).await); info!("writing..."); unwrap!(uart.write(&buf).await); - - /* - // `receive()` doesn't return until the buffer has been completely filled with - // incoming data, which in this case is 8 bytes. - // - // This example shows how to use `select` to run an uart receive concurrently with a - // 1 second timer, effectively adding a timeout to the receive operation. - let recv_fut = uart.read(&mut buf); - let timer_fut = Timer::after(Duration::from_millis(1000)); - let received_len = match select(recv_fut, timer_fut).await { - // recv_fut completed first, so we've received `buf_len` bytes. - Either::Left(_) => buf_len, - // timer_fut completed first. `select` gives us back the future that didn't complete, which - // is `recv_fut` in this case, so we can do further stuff with it. - // - // The recv_fut would stop the uart read automatically when dropped. However, we want to know how - // many bytes have been received, so we have to "gracefully stop" it with `.stop()`. - Either::Right((_, recv_fut)) => recv_fut.stop().await, - }; - let received = &mut buf[..received_len]; - - if !received.is_empty() { - info!("read done, got {}", received); - - // Echo back received data - unwrap!(uart.write(received).await); - } - */ } } diff --git a/embassy-nrf-examples/src/bin/uart_idle.rs b/embassy-nrf-examples/src/bin/uart_idle.rs index 54d524ae..a97c6593 100644 --- a/embassy-nrf-examples/src/bin/uart_idle.rs +++ b/embassy-nrf-examples/src/bin/uart_idle.rs @@ -18,9 +18,7 @@ use embassy_nrf::gpio::NoPin; use embassy_nrf::{interrupt, uarte, Peripherals}; #[embassy::main] -async fn main(spawner: Spawner) { - let p = unsafe { Peripherals::steal() }; - +async fn main(spawner: Spawner, p: Peripherals) { let mut config = uarte::Config::default(); config.parity = uarte::Parity::EXCLUDED; config.baudrate = uarte::Baudrate::BAUD115200; diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 4349bf39..6ab9cbb2 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -35,7 +35,6 @@ pub mod rtc; #[cfg(not(feature = "nrf52820"))] pub mod saadc; pub mod spim; -pub mod system; pub mod timer; pub mod twim; pub mod uarte; @@ -73,3 +72,88 @@ pub mod interrupt { pub use embassy_extras::interrupt::Priority3 as Priority; } pub use embassy_macros::interrupt; + +pub mod config { + pub enum HfclkSource { + Internal, + ExternalXtal, + } + + pub enum LfclkSource { + InternalRC, + Synthesized, + ExternalXtal, + ExternalLowSwing, + ExternalFullSwing, + } + + #[non_exhaustive] + pub struct Config { + pub hfclk_source: HfclkSource, + pub lfclk_source: LfclkSource, + } + + 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, + } + } + } +} + +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. + 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 + }), + } + + // 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 + crate::gpiote::init(); + + peripherals +} diff --git a/embassy-nrf/src/system.rs b/embassy-nrf/src/system.rs deleted file mode 100644 index e358d2c3..00000000 --- a/embassy-nrf/src/system.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::pac; - -pub enum HfclkSource { - Internal, - ExternalXtal, -} - -pub enum LfclkSource { - InternalRC, - Synthesized, - ExternalXtal, - ExternalLowSwing, - ExternalFullSwing, -} - -#[non_exhaustive] -pub struct Config { - pub hfclk_source: HfclkSource, - pub lfclk_source: LfclkSource, -} - -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, - } - } -} - -/// safety: must only call once. -pub unsafe fn configure(config: Config) { - let r = &*pac::CLOCK::ptr(); - - // Start HFCLK. - match config.hfclk_source { - HfclkSource::Internal => {} - 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. - match config.lfclk_source { - LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().rc()), - LfclkSource::Synthesized => r.lfclksrc.write(|w| w.src().synth()), - - LfclkSource::ExternalXtal => r.lfclksrc.write(move |w| w.src().xtal()), - - LfclkSource::ExternalLowSwing => r.lfclksrc.write(move |w| { - w.src().xtal(); - w.external().enabled(); - w.bypass().disabled(); - w - }), - LfclkSource::ExternalFullSwing => r.lfclksrc.write(move |w| { - w.src().xtal(); - w.external().enabled(); - w.bypass().enabled(); - w - }), - } - - // 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 - crate::gpiote::init(); -} diff --git a/embassy-rp-examples/src/bin/blinky.rs b/embassy-rp-examples/src/bin/blinky.rs index 34e3cafc..e4299991 100644 --- a/embassy-rp-examples/src/bin/blinky.rs +++ b/embassy-rp-examples/src/bin/blinky.rs @@ -16,9 +16,7 @@ use embedded_hal::digital::v2::OutputPin; use gpio::{Level, Output}; #[embassy::main] -async fn main(_spawner: Spawner) { - let p = unwrap!(Peripherals::take()); - +async fn main(_spawner: Spawner, p: Peripherals) { let mut led = Output::new(p.PIN_25, Level::Low); loop { diff --git a/embassy-rp-examples/src/bin/button.rs b/embassy-rp-examples/src/bin/button.rs index 77d4c57a..007d07a3 100644 --- a/embassy-rp-examples/src/bin/button.rs +++ b/embassy-rp-examples/src/bin/button.rs @@ -16,9 +16,7 @@ use embassy_rp::Peripherals; use embedded_hal::digital::v2::{InputPin, OutputPin}; #[embassy::main] -async fn main(_spawner: Spawner) { - let p = unwrap!(Peripherals::take()); - +async fn main(_spawner: Spawner, p: Peripherals) { let button = Input::new(p.PIN_28, Pull::Up); let mut led = Output::new(p.PIN_25, Level::Low); diff --git a/embassy-rp-examples/src/bin/uart.rs b/embassy-rp-examples/src/bin/uart.rs index cd72d531..82bd4cb6 100644 --- a/embassy-rp-examples/src/bin/uart.rs +++ b/embassy-rp-examples/src/bin/uart.rs @@ -14,9 +14,7 @@ use embassy::executor::Spawner; use embassy_rp::{uart, Peripherals}; #[embassy::main] -async fn main(_spanwer: Spawner) { - let p = unwrap!(Peripherals::take()); - +async fn main(_spawner: Spawner, p: Peripherals) { let config = uart::Config::default(); let mut uart = uart::Uart::new(p.UART0, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, config); uart.send("Hello World!\r\n".as_bytes()); diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index f64464d1..f1a04598 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -15,7 +15,6 @@ pub mod dma; pub mod gpio; pub mod pll; pub mod resets; -pub mod system; pub mod uart; embassy_extras::peripherals! { @@ -72,3 +71,105 @@ embassy_extras::peripherals! { DMA_CH10, DMA_CH11, } + +#[link_section = ".boot2"] +#[used] +static BOOT2: [u8; 256] = *include_bytes!("boot2.bin"); + +pub mod config { + #[non_exhaustive] + pub struct Config {} + + impl Default for Config { + fn default() -> Self { + Self {} + } + } +} + +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(); + + // Now reset all the peripherals, except QSPI and XIP (we're using those + // to execute from external flash!) + + let resets = resets::Resets::new(); + + // Reset everything except: + // - QSPI (we're using it to run this code!) + // - PLLs (it may be suicide if that's what's clocking us) + let mut peris = resets::ALL_PERIPHERALS; + peris.set_io_qspi(false); + peris.set_pads_qspi(false); + peris.set_pll_sys(false); + peris.set_pll_usb(false); + resets.reset(peris); + + let mut peris = resets::ALL_PERIPHERALS; + peris.set_adc(false); + peris.set_rtc(false); + peris.set_spi0(false); + peris.set_spi1(false); + peris.set_uart0(false); + peris.set_uart1(false); + peris.set_usbctrl(false); + resets.unreset_wait(peris); + + unsafe { + // xosc 12 mhz + pac::WATCHDOG.tick().write(|w| { + w.set_cycles(XOSC_MHZ as u16); + w.set_enable(true); + }); + + pac::CLOCKS + .clk_sys_resus_ctrl() + .write_value(pac::clocks::regs::ClkSysResusCtrl(0)); + + // Enable XOSC + // TODO extract to HAL module + const XOSC_MHZ: u32 = 12; + pac::XOSC + .ctrl() + .write(|w| w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ)); + + let startup_delay = (((XOSC_MHZ * 1_000_000) / 1000) + 128) / 256; + pac::XOSC + .startup() + .write(|w| w.set_delay(startup_delay as u16)); + pac::XOSC.ctrl().write(|w| { + w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ); + w.set_enable(pac::xosc::vals::CtrlEnable::ENABLE); + }); + while !pac::XOSC.status().read().stable() {} + + // Before we touch PLLs, switch sys and ref cleanly away from their aux sources. + pac::CLOCKS + .clk_sys_ctrl() + .modify(|w| w.set_src(pac::clocks::vals::ClkSysCtrlSrc::CLK_REF)); + while pac::CLOCKS.clk_sys_selected().read() != 1 {} + pac::CLOCKS + .clk_ref_ctrl() + .modify(|w| w.set_src(pac::clocks::vals::ClkRefCtrlSrc::ROSC_CLKSRC_PH)); + while pac::CLOCKS.clk_ref_selected().read() != 1 {} + + let mut peris = resets::Peripherals(0); + peris.set_pll_sys(true); + peris.set_pll_usb(true); + resets.reset(peris); + resets.unreset_wait(peris); + + pll::PLL::new(pll::PllSys).configure(1, 1500_000_000, 6, 2); + pll::PLL::new(pll::PllUsb).configure(1, 480_000_000, 5, 2); + + // Activate peripheral clock and take external oscillator as input + pac::CLOCKS.clk_peri_ctrl().write(|w| { + w.set_enable(true); + w.set_auxsrc(pac::clocks::vals::ClkPeriCtrlAuxsrc::XOSC_CLKSRC); + }); + } + + peripherals +} diff --git a/embassy-rp/src/system.rs b/embassy-rp/src/system.rs deleted file mode 100644 index ba139643..00000000 --- a/embassy-rp/src/system.rs +++ /dev/null @@ -1,94 +0,0 @@ -use crate::{pac, pll, resets}; - -#[link_section = ".boot2"] -#[used] -pub static BOOT2: [u8; 256] = *include_bytes!("boot2.bin"); - -#[non_exhaustive] -pub struct Config {} - -impl Default for Config { - fn default() -> Self { - Self {} - } -} - -/// safety: must only call once. -pub unsafe fn configure(_config: Config) { - // Now reset all the peripherals, except QSPI and XIP (we're using those - // to execute from external flash!) - - let resets = resets::Resets::new(); - - // Reset everything except: - // - QSPI (we're using it to run this code!) - // - PLLs (it may be suicide if that's what's clocking us) - let mut peris = resets::ALL_PERIPHERALS; - peris.set_io_qspi(false); - peris.set_pads_qspi(false); - peris.set_pll_sys(false); - peris.set_pll_usb(false); - resets.reset(peris); - - let mut peris = resets::ALL_PERIPHERALS; - peris.set_adc(false); - peris.set_rtc(false); - peris.set_spi0(false); - peris.set_spi1(false); - peris.set_uart0(false); - peris.set_uart1(false); - peris.set_usbctrl(false); - resets.unreset_wait(peris); - - // xosc 12 mhz - pac::WATCHDOG.tick().write(|w| { - w.set_cycles(XOSC_MHZ as u16); - w.set_enable(true); - }); - - pac::CLOCKS - .clk_sys_resus_ctrl() - .write_value(pac::clocks::regs::ClkSysResusCtrl(0)); - - // Enable XOSC - // TODO extract to HAL module - const XOSC_MHZ: u32 = 12; - pac::XOSC - .ctrl() - .write(|w| w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ)); - - let startup_delay = (((XOSC_MHZ * 1_000_000) / 1000) + 128) / 256; - pac::XOSC - .startup() - .write(|w| w.set_delay(startup_delay as u16)); - pac::XOSC.ctrl().write(|w| { - w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ); - w.set_enable(pac::xosc::vals::CtrlEnable::ENABLE); - }); - while !pac::XOSC.status().read().stable() {} - - // Before we touch PLLs, switch sys and ref cleanly away from their aux sources. - pac::CLOCKS - .clk_sys_ctrl() - .modify(|w| w.set_src(pac::clocks::vals::ClkSysCtrlSrc::CLK_REF)); - while pac::CLOCKS.clk_sys_selected().read() != 1 {} - pac::CLOCKS - .clk_ref_ctrl() - .modify(|w| w.set_src(pac::clocks::vals::ClkRefCtrlSrc::ROSC_CLKSRC_PH)); - while pac::CLOCKS.clk_ref_selected().read() != 1 {} - - let mut peris = resets::Peripherals(0); - peris.set_pll_sys(true); - peris.set_pll_usb(true); - resets.reset(peris); - resets.unreset_wait(peris); - - pll::PLL::new(pll::PllSys).configure(1, 1500_000_000, 6, 2); - pll::PLL::new(pll::PllUsb).configure(1, 480_000_000, 5, 2); - - // Activate peripheral clock and take external oscillator as input - pac::CLOCKS.clk_peri_ctrl().write(|w| { - w.set_enable(true); - w.set_auxsrc(pac::clocks::vals::ClkPeriCtrlAuxsrc::XOSC_CLKSRC); - }); -}