rp235x_hal/
lib.rs

1//! HAL for the Raspberry Pi RP235x microcontrollers
2//!
3//! This is an implementation of the [`embedded-hal`](https://crates.io/crates/embedded-hal)
4//! traits for the RP235x microcontrollers
5//!
6//! NOTE This HAL is still under active development. This API will remain volatile until 1.0.0
7//!
8//! # Crate features
9//!
10//! * **critical-section-impl** -
11//!   critical section that is safe for multicore use
12//! * **defmt** -
13//!   Implement `defmt::Format` for several types.
14//! * **embedded_hal_1** -
15//!   Support alpha release of embedded-hal
16//! * **rom-func-cache** -
17//!   Memoize(cache) ROM function pointers on first use to improve performance
18//! * **rt** -
19//!   Minimal startup / runtime for Cortex-M microcontrollers
20//! * **rtic-monotonic** -
21//!   Implement `rtic_monotonic::Monotonic` based on the RP2350 timer peripheral
22//! * **i2c-write-iter** -
23//!   Implement `i2c_write_iter` traits for `I2C<_, _, Controller>`.
24//! * **binary-info** -
25//!   Include a `static` variable containing picotool compatible binary info.
26
27#![recursion_limit = "256"]
28#![warn(missing_docs)]
29#![no_std]
30
31#[doc(hidden)]
32pub use paste;
33
34/// Re-export of the PAC
35pub use rp235x_pac as pac;
36
37pub mod adc;
38pub mod arch;
39#[macro_use]
40pub mod async_utils;
41pub(crate) mod atomic_register_access;
42pub use rp_binary_info as binary_info;
43pub mod block;
44pub mod clocks;
45#[cfg(feature = "critical-section-impl")]
46mod critical_section_impl;
47#[cfg(all(target_arch = "arm", target_os = "none"))]
48pub mod dcp;
49pub mod dma;
50pub mod gpio;
51pub mod i2c;
52pub mod lposc;
53#[cfg(all(target_arch = "arm", target_os = "none"))]
54pub mod multicore;
55pub mod otp;
56pub mod pio;
57pub mod pll;
58pub mod powman;
59pub mod prelude;
60pub mod pwm;
61pub mod reboot;
62pub mod resets;
63pub mod rom_data;
64pub mod rosc;
65pub mod sio;
66pub mod spi;
67pub mod timer;
68pub mod typelevel;
69pub mod uart;
70pub mod usb;
71pub mod vector_table;
72pub mod watchdog;
73pub mod xosc;
74
75// Provide access to common datastructures to avoid repeating ourselves
76pub use adc::Adc;
77pub use clocks::Clock;
78pub use i2c::I2C;
79
80/// Attribute to declare the entry point of the program
81///
82/// This is based on and can be used like the [entry attribute from
83/// cortex-m-rt](https://docs.rs/cortex-m-rt/latest/cortex_m_rt/attr.entry.html).
84///
85/// It extends that macro with code to unlock all spinlocks at the beginning of
86/// `main`. As spinlocks are not automatically unlocked on software resets, this
87/// can prevent unexpected deadlocks when running from a debugger. The macro
88/// also enables the FPU (CP10) and the Double-Co-Processor (CP4) before we hit
89/// main.
90pub use rp235x_hal_macros::entry;
91
92/// Called by the rp235x-specific entry macro
93#[cfg(all(target_arch = "arm", target_os = "none"))]
94pub use cortex_m_rt::entry as arch_entry;
95
96/// Called by the rp235x-specific entry macro
97#[cfg(all(target_arch = "riscv32", target_os = "none"))]
98pub use riscv_rt::entry as arch_entry;
99
100use sio::CoreId;
101pub use sio::Sio;
102pub use spi::Spi;
103pub use timer::Timer;
104pub use watchdog::Watchdog;
105// Re-export crates used in rp235x-hal's public API
106pub extern crate fugit;
107
108/// Trigger full reset of the rp235x.
109///
110/// Uses the watchdog and the power-on state machine (PSM) to reset all on-chip components.
111pub fn reset() -> ! {
112    unsafe {
113        crate::arch::interrupt_disable();
114        (*pac::PSM::PTR).wdsel().write(|w| w.bits(0x0001ffff));
115        (*pac::WATCHDOG::PTR)
116            .ctrl()
117            .write(|w| w.trigger().set_bit());
118        #[allow(clippy::empty_loop)]
119        loop {}
120    }
121}
122
123/// Halt the rp235x.
124///
125/// Disables the other core, and parks the current core in an
126/// infinite loop with interrupts disabled.
127///
128/// Doesn't stop other subsystems, like the DMA controller.
129///
130/// When called from core1, core0 will be kept forced off, which
131/// likely breaks debug connections. You may need to reboot with
132/// BOOTSEL pressed to reboot into a debuggable state.
133pub fn halt() -> ! {
134    unsafe {
135        crate::arch::interrupt_disable();
136        // Stop other core
137        match crate::Sio::core() {
138            CoreId::Core0 => {
139                // Stop core 1.
140                (*pac::PSM::PTR)
141                    .frce_off()
142                    .modify(|_, w| w.proc1().set_bit());
143                while !(*pac::PSM::PTR).frce_off().read().proc1().bit_is_set() {
144                    crate::arch::nop();
145                }
146                // Restart core 1. Without this, most debuggers will fail connecting.
147                // It will loop indefinitely in BOOTROM, as nothing
148                // will trigger the wakeup sequence.
149                (*pac::PSM::PTR)
150                    .frce_off()
151                    .modify(|_, w| w.proc1().clear_bit());
152            }
153            CoreId::Core1 => {
154                // Stop core 0.
155                (*pac::PSM::PTR)
156                    .frce_off()
157                    .modify(|_, w| w.proc0().set_bit());
158                // We cannot restart core 0 here, as it would just boot into main.
159                // So the best we can do is to keep core 0 disabled, which may break
160                // further debug connections.
161            }
162        };
163
164        // Keep current core running, so debugging stays possible
165        loop {
166            crate::arch::wfe()
167        }
168    }
169}