1#![no_std]
2#![allow(async_fn_in_trait)]
3#![allow(unsafe_op_in_unsafe_fn)]
4#![allow(unused_unsafe)]
5#![doc = include_str!("../README.md")]
6#![warn(missing_docs)]
7
8#![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
10
11pub(crate) mod fmt;
13
14#[cfg(feature = "binary-info")]
15pub use rp_binary_info as binary_info;
16
17#[cfg(feature = "critical-section-impl")]
18mod critical_section_impl;
19
20#[cfg(feature = "rp2040")]
21mod intrinsics;
22
23pub mod adc;
24#[cfg(feature = "_rp235x")]
25pub mod aon_timer;
26#[cfg(feature = "_rp235x")]
27pub mod block;
28#[cfg(feature = "rp2040")]
29pub mod bootsel;
30pub mod clocks;
31pub(crate) mod datetime;
32pub mod dma;
33#[cfg(any(feature = "executor-thread", feature = "executor-interrupt"))]
34pub mod executor;
35pub mod flash;
36#[cfg(feature = "rp2040")]
37mod float;
38pub mod gpio;
39pub mod i2c;
40pub mod i2c_slave;
41pub mod multicore;
42#[cfg(feature = "_rp235x")]
43pub mod otp;
44pub mod pio_programs;
45#[cfg(feature = "_rp235x")]
46pub mod psram;
47pub mod pwm;
48#[cfg(feature = "_rp235x")]
49pub mod qmi_cs1;
50mod reset;
51pub mod rom_data;
52#[cfg(feature = "rp2040")]
53pub mod rtc;
54pub mod spi;
55mod spinlock;
56pub mod spinlock_mutex;
57#[cfg(feature = "time-driver")]
58pub mod time_driver;
59#[cfg(feature = "_rp235x")]
60pub mod trng;
61pub mod uart;
62pub mod usb;
63pub mod watchdog;
64
65pub mod pio;
67pub(crate) mod relocate;
68
69pub use embassy_hal_internal::{Peri, PeripheralType};
71#[cfg(feature = "unstable-pac")]
72pub use rp_pac as pac;
73#[cfg(not(feature = "unstable-pac"))]
74pub(crate) use rp_pac as pac;
75
76#[cfg(feature = "rt")]
77pub use crate::pac::NVIC_PRIO_BITS;
78
79#[cfg(feature = "rp2040")]
80embassy_hal_internal::interrupt_mod!(
81 TIMER_IRQ_0,
82 TIMER_IRQ_1,
83 TIMER_IRQ_2,
84 TIMER_IRQ_3,
85 PWM_IRQ_WRAP,
86 USBCTRL_IRQ,
87 XIP_IRQ,
88 PIO0_IRQ_0,
89 PIO0_IRQ_1,
90 PIO1_IRQ_0,
91 PIO1_IRQ_1,
92 DMA_IRQ_0,
93 DMA_IRQ_1,
94 IO_IRQ_BANK0,
95 IO_IRQ_QSPI,
96 SIO_IRQ_PROC0,
97 SIO_IRQ_PROC1,
98 CLOCKS_IRQ,
99 SPI0_IRQ,
100 SPI1_IRQ,
101 UART0_IRQ,
102 UART1_IRQ,
103 ADC_IRQ_FIFO,
104 I2C0_IRQ,
105 I2C1_IRQ,
106 RTC_IRQ,
107 SWI_IRQ_0,
108 SWI_IRQ_1,
109 SWI_IRQ_2,
110 SWI_IRQ_3,
111 SWI_IRQ_4,
112 SWI_IRQ_5,
113);
114
115#[cfg(feature = "_rp235x")]
116embassy_hal_internal::interrupt_mod!(
117 TIMER0_IRQ_0,
118 TIMER0_IRQ_1,
119 TIMER0_IRQ_2,
120 TIMER0_IRQ_3,
121 TIMER1_IRQ_0,
122 TIMER1_IRQ_1,
123 TIMER1_IRQ_2,
124 TIMER1_IRQ_3,
125 PWM_IRQ_WRAP_0,
126 PWM_IRQ_WRAP_1,
127 DMA_IRQ_0,
128 DMA_IRQ_1,
129 USBCTRL_IRQ,
130 PIO0_IRQ_0,
131 PIO0_IRQ_1,
132 PIO1_IRQ_0,
133 PIO1_IRQ_1,
134 PIO2_IRQ_0,
135 PIO2_IRQ_1,
136 IO_IRQ_BANK0,
137 IO_IRQ_BANK0_NS,
138 IO_IRQ_QSPI,
139 IO_IRQ_QSPI_NS,
140 SIO_IRQ_FIFO,
141 SIO_IRQ_BELL,
142 SIO_IRQ_FIFO_NS,
143 SIO_IRQ_BELL_NS,
144 CLOCKS_IRQ,
145 SPI0_IRQ,
146 SPI1_IRQ,
147 UART0_IRQ,
148 UART1_IRQ,
149 ADC_IRQ_FIFO,
150 I2C0_IRQ,
151 I2C1_IRQ,
152 TRNG_IRQ,
153 PLL_SYS_IRQ,
154 PLL_USB_IRQ,
155 POWMAN_IRQ_POW,
156 POWMAN_IRQ_TIMER,
157 SWI_IRQ_0,
158 SWI_IRQ_1,
159 SWI_IRQ_2,
160 SWI_IRQ_3,
161 SWI_IRQ_4,
162 SWI_IRQ_5,
163);
164
165#[macro_export]
186macro_rules! bind_interrupts {
187 ($(#[$attr:meta])* $vis:vis struct $name:ident {
188 $(
189 $(#[cfg($cond_irq:meta)])?
190 $irq:ident => $(
191 $(#[cfg($cond_handler:meta)])?
192 $handler:ty
193 ),*;
194 )*
195 }) => {
196 #[derive(Copy, Clone)]
197 $(#[$attr])*
198 $vis struct $name;
199
200 $(
201 #[allow(non_snake_case)]
202 #[unsafe(no_mangle)]
203 $(#[cfg($cond_irq)])?
204 unsafe extern "C" fn $irq() {
205 unsafe {
206 $(
207 $(#[cfg($cond_handler)])?
208 <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt();
209
210 )*
211 }
212 }
213
214 $(#[cfg($cond_irq)])?
215 $crate::bind_interrupts!(@inner
216 $(
217 $(#[cfg($cond_handler)])?
218 unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {}
219 )*
220 );
221 )*
222 };
223 (@inner $($t:tt)*) => {
224 $($t)*
225 }
226}
227
228#[cfg(feature = "rp2040")]
229embassy_hal_internal::peripherals! {
230 PIN_0,
231 PIN_1,
232 PIN_2,
233 PIN_3,
234 PIN_4,
235 PIN_5,
236 PIN_6,
237 PIN_7,
238 PIN_8,
239 PIN_9,
240 PIN_10,
241 PIN_11,
242 PIN_12,
243 PIN_13,
244 PIN_14,
245 PIN_15,
246 PIN_16,
247 PIN_17,
248 PIN_18,
249 PIN_19,
250 PIN_20,
251 PIN_21,
252 PIN_22,
253 PIN_23,
254 PIN_24,
255 PIN_25,
256 PIN_26,
257 PIN_27,
258 PIN_28,
259 PIN_29,
260 PIN_QSPI_SCLK,
261 PIN_QSPI_SS,
262 PIN_QSPI_SD0,
263 PIN_QSPI_SD1,
264 PIN_QSPI_SD2,
265 PIN_QSPI_SD3,
266
267 UART0,
268 UART1,
269
270 SPI0,
271 SPI1,
272
273 I2C0,
274 I2C1,
275
276 DMA_CH0,
277 DMA_CH1,
278 DMA_CH2,
279 DMA_CH3,
280 DMA_CH4,
281 DMA_CH5,
282 DMA_CH6,
283 DMA_CH7,
284 DMA_CH8,
285 DMA_CH9,
286 DMA_CH10,
287 DMA_CH11,
288
289 PWM_SLICE0,
290 PWM_SLICE1,
291 PWM_SLICE2,
292 PWM_SLICE3,
293 PWM_SLICE4,
294 PWM_SLICE5,
295 PWM_SLICE6,
296 PWM_SLICE7,
297
298 USB,
299
300 RTC,
301
302 FLASH,
303
304 ADC,
305 ADC_TEMP_SENSOR,
306
307 CORE1,
308
309 PIO0,
310 PIO1,
311
312 WATCHDOG,
313 BOOTSEL,
314}
315
316#[cfg(feature = "_rp235x")]
317embassy_hal_internal::peripherals! {
318 PIN_0,
319 PIN_1,
320 PIN_2,
321 PIN_3,
322 PIN_4,
323 PIN_5,
324 PIN_6,
325 PIN_7,
326 PIN_8,
327 PIN_9,
328 PIN_10,
329 PIN_11,
330 PIN_12,
331 PIN_13,
332 PIN_14,
333 PIN_15,
334 PIN_16,
335 PIN_17,
336 PIN_18,
337 PIN_19,
338 PIN_20,
339 PIN_21,
340 PIN_22,
341 PIN_23,
342 PIN_24,
343 PIN_25,
344 PIN_26,
345 PIN_27,
346 PIN_28,
347 PIN_29,
348 #[cfg(feature = "rp235xb")]
349 PIN_30,
350 #[cfg(feature = "rp235xb")]
351 PIN_31,
352 #[cfg(feature = "rp235xb")]
353 PIN_32,
354 #[cfg(feature = "rp235xb")]
355 PIN_33,
356 #[cfg(feature = "rp235xb")]
357 PIN_34,
358 #[cfg(feature = "rp235xb")]
359 PIN_35,
360 #[cfg(feature = "rp235xb")]
361 PIN_36,
362 #[cfg(feature = "rp235xb")]
363 PIN_37,
364 #[cfg(feature = "rp235xb")]
365 PIN_38,
366 #[cfg(feature = "rp235xb")]
367 PIN_39,
368 #[cfg(feature = "rp235xb")]
369 PIN_40,
370 #[cfg(feature = "rp235xb")]
371 PIN_41,
372 #[cfg(feature = "rp235xb")]
373 PIN_42,
374 #[cfg(feature = "rp235xb")]
375 PIN_43,
376 #[cfg(feature = "rp235xb")]
377 PIN_44,
378 #[cfg(feature = "rp235xb")]
379 PIN_45,
380 #[cfg(feature = "rp235xb")]
381 PIN_46,
382 #[cfg(feature = "rp235xb")]
383 PIN_47,
384 PIN_QSPI_SCLK,
385 PIN_QSPI_SS,
386 PIN_QSPI_SD0,
387 PIN_QSPI_SD1,
388 PIN_QSPI_SD2,
389 PIN_QSPI_SD3,
390
391 UART0,
392 UART1,
393
394 SPI0,
395 SPI1,
396
397 QMI_CS1,
398
399 I2C0,
400 I2C1,
401
402 DMA_CH0,
403 DMA_CH1,
404 DMA_CH2,
405 DMA_CH3,
406 DMA_CH4,
407 DMA_CH5,
408 DMA_CH6,
409 DMA_CH7,
410 DMA_CH8,
411 DMA_CH9,
412 DMA_CH10,
413 DMA_CH11,
414 DMA_CH12,
415 DMA_CH13,
416 DMA_CH14,
417 DMA_CH15,
418
419 PWM_SLICE0,
420 PWM_SLICE1,
421 PWM_SLICE2,
422 PWM_SLICE3,
423 PWM_SLICE4,
424 PWM_SLICE5,
425 PWM_SLICE6,
426 PWM_SLICE7,
427 PWM_SLICE8,
428 PWM_SLICE9,
429 PWM_SLICE10,
430 PWM_SLICE11,
431
432 USB,
433
434 RTC,
435
436 FLASH,
437
438 ADC,
439 ADC_TEMP_SENSOR,
440
441 CORE1,
442
443 PIO0,
444 PIO1,
445 PIO2,
446
447 WATCHDOG,
448 BOOTSEL,
449
450 POWMAN,
451 TRNG
452}
453
454#[cfg(all(not(feature = "boot2-none"), feature = "rp2040"))]
455macro_rules! select_bootloader {
456 ( $( $feature:literal => $loader:ident, )+ default => $default:ident ) => {
457 $(
458 #[cfg(feature = $feature)]
459 #[unsafe(link_section = ".boot2")]
460 #[used]
461 static BOOT2: [u8; 256] = rp2040_boot2::$loader;
462 )*
463
464 #[cfg(not(any( $( feature = $feature),* )))]
465 #[unsafe(link_section = ".boot2")]
466 #[used]
467 static BOOT2: [u8; 256] = rp2040_boot2::$default;
468 }
469}
470
471#[cfg(all(not(feature = "boot2-none"), feature = "rp2040"))]
472select_bootloader! {
473 "boot2-at25sf128a" => BOOT_LOADER_AT25SF128A,
474 "boot2-gd25q64cs" => BOOT_LOADER_GD25Q64CS,
475 "boot2-generic-03h" => BOOT_LOADER_GENERIC_03H,
476 "boot2-is25lp080" => BOOT_LOADER_IS25LP080,
477 "boot2-ram-memcpy" => BOOT_LOADER_RAM_MEMCPY,
478 "boot2-w25q080" => BOOT_LOADER_W25Q080,
479 "boot2-w25x10cl" => BOOT_LOADER_W25X10CL,
480 default => BOOT_LOADER_W25Q080
481}
482
483#[cfg(all(not(feature = "imagedef-none"), feature = "_rp235x"))]
484macro_rules! select_imagedef {
485 ( $( $feature:literal => $imagedef:ident, )+ default => $default:ident ) => {
486 $(
487 #[cfg(feature = $feature)]
488 #[unsafe(link_section = ".start_block")]
489 #[used]
490 static IMAGE_DEF: crate::block::ImageDef = crate::block::ImageDef::$imagedef();
491 )*
492
493 #[cfg(not(any( $( feature = $feature),* )))]
494 #[unsafe(link_section = ".start_block")]
495 #[used]
496 static IMAGE_DEF: crate::block::ImageDef = crate::block::ImageDef::$default();
497 }
498}
499
500#[cfg(all(not(feature = "imagedef-none"), feature = "_rp235x"))]
501select_imagedef! {
502 "imagedef-secure-exe" => secure_exe,
503 "imagedef-nonsecure-exe" => non_secure_exe,
504 default => secure_exe
505}
506
507pub fn install_core0_stack_guard() -> Result<(), ()> {
541 unsafe extern "C" {
542 static mut _stack_end: usize;
543 }
544 unsafe { install_stack_guard(core::ptr::addr_of_mut!(_stack_end)) }
545}
546
547#[cfg(all(feature = "rp2040", not(feature = "_test")))]
548#[inline(always)]
549unsafe fn install_stack_guard(stack_bottom: *mut usize) -> Result<(), ()> {
550 let core = unsafe { cortex_m::Peripherals::steal() };
551
552 if core.MPU.ctrl.read() != 0 {
554 return Err(());
555 }
556
557 let addr = (stack_bottom as u32 + 31) & !31;
560 let subregion_select = 0xff ^ (1 << ((addr >> 5) & 7));
562 unsafe {
563 core.MPU.ctrl.write(5); core.MPU.rbar.write((addr & !0xff) | (1 << 4)); core.MPU.rasr.write(
566 1 | (0x7 << 1) | (subregion_select << 8)
569 | 0x10000000, );
571 }
572 Ok(())
573}
574
575#[cfg(all(feature = "_rp235x", not(feature = "_test")))]
576#[inline(always)]
577unsafe fn install_stack_guard(stack_bottom: *mut usize) -> Result<(), ()> {
578 cortex_m::register::msplim::write(stack_bottom.addr() as u32);
581
582 Ok(())
583}
584
585#[cfg(feature = "_test")]
588#[inline(always)]
589unsafe fn install_stack_guard(_stack_bottom: *mut usize) -> Result<(), ()> {
590 Ok(())
591}
592
593pub mod config {
595 use crate::clocks::ClockConfig;
596
597 #[non_exhaustive]
599 pub struct Config {
600 pub clocks: ClockConfig,
602 }
603
604 impl Default for Config {
605 fn default() -> Self {
606 Self {
607 clocks: ClockConfig::crystal(12_000_000),
608 }
609 }
610 }
611
612 impl Config {
613 pub fn new(clocks: ClockConfig) -> Self {
615 Self { clocks }
616 }
617 }
618}
619
620pub fn init(config: config::Config) -> Peripherals {
626 let peripherals = Peripherals::take();
629
630 unsafe {
631 clocks::init(config.clocks);
632 #[cfg(feature = "time-driver")]
633 time_driver::init();
634 dma::init();
635 gpio::init();
636 }
637
638 peripherals
639}
640
641#[cfg(feature = "rt")]
642#[cortex_m_rt::pre_init]
643unsafe fn pre_init() {
644 #[cfg(feature = "rp2040")]
673 {
674 pac::PSM.frce_on().write_and_wait(|w| {
675 w.set_proc0(true);
676 });
677 pac::PSM.frce_off().write_and_wait(|w| {
679 w.set_sio(true);
680 w.set_proc1(true);
681 });
682 pac::PSM.frce_off().write_and_wait(|_| {});
684 pac::PSM.frce_on().write_and_wait(|_| {});
685 }
686
687 #[cfg(feature = "_rp235x")]
688 {
689 pac::SIO.spinlock(31).write_value(1);
695
696 pac::PSM.frce_off().write_and_wait(|w| w.set_proc1(true));
698 pac::PSM.frce_off().write_and_wait(|_| {});
699
700 enable_actlr_extexclall();
702 }
703}
704
705#[cfg(feature = "_rp235x")]
716unsafe fn enable_actlr_extexclall() {
717 (&*cortex_m::peripheral::ICB::PTR).actlr.modify(|w| w | (1 << 29));
718}
719
720#[allow(unused)]
722trait RegExt<T: Copy> {
723 #[allow(unused)]
724 fn write_xor<R>(&self, f: impl FnOnce(&mut T) -> R) -> R;
725 fn write_set<R>(&self, f: impl FnOnce(&mut T) -> R) -> R;
726 fn write_clear<R>(&self, f: impl FnOnce(&mut T) -> R) -> R;
727 fn write_and_wait<R>(&self, f: impl FnOnce(&mut T) -> R) -> R
728 where
729 T: PartialEq;
730}
731
732impl<T: Default + Copy, A: pac::common::Write> RegExt<T> for pac::common::Reg<T, A> {
733 fn write_xor<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
734 let mut val = Default::default();
735 let res = f(&mut val);
736 unsafe {
737 let ptr = (self.as_ptr() as *mut u8).add(0x1000) as *mut T;
738 ptr.write_volatile(val);
739 }
740 res
741 }
742
743 fn write_set<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
744 let mut val = Default::default();
745 let res = f(&mut val);
746 unsafe {
747 let ptr = (self.as_ptr() as *mut u8).add(0x2000) as *mut T;
748 ptr.write_volatile(val);
749 }
750 res
751 }
752
753 fn write_clear<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
754 let mut val = Default::default();
755 let res = f(&mut val);
756 unsafe {
757 let ptr = (self.as_ptr() as *mut u8).add(0x3000) as *mut T;
758 ptr.write_volatile(val);
759 }
760 res
761 }
762
763 fn write_and_wait<R>(&self, f: impl FnOnce(&mut T) -> R) -> R
764 where
765 T: PartialEq,
766 {
767 let mut val = Default::default();
768 let res = f(&mut val);
769 unsafe {
770 self.as_ptr().write_volatile(val);
771 while self.as_ptr().read_volatile() != val {}
772 }
773 res
774 }
775}