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