Unstabilize CPU-related functionality, merge modules (#3099)

* Move Cpu to a new module

* Move cpu_control's contents into cpu

* Merge raw_core functions

* Hide cpu control APIs

* Move reset into cpu

* Fix software_reset_cpu

* Allow inlining cpu functions

* Changelog

* Mark software_reset no-return

* Move WakeupReason

* Remove PeripheralIter

* Move cpu into system

* Mark system stable
This commit is contained in:
Dániel Buga 2025-02-07 15:15:26 +01:00 committed by GitHub
parent bb92715f6b
commit 392d5ccdc1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
59 changed files with 548 additions and 498 deletions

View File

@ -5,7 +5,7 @@ use core::{cell::UnsafeCell, mem::MaybeUninit};
use embassy_executor::SendSpawner;
use esp_hal::{
interrupt::{self, software::SoftwareInterrupt, InterruptHandler},
Cpu,
system::Cpu,
};
use portable_atomic::{AtomicUsize, Ordering};

View File

@ -5,7 +5,7 @@ use core::marker::PhantomData;
use embassy_executor::Spawner;
#[cfg(all(low_power_wait, multi_core))]
use esp_hal::interrupt::software::SoftwareInterrupt;
use esp_hal::{interrupt::Priority, Cpu};
use esp_hal::{interrupt::Priority, system::Cpu};
#[cfg(low_power_wait)]
use portable_atomic::{AtomicBool, Ordering};

View File

@ -40,6 +40,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Removed features `psram-quad` and `psram-octal` - replaced by `psram` and the `ESP_HAL_CONFIG_PSRAM_MODE` (`quad`/`octal`) (#3001)
- The `esp_hal::time` module no longer reexports `fugit` types (#3083)
- The `system::RadioClockController` trait has been replaced by the `clock::RadioClockController` struct. (#3100)
- The `Cpu` struct and contents of the `reset` and `cpu_control` modules have been moved into `cpu`. (#)
- The `software_reset_cpu` now takes which CPU to reset as parameter. (#)
- I2C: Async functions are postfixed with `_async`, non-async functions are available in async-mode (#3056)

View File

@ -534,7 +534,7 @@ impl<ADCI> crate::private::Sealed for Adc<'_, ADCI, Blocking> {}
impl<ADCI> InterruptConfigurable for Adc<'_, ADCI, Blocking> {
fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, InterruptSource);
}
unsafe { crate::interrupt::bind_interrupt(InterruptSource, handler.handler()) };
@ -643,7 +643,7 @@ where
pub fn into_blocking(self) -> Adc<'d, ADCI, Blocking> {
if asynch::release_async_adc() {
// Disable ADC interrupt on all cores if the last async ADC instance is disabled
for cpu in crate::Cpu::all() {
for cpu in crate::system::Cpu::all() {
crate::interrupt::disable(cpu, InterruptSource);
}
}

View File

@ -52,7 +52,7 @@ impl<'d> DebugAssist<'d> {
/// handlers.
#[instability::unstable]
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, Interrupt::ASSIST_DEBUG);
}
unsafe { crate::interrupt::bind_interrupt(Interrupt::ASSIST_DEBUG, handler.handler()) };

View File

@ -66,9 +66,9 @@ use crate::{
peripherals::Interrupt,
soc::{is_slice_in_dram, is_valid_memory_address, is_valid_ram_address},
system,
system::Cpu,
Async,
Blocking,
Cpu,
DriverMode,
};
@ -1873,7 +1873,7 @@ where
self.clear_in(EnumSet::all());
if let Some(interrupt) = self.rx_impl.peripheral_interrupt() {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, interrupt);
}
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
@ -2168,7 +2168,7 @@ where
self.clear_out(EnumSet::all());
if let Some(interrupt) = self.tx_impl.peripheral_interrupt() {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, interrupt);
}
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };

View File

@ -992,7 +992,7 @@ impl<Dm: DriverMode> Ecc<'_, Dm> {
/// handlers.
#[instability::unstable]
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, Interrupt::ECC);
}
unsafe { crate::interrupt::bind_interrupt(Interrupt::ECC, handler.handler()) };

View File

@ -717,7 +717,8 @@ pub(crate) fn bind_default_interrupt_handler() {
}
// The vector table doesn't contain a custom entry.Still, the
// peripheral interrupt may already be bound to something else.
if interrupt::bound_cpu_interrupt_for(crate::Cpu::current(), Interrupt::GPIO).is_some() {
if interrupt::bound_cpu_interrupt_for(crate::system::Cpu::current(), Interrupt::GPIO).is_some()
{
info!("Not using default GPIO interrupt handler: peripheral interrupt already in use");
return;
}
@ -773,7 +774,7 @@ impl Io {
/// `None`)
#[instability::unstable]
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, Interrupt::GPIO);
}
self.set_interrupt_priority(handler.priority());

View File

@ -1332,7 +1332,7 @@ impl Info {
}
fn set_interrupt_handler(&self, handler: InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, self.interrupt);
}
self.enable_listen(EnumSet::all(), false);
@ -1342,7 +1342,7 @@ impl Info {
}
fn disable_interrupts(&self) {
crate::interrupt::disable(crate::Cpu::current(), self.interrupt);
crate::interrupt::disable(crate::system::Cpu::current(), self.interrupt);
}
}

View File

@ -1518,7 +1518,7 @@ mod private {
impl RegisterAccessPrivate for I2S0 {
fn set_interrupt_handler(&self, handler: InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, Interrupt::I2S0);
}
unsafe { crate::peripherals::I2S0::steal() }.bind_i2s0_interrupt(handler.handler());
@ -1627,7 +1627,7 @@ mod private {
#[cfg(i2s1)]
impl RegisterAccessPrivate for I2S1 {
fn set_interrupt_handler(&self, handler: InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, Interrupt::I2S1);
}
unsafe { crate::peripherals::I2S1::steal() }.bind_i2s1_interrupt(handler.handler());

View File

@ -25,7 +25,7 @@ use super::InterruptStatus;
use crate::{
pac,
peripherals::{Interrupt, INTERRUPT_CORE0},
Cpu,
system::Cpu,
};
/// Interrupt Error
@ -560,7 +560,7 @@ mod vectored {
#[cfg(not(plic))]
mod classic {
use super::{CpuInterrupt, InterruptKind, Priority};
use crate::{peripherals::INTERRUPT_CORE0, Cpu};
use crate::{peripherals::INTERRUPT_CORE0, system::Cpu};
#[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")]
pub(super) static DISABLED_CPU_INTERRUPT: u32 = 0;
@ -710,7 +710,7 @@ mod classic {
#[cfg(plic)]
mod plic {
use super::{CpuInterrupt, InterruptKind, Priority};
use crate::{peripherals::PLIC_MX, Cpu};
use crate::{peripherals::PLIC_MX, system::Cpu};
#[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")]
pub(super) static DISABLED_CPU_INTERRUPT: u32 = 31;

View File

@ -66,7 +66,7 @@ impl<const NUM: u8> SoftwareInterrupt<NUM> {
_ => unreachable!(),
};
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, interrupt);
}
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };

View File

@ -6,7 +6,7 @@ use xtensa_lx_rt::exception::Context;
pub use self::vectored::*;
use super::InterruptStatus;
use crate::{pac, peripherals::Interrupt, Cpu};
use crate::{pac, peripherals::Interrupt, system::Cpu};
/// Interrupt Error
#[derive(Copy, Clone, Debug, PartialEq, Eq)]

View File

@ -17,10 +17,9 @@ use crate::{
lcd_cam::{cam::Cam, lcd::Lcd},
peripheral::Peripheral,
peripherals::{Interrupt, LCD_CAM},
system::GenericPeripheralGuard,
system::{Cpu, GenericPeripheralGuard},
Async,
Blocking,
Cpu,
};
/// Represents a combined LCD and Camera interface.
@ -71,7 +70,7 @@ impl<'d> LcdCam<'d, Blocking> {
/// handlers.
#[instability::unstable]
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, Interrupt::LCD_CAM);
}
unsafe { crate::interrupt::bind_interrupt(Interrupt::LCD_CAM, handler.handler()) };

View File

@ -155,8 +155,6 @@ pub use esp_riscv_rt::{self, riscv};
pub use xtensa_lx_rt::{self, xtensa_lx};
// TODO what should we reexport stably?
#[cfg(any(esp32, esp32s3))]
pub use self::soc::cpu_control;
#[cfg(efuse)]
#[instability::unstable]
#[cfg_attr(not(feature = "unstable"), allow(unused))]
@ -186,6 +184,7 @@ pub mod peripheral;
mod reg_access;
#[cfg(any(spi0, spi1, spi2, spi3))]
pub mod spi;
pub mod system;
pub mod time;
#[cfg(any(uart0, uart1, uart2))]
pub mod uart;
@ -262,8 +261,6 @@ unstable_module! {
pub mod parl_io;
#[cfg(pcnt)]
pub mod pcnt;
#[cfg(any(lp_clkrst, rtc_cntl))]
pub mod reset;
#[cfg(rmt)]
pub mod rmt;
#[cfg(rng)]
@ -277,8 +274,6 @@ unstable_module! {
pub mod sha;
#[doc(hidden)]
pub mod sync;
#[cfg(any(dport, hp_sys, pcr, system))]
pub mod system;
#[cfg(any(systimer, timg0, timg1))]
pub mod timer;
#[cfg(touch)]
@ -294,6 +289,8 @@ unstable_module! {
}
/// State of the CPU saved when entering exception or interrupt
#[instability::unstable]
#[allow(unused_imports)]
pub mod trapframe {
#[cfg(riscv)]
pub use esp_riscv_rt::TrapFrame;
@ -404,97 +401,6 @@ pub mod __macro_implementation {
pub use xtensa_lx_rt::entry as __entry;
}
/// Available CPU cores
///
/// The actual number of available cores depends on the target.
#[derive(Debug, Copy, Clone, PartialEq, Eq, strum::FromRepr)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(C)]
pub enum Cpu {
/// The first core
ProCpu = 0,
/// The second core
#[cfg(multi_core)]
AppCpu = 1,
}
impl Cpu {
/// The number of available cores.
pub const COUNT: usize = 1 + cfg!(multi_core) as usize;
/// Returns the core the application is currently executing on
#[inline(always)]
pub fn current() -> Self {
// This works for both RISCV and Xtensa because both
// get_raw_core functions return zero, _or_ something
// greater than zero; 1 in the case of RISCV and 0x2000
// in the case of Xtensa.
match raw_core() {
0 => Cpu::ProCpu,
#[cfg(all(multi_core, riscv))]
1 => Cpu::AppCpu,
#[cfg(all(multi_core, xtensa))]
0x2000 => Cpu::AppCpu,
_ => unreachable!(),
}
}
/// Returns an iterator over the "other" cores.
#[inline(always)]
pub(crate) fn other() -> impl Iterator<Item = Self> {
cfg_if::cfg_if! {
if #[cfg(multi_core)] {
match Self::current() {
Cpu::ProCpu => [Cpu::AppCpu].into_iter(),
Cpu::AppCpu => [Cpu::ProCpu].into_iter(),
}
} else {
[].into_iter()
}
}
}
/// Returns an iterator over all cores.
#[inline(always)]
pub(crate) fn all() -> impl Iterator<Item = Self> {
cfg_if::cfg_if! {
if #[cfg(multi_core)] {
[Cpu::ProCpu, Cpu::AppCpu].into_iter()
} else {
[Cpu::ProCpu].into_iter()
}
}
}
}
/// Returns the raw value of the mhartid register.
///
/// Safety: This method should never return UNUSED_THREAD_ID_VALUE
#[cfg(riscv)]
#[inline(always)]
fn raw_core() -> usize {
#[cfg(multi_core)]
{
riscv::register::mhartid::read()
}
#[cfg(not(multi_core))]
0
}
/// Returns the result of reading the PRID register logically ANDed with 0x2000,
/// the 13th bit in the register. Espressif Xtensa chips use this bit to
/// determine the core id.
///
/// Returns either 0 or 0x2000
///
/// Safety: This method should never return UNUSED_THREAD_ID_VALUE
#[cfg(xtensa)]
#[inline(always)]
fn raw_core() -> usize {
(xtensa_lx::get_processor_id() & 0x2000) as usize
}
#[cfg(riscv)]
#[export_name = "hal_main"]
fn hal_main(a0: usize, a1: usize, a2: usize) -> ! {

View File

@ -147,7 +147,7 @@ pub mod asynch {
use procmacros::handler;
use super::*;
use crate::Cpu;
use crate::system::Cpu;
// From ESP32-S3 TRM:
// Six additional endpoints (endpoint numbers 1 to 6), configurable as IN or OUT

View File

@ -985,7 +985,7 @@ fn internal_set_interrupt_handler(handler: InterruptHandler) {
let mut peri = unsafe { PARL_IO::steal() };
#[cfg(esp32c6)]
{
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, Interrupt::PARL_IO);
}
internal_listen(EnumSet::all(), false);
@ -999,7 +999,7 @@ fn internal_set_interrupt_handler(handler: InterruptHandler) {
}
#[cfg(esp32h2)]
{
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, Interrupt::PARL_IO_RX);
crate::interrupt::disable(core, Interrupt::PARL_IO_TX);
}
@ -1107,7 +1107,7 @@ impl<'d> ParlIoFullDuplex<'d, Blocking> {
/// Convert to an async version.
pub fn into_async(self) -> ParlIoFullDuplex<'d, Async> {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
#[cfg(esp32c6)]
{
crate::interrupt::disable(core, Interrupt::PARL_IO);
@ -1244,7 +1244,7 @@ impl<'d> ParlIoTxOnly<'d, Blocking> {
/// Converts to Async mode.
pub fn into_async(self) -> ParlIoTxOnly<'d, Async> {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
#[cfg(esp32c6)]
{
crate::interrupt::disable(core, Interrupt::PARL_IO);
@ -1372,7 +1372,7 @@ impl<'d> ParlIoRxOnly<'d, Blocking> {
/// Converts to Async mode.
pub fn into_async(self) -> ParlIoRxOnly<'d, Async> {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
#[cfg(esp32c6)]
{
crate::interrupt::disable(core, Interrupt::PARL_IO);

View File

@ -188,7 +188,7 @@ impl<'d> Pcnt<'d> {
/// handlers.
#[instability::unstable]
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, Interrupt::PCNT);
}
unsafe { interrupt::bind_interrupt(Interrupt::PCNT, handler.handler()) };

View File

@ -1,112 +0,0 @@
//! # Hardware and Software Reset
//!
//! ## Overview
//! Espressif chips provide four types of reset that occur at different levels,
//! namely CPU Reset, Core Reset, System Reset, and Chip Reset. All reset types
//! mentioned above (except Chip Reset) preserve the data stored in internal
//! memory.
//!
//! The Hardware and Software Reset module provides functions for
//! performing hardware and software resets and includes functions for
//! retrieving the reset reason and the wakeup cause after a reset.
//!
//! The module defines a set of sleep sources (`SleepSource`) that indicate the
//! source of the wakeup event. It also includes a set of flags (`WakeupReason`)
//! that represent different wakeup sources and enable/disable wakeup triggers
//! for specific events.
use crate::rtc_cntl::SocResetReason;
/// Source of the wakeup event
#[derive(Debug, Copy, Clone)]
pub enum SleepSource {
/// In case of deep sleep, reset was not caused by exit from deep sleep
Undefined = 0,
/// Not a wakeup cause, used to disable all wakeup sources with
/// esp_sleep_disable_wakeup_source
All,
/// Wakeup caused by external signal using RTC_IO
Ext0,
/// Wakeup caused by external signal using RTC_CNTL
Ext1,
/// Wakeup caused by timer
Timer,
/// Wakeup caused by touchpad
TouchPad,
/// Wakeup caused by ULP program
Ulp,
/// Wakeup caused by GPIO (light sleep only on ESP32, S2 and S3)
Gpio,
/// Wakeup caused by UART (light sleep only)
Uart,
/// Wakeup caused by WIFI (light sleep only)
Wifi,
/// Wakeup caused by COCPU int
Cocpu,
/// Wakeup caused by COCPU crash
CocpuTrapTrig,
/// Wakeup caused by BT (light sleep only)
BT,
}
bitflags::bitflags! {
#[allow(unused)]
pub(crate) struct WakeupReason: u32 {
const NoSleep = 0;
#[cfg(pm_support_ext0_wakeup)]
/// EXT0 GPIO wakeup
const ExtEvent0Trig = 1 << 0;
#[cfg(pm_support_ext1_wakeup)]
/// EXT1 GPIO wakeup
const ExtEvent1Trig = 1 << 1;
/// GPIO wakeup (light sleep only)
const GpioTrigEn = 1 << 2;
#[cfg(not(any(esp32c6, esp32h2)))]
/// Timer wakeup
const TimerTrigEn = 1 << 3;
#[cfg(any(esp32c6, esp32h2))]
/// Timer wakeup
const TimerTrigEn = 1 << 4;
#[cfg(pm_support_wifi_wakeup)]
/// MAC wakeup (light sleep only)
const WifiTrigEn = 1 << 5;
/// UART0 wakeup (light sleep only)
const Uart0TrigEn = 1 << 6;
/// UART1 wakeup (light sleep only)
const Uart1TrigEn = 1 << 7;
#[cfg(pm_support_touch_sensor_wakeup)]
/// Touch wakeup
const TouchTrigEn = 1 << 8;
#[cfg(ulp_supported)]
/// ULP wakeup
const UlpTrigEn = 1 << 9;
#[cfg(pm_support_bt_wakeup)]
/// BT wakeup (light sleep only)
const BtTrigEn = 1 << 10;
#[cfg(riscv_coproc_supported)]
const CocpuTrigEn = 1 << 11;
#[cfg(riscv_coproc_supported)]
const CocpuTrapTrigEn = 1 << 13;
}
}
/// Performs a software reset on the chip.
pub fn software_reset() {
crate::rom::software_reset();
}
/// Performs a software reset on the CPU.
pub fn software_reset_cpu() {
crate::rom::software_reset_cpu();
}
/// Retrieves the reason for the last reset as a SocResetReason enum value.
/// Returns `None` if the reset reason cannot be determined.
pub fn reset_reason() -> Option<SocResetReason> {
crate::rtc_cntl::reset_reason(crate::Cpu::current())
}
/// Retrieves the cause of the last wakeup event as a SleepSource enum value.
pub fn wakeup_cause() -> SleepSource {
crate::rtc_cntl::wakeup_cause()
}

View File

@ -449,7 +449,7 @@ impl<'d> Rmt<'d, Blocking> {
/// handlers.
#[instability::unstable]
pub fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, Interrupt::RMT);
}
unsafe { crate::interrupt::bind_interrupt(Interrupt::RMT, handler.handler()) };

View File

@ -113,21 +113,21 @@ pub(crate) fn rtc_get_reset_reason(cpu_num: u32) -> u32 {
}
#[inline(always)]
pub(crate) fn software_reset_cpu() {
pub(crate) fn software_reset_cpu(cpu_num: u32) {
extern "C" {
fn software_reset_cpu();
fn software_reset_cpu(cpu_num: u32);
}
unsafe { software_reset_cpu() };
unsafe { software_reset_cpu(cpu_num) };
}
#[inline(always)]
pub(crate) fn software_reset() {
pub(crate) fn software_reset() -> ! {
extern "C" {
fn software_reset();
fn software_reset() -> !;
}
unsafe { software_reset() };
unsafe { software_reset() }
}
#[cfg(esp32s3)]

View File

@ -28,10 +28,9 @@ use crate::{
pac,
peripheral::{Peripheral, PeripheralRef},
peripherals::{Interrupt, RSA},
system::{GenericPeripheralGuard, Peripheral as PeripheralEnable},
system::{Cpu, GenericPeripheralGuard, Peripheral as PeripheralEnable},
Async,
Blocking,
Cpu,
};
#[cfg_attr(esp32s2, path = "esp32sX.rs")]
@ -75,7 +74,7 @@ impl<'d> Rsa<'d, Blocking> {
/// handlers.
#[instability::unstable]
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, Interrupt::RSA);
}
unsafe { crate::interrupt::bind_interrupt(Interrupt::RSA, handler.handler()) };

View File

@ -126,9 +126,8 @@ use crate::{
interrupt::{self, InterruptHandler},
peripheral::{Peripheral, PeripheralRef},
peripherals::Interrupt,
reset::{SleepSource, WakeupReason},
system::{Cpu, SleepSource},
time::Duration,
Cpu,
};
#[cfg(not(any(esp32c6, esp32h2)))]
use crate::{
@ -160,6 +159,47 @@ cfg_if::cfg_if! {
}
}
bitflags::bitflags! {
#[allow(unused)]
struct WakeupReason: u32 {
const NoSleep = 0;
#[cfg(pm_support_ext0_wakeup)]
/// EXT0 GPIO wakeup
const ExtEvent0Trig = 1 << 0;
#[cfg(pm_support_ext1_wakeup)]
/// EXT1 GPIO wakeup
const ExtEvent1Trig = 1 << 1;
/// GPIO wakeup (light sleep only)
const GpioTrigEn = 1 << 2;
#[cfg(not(any(esp32c6, esp32h2)))]
/// Timer wakeup
const TimerTrigEn = 1 << 3;
#[cfg(any(esp32c6, esp32h2))]
/// Timer wakeup
const TimerTrigEn = 1 << 4;
#[cfg(pm_support_wifi_wakeup)]
/// MAC wakeup (light sleep only)
const WifiTrigEn = 1 << 5;
/// UART0 wakeup (light sleep only)
const Uart0TrigEn = 1 << 6;
/// UART1 wakeup (light sleep only)
const Uart1TrigEn = 1 << 7;
#[cfg(pm_support_touch_sensor_wakeup)]
/// Touch wakeup
const TouchTrigEn = 1 << 8;
#[cfg(ulp_supported)]
/// ULP wakeup
const UlpTrigEn = 1 << 9;
#[cfg(pm_support_bt_wakeup)]
/// BT wakeup (light sleep only)
const BtTrigEn = 1 << 10;
#[cfg(riscv_coproc_supported)]
const CocpuTrigEn = 1 << 11;
#[cfg(riscv_coproc_supported)]
const CocpuTrapTrigEn = 1 << 13;
}
}
#[cfg(not(any(esp32c6, esp32h2)))]
#[allow(unused)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -474,7 +514,7 @@ impl<'d> Rtc<'d> {
let interrupt = Interrupt::RTC_CORE;
}
}
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, interrupt);
}
unsafe { interrupt::bind_interrupt(interrupt, handler.handler()) };

View File

@ -56,7 +56,7 @@ pub enum WakeupLevel {
/// # use core::time::Duration;
/// # use esp_hal::delay::Delay;
/// # use esp_hal::rtc_cntl::{reset_reason, sleep::TimerWakeupSource, wakeup_cause, Rtc, SocResetReason};
/// # use esp_hal::Cpu;
/// # use esp_hal::system::Cpu;
///
/// let delay = Delay::new();
/// let mut rtc = Rtc::new(peripherals.LPWR);
@ -104,7 +104,7 @@ pub enum Error {
/// # use core::time::Duration;
/// # use esp_hal::delay::Delay;
/// # use esp_hal::rtc_cntl::{reset_reason, sleep::{Ext0WakeupSource, TimerWakeupSource, WakeupLevel}, wakeup_cause, Rtc, SocResetReason};
/// # use esp_hal::Cpu;
/// # use esp_hal::system::Cpu;
/// # use esp_hal::gpio::{Input, InputConfig, Pull};
///
/// let delay = Delay::new();
@ -157,7 +157,7 @@ impl<'a, P: RtcIoWakeupPinType> Ext0WakeupSource<'a, P> {
/// # use core::time::Duration;
/// # use esp_hal::delay::Delay;
/// # use esp_hal::rtc_cntl::{reset_reason, sleep::{Ext1WakeupSource, TimerWakeupSource, WakeupLevel}, wakeup_cause, Rtc, SocResetReason};
/// # use esp_hal::Cpu;
/// # use esp_hal::system::Cpu;
/// # use esp_hal::gpio::{Input, InputConfig, Pull, RtcPin};
/// # use esp_hal::peripheral::Peripheral;
///
@ -214,7 +214,7 @@ impl<'a, 'b> Ext1WakeupSource<'a, 'b> {
/// # use core::time::Duration;
/// # use esp_hal::delay::Delay;
/// # use esp_hal::rtc_cntl::{reset_reason, sleep::{Ext1WakeupSource, TimerWakeupSource, WakeupLevel}, wakeup_cause, Rtc, SocResetReason};
/// # use esp_hal::Cpu;
/// # use esp_hal::system::Cpu;
/// # use esp_hal::gpio::{Input, InputConfig, Pull, RtcPinWithResistors};
/// # use esp_hal::peripheral::Peripheral;
///
@ -276,7 +276,7 @@ impl<'a, 'b> Ext1WakeupSource<'a, 'b> {
/// # use esp_hal::delay::Delay;
/// # use esp_hal::gpio::{self, Input, InputConfig, Pull};
/// # use esp_hal::rtc_cntl::{reset_reason, sleep::{RtcioWakeupSource, TimerWakeupSource, WakeupLevel}, wakeup_cause, Rtc, SocResetReason};
/// # use esp_hal::Cpu;
/// # use esp_hal::system::Cpu;
/// # use esp_hal::peripheral::Peripheral;
///
/// let mut rtc = Rtc::new(peripherals.LPWR);

View File

@ -111,7 +111,7 @@ impl crate::private::Sealed for Sha<'_> {}
#[instability::unstable]
impl crate::interrupt::InterruptConfigurable for Sha<'_> {
fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, Interrupt::SHA);
}
unsafe { crate::interrupt::bind_interrupt(Interrupt::SHA, handler.handler()) };

View File

@ -4,53 +4,6 @@
//! This module provides essential functionality for controlling
//! and managing the APP (second) CPU core on the `ESP32` chip. It is used to
//! start and stop program execution on the APP core.
//!
//! ## Examples
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! # use esp_hal::delay::Delay;
//! # use esp_hal::cpu_control::{CpuControl, Stack};
//! # use core::{cell::RefCell, ptr::addr_of_mut};
//! # use critical_section::Mutex;
//! static mut APP_CORE_STACK: Stack<8192> = Stack::new();
//!
//! # let delay = Delay::new();
//!
//! let counter = Mutex::new(RefCell::new(0));
//!
//! let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL);
//! let cpu1_fnctn = || {
//! cpu1_task(&delay, &counter);
//! };
//! let _guard = cpu_control
//! .start_app_core(
//! unsafe { &mut *addr_of_mut!(APP_CORE_STACK) },
//! cpu1_fnctn
//! )?;
//!
//! loop {
//! delay.delay(Duration::from_secs(1));
//! let count = critical_section::with(|cs| *counter.borrow_ref(cs));
//! }
//! # }
//!
//! // Where `cpu1_task()` may be defined as:
//! # use esp_hal::delay::Delay;
//! # use core::cell::RefCell;
//! fn cpu1_task(
//! delay: &Delay,
//! counter: &critical_section::Mutex<RefCell<i32>>,
//! ) -> ! {
//! loop {
//! delay.delay(Duration::from_millis(500));
//!
//! critical_section::with(|cs| {
//! let mut val = counter.borrow_ref_mut(cs);
//! *val = val.wrapping_add(1);
//! });
//! }
//! }
//! ```
use core::{
marker::PhantomData,
@ -60,7 +13,7 @@ use core::{
use crate::{
peripheral::{Peripheral, PeripheralRef},
peripherals::{CPU_CTRL, DPORT, LPWR, SPI0},
Cpu,
system::Cpu,
};
/// Data type for a properly aligned stack of N bytes
@ -77,6 +30,7 @@ use crate::{
// Stack frame alignment depends on the SIZE as well as the placement of the
// array.
#[repr(C, align(16))]
#[instability::unstable]
pub struct Stack<const SIZE: usize> {
/// Memory to be used for the stack
pub mem: MaybeUninit<[u8; SIZE]>,
@ -91,6 +45,7 @@ impl<const SIZE: usize> Default for Stack<SIZE> {
#[allow(clippy::len_without_is_empty)]
impl<const SIZE: usize> Stack<SIZE> {
/// Construct a stack of length SIZE, uninitialized
#[instability::unstable]
pub const fn new() -> Stack<SIZE> {
::core::assert!(SIZE % 16 == 0); // Make sure stack top is aligned, too.
@ -99,17 +54,20 @@ impl<const SIZE: usize> Stack<SIZE> {
}
}
/// Returns the size of the stack.
/// Returns the length of the stack in bytes.
#[instability::unstable]
pub const fn len(&self) -> usize {
SIZE
}
/// Provides a mutable pointer to the bottom of the stack.
/// Returns a mutable pointer to the bottom of the stack.
#[instability::unstable]
pub fn bottom(&mut self) -> *mut u32 {
self.mem.as_mut_ptr() as *mut u32
}
/// Provides a mutable pointer to the top of the stack.
/// Returns a mutable pointer to the top of the stack.
#[instability::unstable]
pub fn top(&mut self) -> *mut u32 {
unsafe { self.bottom().add(SIZE / 4) }
}
@ -118,53 +76,102 @@ impl<const SIZE: usize> Stack<SIZE> {
// Pointer to the closure that will be executed on the second core. The closure
// is copied to the core's stack.
static mut START_CORE1_FUNCTION: Option<*mut ()> = None;
static mut APP_CORE_STACK_TOP: Option<*mut u32> = None;
/// Will park the APP (second) core when dropped
#[must_use]
#[must_use = "Dropping this guard will park the APP core"]
#[instability::unstable]
pub struct AppCoreGuard<'a> {
phantom: PhantomData<&'a ()>,
}
impl Drop for AppCoreGuard<'_> {
fn drop(&mut self) {
unsafe {
internal_park_core(Cpu::AppCpu);
}
unsafe { internal_park_core(Cpu::AppCpu, true) };
}
}
/// Represents errors that can occur while working with the core.
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[instability::unstable]
pub enum Error {
/// The core is already running.
CoreAlreadyRunning,
}
/// Control CPU Cores
///
/// ## Examples
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::delay::Delay;
/// # use esp_hal::system::{CpuControl, Stack};
/// # use core::{cell::RefCell, ptr::addr_of_mut};
/// # use critical_section::Mutex;
/// # let delay = Delay::new();
/// static mut APP_CORE_STACK: Stack<8192> = Stack::new();
///
/// let counter = Mutex::new(RefCell::new(0));
///
/// let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL);
/// let cpu1_fnctn = || {
/// cpu1_task(&delay, &counter);
/// };
/// let _guard = cpu_control
/// .start_app_core(
/// unsafe { &mut *addr_of_mut!(APP_CORE_STACK) },
/// cpu1_fnctn
/// )?;
///
/// loop {
/// delay.delay(Duration::from_secs(1));
/// let count = critical_section::with(|cs| *counter.borrow_ref(cs));
/// }
/// # }
///
/// // Where `cpu1_task()` may be defined as:
/// # use esp_hal::delay::Delay;
/// # use core::cell::RefCell;
///
/// fn cpu1_task(
/// delay: &Delay,
/// counter: &critical_section::Mutex<RefCell<i32>>,
/// ) -> ! {
/// loop {
/// delay.delay(Duration::from_millis(500));
///
/// critical_section::with(|cs| {
/// let mut val = counter.borrow_ref_mut(cs);
/// *val = val.wrapping_add(1);
/// });
/// }
/// }
/// ```
#[instability::unstable]
pub struct CpuControl<'d> {
_cpu_control: PeripheralRef<'d, CPU_CTRL>,
}
unsafe fn internal_park_core(core: Cpu) {
unsafe fn internal_park_core(core: Cpu, park: bool) {
let c1_value = if park { 0x21 } else { 0 };
let c0_value = if park { 0x02 } else { 0 };
match core {
Cpu::ProCpu => {
LPWR::regs()
.sw_cpu_stall()
.modify(|_, w| w.sw_stall_procpu_c1().bits(0x21));
.modify(|_, w| w.sw_stall_procpu_c1().bits(c1_value));
LPWR::regs()
.options0()
.modify(|_, w| w.sw_stall_procpu_c0().bits(0x02));
.modify(|_, w| w.sw_stall_procpu_c0().bits(c0_value));
}
Cpu::AppCpu => {
LPWR::regs()
.sw_cpu_stall()
.modify(|_, w| w.sw_stall_appcpu_c1().bits(0x21));
.modify(|_, w| w.sw_stall_appcpu_c1().bits(c1_value));
LPWR::regs()
.options0()
.modify(|_, w| w.sw_stall_appcpu_c0().bits(0x02));
.modify(|_, w| w.sw_stall_appcpu_c0().bits(c0_value));
}
}
}
@ -186,30 +193,15 @@ impl<'d> CpuControl<'d> {
///
/// The user must ensure that the core being parked is not the core which is
/// currently executing their code.
#[instability::unstable]
pub unsafe fn park_core(&mut self, core: Cpu) {
internal_park_core(core);
internal_park_core(core, true);
}
/// Unpark the given core
#[instability::unstable]
pub fn unpark_core(&mut self, core: Cpu) {
match core {
Cpu::ProCpu => {
LPWR::regs()
.sw_cpu_stall()
.modify(|_, w| unsafe { w.sw_stall_procpu_c1().bits(0) });
LPWR::regs()
.options0()
.modify(|_, w| unsafe { w.sw_stall_procpu_c0().bits(0) });
}
Cpu::AppCpu => {
LPWR::regs()
.sw_cpu_stall()
.modify(|_, w| unsafe { w.sw_stall_appcpu_c1().bits(0) });
LPWR::regs()
.options0()
.modify(|_, w| unsafe { w.sw_stall_appcpu_c0().bits(0) });
}
}
unsafe { internal_park_core(core, false) };
}
fn flush_cache(&mut self, core: Cpu) {
@ -323,7 +315,7 @@ impl<'d> CpuControl<'d> {
let entry = unsafe { ManuallyDrop::take(&mut *entry.cast::<ManuallyDrop<F>>()) };
entry();
loop {
unsafe { internal_park_core(Cpu::current()) };
unsafe { internal_park_core(Cpu::current(), true) };
}
}
None => panic!("No start function set"),
@ -336,6 +328,7 @@ impl<'d> CpuControl<'d> {
/// closure exits, the core will be parked.
///
/// Dropping the returned guard will park the core.
#[instability::unstable]
pub fn start_app_core<'a, const SIZE: usize, F>(
&mut self,
stack: &'static mut Stack<SIZE>,

View File

@ -46,7 +46,7 @@ use crate::{
gpio::{AlternateFunction, GpioPin},
pac::io_mux,
peripherals::{GPIO, IO_MUX},
Cpu,
system::Cpu,
};
/// The total number of GPIO pins available.

View File

@ -97,7 +97,7 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
addr_of_mut!(_rtc_slow_bss_end),
);
if matches!(
crate::reset::reset_reason(),
crate::system::reset_reason(),
None | Some(SocResetReason::ChipPowerOn)
) {
xtensa_lx_rt::zero_bss(

View File

@ -101,7 +101,7 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
addr_of_mut!(_rtc_slow_bss_end),
);
if matches!(
crate::reset::reset_reason(),
crate::system::reset_reason(),
None | Some(SocResetReason::ChipPowerOn)
) {
xtensa_lx_rt::zero_bss(

View File

@ -5,53 +5,6 @@
//! This module provides essential functionality for controlling
//! and managing the APP (second) CPU core on the `ESP32-S3` chip. It is used to
//! start and stop program execution on the APP core.
//!
//! ## Examples
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! # use esp_hal::delay::Delay;
//! # use esp_hal::cpu_control::{CpuControl, Stack};
//! # use core::{cell::RefCell, ptr::addr_of_mut};
//! # use critical_section::Mutex;
//! # let delay = Delay::new();
//! static mut APP_CORE_STACK: Stack<8192> = Stack::new();
//!
//! let counter = Mutex::new(RefCell::new(0));
//!
//! let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL);
//! let cpu1_fnctn = || {
//! cpu1_task(&delay, &counter);
//! };
//! let _guard = cpu_control
//! .start_app_core(
//! unsafe { &mut *addr_of_mut!(APP_CORE_STACK) },
//! cpu1_fnctn
//! )?;
//!
//! loop {
//! delay.delay(Duration::from_secs(1));
//! let count = critical_section::with(|cs| *counter.borrow_ref(cs));
//! }
//! # }
//!
//! // Where `cpu1_task()` may be defined as:
//! # use esp_hal::delay::Delay;
//! # use core::cell::RefCell;
//!
//! fn cpu1_task(
//! delay: &Delay,
//! counter: &critical_section::Mutex<RefCell<i32>>,
//! ) -> ! {
//! loop {
//! delay.delay(Duration::from_millis(500));
//!
//! critical_section::with(|cs| {
//! let mut val = counter.borrow_ref_mut(cs);
//! *val = val.wrapping_add(1);
//! });
//! }
//! }
//! ```
use core::{
marker::PhantomData,
@ -60,8 +13,8 @@ use core::{
use crate::{
peripheral::{Peripheral, PeripheralRef},
peripherals::CPU_CTRL,
Cpu,
peripherals::{CPU_CTRL, LPWR, SYSTEM},
system::Cpu,
};
/// Data type for a properly aligned stack of N bytes
@ -78,6 +31,7 @@ use crate::{
// Stack frame alignment depends on the SIZE as well as the placement of the
// array.
#[repr(C, align(16))]
#[instability::unstable]
pub struct Stack<const SIZE: usize> {
/// Memory to be used for the stack
pub mem: MaybeUninit<[u8; SIZE]>,
@ -92,6 +46,7 @@ impl<const SIZE: usize> Default for Stack<SIZE> {
#[allow(clippy::len_without_is_empty)]
impl<const SIZE: usize> Stack<SIZE> {
/// Construct a stack of length SIZE, uninitialized
#[instability::unstable]
pub const fn new() -> Stack<SIZE> {
::core::assert!(SIZE % 16 == 0); // Make sure stack top is aligned, too.
@ -101,16 +56,19 @@ impl<const SIZE: usize> Stack<SIZE> {
}
/// Returns the length of the stack in bytes.
#[instability::unstable]
pub const fn len(&self) -> usize {
SIZE
}
/// Returns a mutable pointer to the bottom of the stack.
#[instability::unstable]
pub fn bottom(&mut self) -> *mut u32 {
self.mem.as_mut_ptr() as *mut u32
}
/// Returns a mutable pointer to the top of the stack.
#[instability::unstable]
pub fn top(&mut self) -> *mut u32 {
unsafe { self.bottom().add(SIZE / 4) }
}
@ -122,51 +80,99 @@ static mut START_CORE1_FUNCTION: Option<*mut ()> = None;
static mut APP_CORE_STACK_TOP: Option<*mut u32> = None;
/// Will park the APP (second) core when dropped
#[must_use]
#[must_use = "Dropping this guard will park the APP core"]
#[instability::unstable]
pub struct AppCoreGuard<'a> {
phantom: PhantomData<&'a ()>,
}
impl Drop for AppCoreGuard<'_> {
fn drop(&mut self) {
unsafe {
internal_park_core(Cpu::AppCpu);
}
unsafe { internal_park_core(Cpu::AppCpu, true) };
}
}
/// Represents errors that can occur while working with the core.
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[instability::unstable]
pub enum Error {
/// The core is already running.
CoreAlreadyRunning,
}
/// Control CPU Cores
///
/// ## Examples
/// ```rust, no_run
#[doc = crate::before_snippet!()]
/// # use esp_hal::delay::Delay;
/// # use esp_hal::system::{CpuControl, Stack};
/// # use core::{cell::RefCell, ptr::addr_of_mut};
/// # use critical_section::Mutex;
/// # let delay = Delay::new();
/// static mut APP_CORE_STACK: Stack<8192> = Stack::new();
///
/// let counter = Mutex::new(RefCell::new(0));
///
/// let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL);
/// let cpu1_fnctn = || {
/// cpu1_task(&delay, &counter);
/// };
/// let _guard = cpu_control
/// .start_app_core(
/// unsafe { &mut *addr_of_mut!(APP_CORE_STACK) },
/// cpu1_fnctn
/// )?;
///
/// loop {
/// delay.delay(Duration::from_secs(1));
/// let count = critical_section::with(|cs| *counter.borrow_ref(cs));
/// }
/// # }
///
/// // Where `cpu1_task()` may be defined as:
/// # use esp_hal::delay::Delay;
/// # use core::cell::RefCell;
///
/// fn cpu1_task(
/// delay: &Delay,
/// counter: &critical_section::Mutex<RefCell<i32>>,
/// ) -> ! {
/// loop {
/// delay.delay(Duration::from_millis(500));
///
/// critical_section::with(|cs| {
/// let mut val = counter.borrow_ref_mut(cs);
/// *val = val.wrapping_add(1);
/// });
/// }
/// }
/// ```
#[instability::unstable]
pub struct CpuControl<'d> {
_cpu_control: PeripheralRef<'d, CPU_CTRL>,
}
unsafe fn internal_park_core(core: Cpu) {
let rtc_control = crate::peripherals::LPWR::regs();
unsafe fn internal_park_core(core: Cpu, park: bool) {
let c1_value = if park { 0x21 } else { 0 };
let c0_value = if park { 0x02 } else { 0 };
match core {
Cpu::ProCpu => {
rtc_control
LPWR::regs()
.sw_cpu_stall()
.modify(|_, w| w.sw_stall_procpu_c1().bits(0x21));
rtc_control
.modify(|_, w| w.sw_stall_procpu_c1().bits(c1_value));
LPWR::regs()
.options0()
.modify(|_, w| w.sw_stall_procpu_c0().bits(0x02));
.modify(|_, w| w.sw_stall_procpu_c0().bits(c0_value));
}
Cpu::AppCpu => {
rtc_control
LPWR::regs()
.sw_cpu_stall()
.modify(|_, w| w.sw_stall_appcpu_c1().bits(0x21));
rtc_control
.modify(|_, w| w.sw_stall_appcpu_c1().bits(c1_value));
LPWR::regs()
.options0()
.modify(|_, w| w.sw_stall_appcpu_c0().bits(0x02));
.modify(|_, w| w.sw_stall_appcpu_c0().bits(c0_value));
}
}
}
@ -188,32 +194,15 @@ impl<'d> CpuControl<'d> {
///
/// The user must ensure that the core being parked is not the core which is
/// currently executing their code.
#[instability::unstable]
pub unsafe fn park_core(&mut self, core: Cpu) {
internal_park_core(core);
internal_park_core(core, true);
}
/// Unpark the given core
#[instability::unstable]
pub fn unpark_core(&mut self, core: Cpu) {
let rtc_control = crate::peripherals::LPWR::regs();
match core {
Cpu::ProCpu => {
rtc_control
.sw_cpu_stall()
.modify(|_, w| unsafe { w.sw_stall_procpu_c1().bits(0) });
rtc_control
.options0()
.modify(|_, w| unsafe { w.sw_stall_procpu_c0().bits(0) });
}
Cpu::AppCpu => {
rtc_control
.sw_cpu_stall()
.modify(|_, w| unsafe { w.sw_stall_appcpu_c1().bits(0) });
rtc_control
.options0()
.modify(|_, w| unsafe { w.sw_stall_appcpu_c0().bits(0) });
}
}
unsafe { internal_park_core(core, false) };
}
/// When we get here, the core is out of reset, with a stack setup by ROM
@ -265,19 +254,20 @@ impl<'d> CpuControl<'d> {
let entry = unsafe { ManuallyDrop::take(&mut *entry.cast::<ManuallyDrop<F>>()) };
entry();
loop {
unsafe { internal_park_core(Cpu::current()) };
unsafe { internal_park_core(Cpu::current(), true) };
}
}
None => panic!("No start function set"),
}
}
/// Start the APP (second) core
/// Start the APP (second) core.
///
/// The second core will start running the closure `entry`. Note that if the
/// closure exits, the core will be parked.
///
/// Dropping the returned guard will park the core.
#[instability::unstable]
pub fn start_app_core<'a, const SIZE: usize, F>(
&mut self,
stack: &'static mut Stack<SIZE>,
@ -287,7 +277,7 @@ impl<'d> CpuControl<'d> {
F: FnOnce(),
F: Send + 'a,
{
let system_control = crate::peripherals::SYSTEM::regs();
let system_control = SYSTEM::regs();
if !xtensa_lx::is_debugger_attached()
&& system_control

View File

@ -140,7 +140,7 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
addr_of_mut!(_rtc_slow_bss_end),
);
if matches!(
crate::reset::reset_reason(),
crate::system::reset_reason(),
None | Some(SocResetReason::ChipPowerOn)
) {
xtensa_lx_rt::zero_bss(

View File

@ -59,11 +59,10 @@ use crate::{
peripheral::{Peripheral, PeripheralRef},
private::{self, Sealed},
spi::AnySpi,
system::PeripheralGuard,
system::{Cpu, PeripheralGuard},
time::Rate,
Async,
Blocking,
Cpu,
DriverMode,
};
@ -1345,7 +1344,7 @@ mod dma {
/// Interrupts are not enabled at the peripheral level here.
fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
let interrupt = self.driver().info.interrupt;
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, interrupt);
}
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };

View File

@ -128,7 +128,7 @@ mod multicore {
const UNUSED_THREAD_ID_VALUE: usize = 0x100;
pub fn thread_id() -> usize {
crate::raw_core()
crate::system::raw_core()
}
pub(super) struct AtomicLock {

View File

@ -3,19 +3,9 @@
use core::cell::RefCell;
use critical_section::{CriticalSection, Mutex};
use strum::{EnumCount, EnumIter, IntoEnumIterator};
use crate::peripherals::SYSTEM;
pub(crate) const KEEP_ENABLED: &[Peripheral] = &[
Peripheral::Uart0,
#[cfg(usb_device)]
Peripheral::UsbDevice,
#[cfg(systimer)]
Peripheral::Systimer,
Peripheral::Timg0,
];
/// Peripherals which can be enabled via `PeripheralClockControl`.
///
/// This enum represents various hardware peripherals that can be enabled
@ -24,7 +14,7 @@ pub(crate) const KEEP_ENABLED: &[Peripheral] = &[
// FIXME: This enum needs to be public because it's exposed via a bunch of traits, but it's not
// useful to users.
#[doc(hidden)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, EnumCount, EnumIter)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Peripheral {
@ -132,6 +122,90 @@ pub enum Peripheral {
Tsens,
}
impl Peripheral {
const KEEP_ENABLED: &[Peripheral] = &[
Peripheral::Uart0,
#[cfg(usb_device)]
Peripheral::UsbDevice,
#[cfg(systimer)]
Peripheral::Systimer,
Peripheral::Timg0,
];
const COUNT: usize = Self::ALL.len();
const ALL: &[Self] = &[
#[cfg(spi2)]
Self::Spi2,
#[cfg(spi3)]
Self::Spi3,
#[cfg(i2c0)]
Self::I2cExt0,
#[cfg(i2c1)]
Self::I2cExt1,
#[cfg(rmt)]
Self::Rmt,
#[cfg(ledc)]
Self::Ledc,
#[cfg(mcpwm0)]
Self::Mcpwm0,
#[cfg(mcpwm1)]
Self::Mcpwm1,
#[cfg(pcnt)]
Self::Pcnt,
#[cfg(apb_saradc)]
Self::ApbSarAdc,
#[cfg(gdma)]
Self::Gdma,
#[cfg(pdma)]
Self::Dma,
#[cfg(i2s0)]
Self::I2s0,
#[cfg(i2s1)]
Self::I2s1,
#[cfg(usb0)]
Self::Usb,
#[cfg(aes)]
Self::Aes,
#[cfg(twai0)]
Self::Twai0,
#[cfg(twai1)]
Self::Twai1,
#[cfg(timg0)]
Self::Timg0,
#[cfg(timg1)]
Self::Timg1,
#[cfg(sha)]
Self::Sha,
#[cfg(usb_device)]
Self::UsbDevice,
#[cfg(uart0)]
Self::Uart0,
#[cfg(uart1)]
Self::Uart1,
#[cfg(uart2)]
Self::Uart2,
#[cfg(rsa)]
Self::Rsa,
#[cfg(parl_io)]
Self::ParlIo,
#[cfg(hmac)]
Self::Hmac,
#[cfg(ecc)]
Self::Ecc,
#[cfg(soc_etm)]
Self::Etm,
#[cfg(trace0)]
Self::Trace0,
#[cfg(lcd_cam)]
Self::LcdCam,
#[cfg(systimer)]
Self::Systimer,
#[cfg(tsens)]
Self::Tsens,
];
}
impl Peripheral {
pub fn try_from(value: u8) -> Option<Peripheral> {
if value >= Peripheral::COUNT as u8 {
@ -151,11 +225,11 @@ static PERIPHERAL_REF_COUNT: Mutex<RefCell<[usize; Peripheral::COUNT]>> =
pub(crate) fn disable_peripherals() {
// Take the critical section up front to avoid taking it multiple times.
critical_section::with(|cs| {
for p in Peripheral::iter() {
if KEEP_ENABLED.contains(&p) {
for p in Peripheral::ALL {
if Peripheral::KEEP_ENABLED.contains(p) {
continue;
}
PeripheralClockControl::enable_forced_with_cs(p, false, true, cs);
PeripheralClockControl::enable_forced_with_cs(*p, false, true, cs);
}
})
}
@ -168,7 +242,7 @@ pub(crate) struct PeripheralGuard {
impl PeripheralGuard {
pub(crate) fn new_with(p: Peripheral, init: fn()) -> Self {
if !KEEP_ENABLED.contains(&p) && PeripheralClockControl::enable(p) {
if !Peripheral::KEEP_ENABLED.contains(&p) && PeripheralClockControl::enable(p) {
PeripheralClockControl::reset(p);
init();
}
@ -183,7 +257,7 @@ impl PeripheralGuard {
impl Drop for PeripheralGuard {
fn drop(&mut self) {
if !KEEP_ENABLED.contains(&self.peripheral) {
if !Peripheral::KEEP_ENABLED.contains(&self.peripheral) {
PeripheralClockControl::disable(self.peripheral);
}
}
@ -197,7 +271,7 @@ impl<const P: u8> GenericPeripheralGuard<P> {
pub(crate) fn new_with(init: fn(CriticalSection<'_>)) -> Self {
let peripheral = unwrap!(Peripheral::try_from(P));
critical_section::with(|cs| {
if !KEEP_ENABLED.contains(&peripheral)
if !Peripheral::KEEP_ENABLED.contains(&peripheral)
&& PeripheralClockControl::enable_with_cs(peripheral, cs)
{
PeripheralClockControl::reset(peripheral);
@ -216,7 +290,7 @@ impl<const P: u8> GenericPeripheralGuard<P> {
impl<const P: u8> Drop for GenericPeripheralGuard<P> {
fn drop(&mut self) {
let peripheral = unwrap!(Peripheral::try_from(P));
if !KEEP_ENABLED.contains(&peripheral) {
if !Peripheral::KEEP_ENABLED.contains(&peripheral) {
PeripheralClockControl::disable(peripheral);
}
}
@ -1075,3 +1149,155 @@ impl PeripheralClockControl {
true
}
}
#[cfg(any(esp32, esp32s3))]
#[allow(unused_imports)]
pub use crate::soc::cpu_control::*;
/// Available CPU cores
///
/// The actual number of available cores depends on the target.
#[derive(Debug, Copy, Clone, PartialEq, Eq, strum::FromRepr)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(C)]
pub enum Cpu {
/// The first core
ProCpu = 0,
/// The second core
#[cfg(multi_core)]
AppCpu = 1,
}
impl Cpu {
/// The number of available cores.
pub const COUNT: usize = 1 + cfg!(multi_core) as usize;
/// Returns the core the application is currently executing on
#[inline(always)]
pub fn current() -> Self {
// This works for both RISCV and Xtensa because both
// get_raw_core functions return zero, _or_ something
// greater than zero; 1 in the case of RISCV and 0x2000
// in the case of Xtensa.
match raw_core() {
0 => Cpu::ProCpu,
#[cfg(all(multi_core, riscv))]
1 => Cpu::AppCpu,
#[cfg(all(multi_core, xtensa))]
0x2000 => Cpu::AppCpu,
_ => unreachable!(),
}
}
/// Returns an iterator over the "other" cores.
#[inline(always)]
pub(crate) fn other() -> impl Iterator<Item = Self> {
cfg_if::cfg_if! {
if #[cfg(multi_core)] {
match Self::current() {
Cpu::ProCpu => [Cpu::AppCpu].into_iter(),
Cpu::AppCpu => [Cpu::ProCpu].into_iter(),
}
} else {
[].into_iter()
}
}
}
/// Returns an iterator over all cores.
#[inline(always)]
pub(crate) fn all() -> impl Iterator<Item = Self> {
cfg_if::cfg_if! {
if #[cfg(multi_core)] {
[Cpu::ProCpu, Cpu::AppCpu].into_iter()
} else {
[Cpu::ProCpu].into_iter()
}
}
}
}
/// Returns the raw value of the mhartid register.
///
/// On RISC-V, this is the hardware thread ID.
///
/// On Xtensa, this returns the result of reading the PRID register logically
/// ANDed with 0x2000, the 13th bit in the register. Espressif Xtensa chips use
/// this bit to determine the core id.
#[inline(always)]
pub(crate) fn raw_core() -> usize {
// This method must never return UNUSED_THREAD_ID_VALUE
cfg_if::cfg_if! {
if #[cfg(all(multi_core, riscv))] {
riscv::register::mhartid::read()
} else if #[cfg(all(multi_core, xtensa))] {
(xtensa_lx::get_processor_id() & 0x2000) as usize
} else {
0
}
}
}
use crate::rtc_cntl::SocResetReason;
/// Source of the wakeup event
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[instability::unstable]
pub enum SleepSource {
/// In case of deep sleep, reset was not caused by exit from deep sleep
Undefined = 0,
/// Not a wakeup cause, used to disable all wakeup sources with
/// esp_sleep_disable_wakeup_source
All,
/// Wakeup caused by external signal using RTC_IO
Ext0,
/// Wakeup caused by external signal using RTC_CNTL
Ext1,
/// Wakeup caused by timer
Timer,
/// Wakeup caused by touchpad
TouchPad,
/// Wakeup caused by ULP program
Ulp,
/// Wakeup caused by GPIO (light sleep only on ESP32, S2 and S3)
Gpio,
/// Wakeup caused by UART (light sleep only)
Uart,
/// Wakeup caused by WIFI (light sleep only)
Wifi,
/// Wakeup caused by COCPU int
Cocpu,
/// Wakeup caused by COCPU crash
CocpuTrapTrig,
/// Wakeup caused by BT (light sleep only)
BT,
}
/// Performs a software reset on the chip.
#[inline]
pub fn software_reset() -> ! {
crate::rom::software_reset()
}
/// Resets the given CPU, leaving peripherals unchanged.
#[instability::unstable]
#[inline]
pub fn software_reset_cpu(cpu: Cpu) {
crate::rom::software_reset_cpu(cpu as u32)
}
/// Retrieves the reason for the last reset as a SocResetReason enum value.
/// Returns `None` if the reset reason cannot be determined.
#[instability::unstable]
#[inline]
pub fn reset_reason() -> Option<SocResetReason> {
crate::rtc_cntl::reset_reason(Cpu::current())
}
/// Retrieves the cause of the last wakeup event as a SleepSource enum value.
#[instability::unstable]
#[inline]
pub fn wakeup_cause() -> SleepSource {
crate::rtc_cntl::wakeup_cause()
}

View File

@ -52,10 +52,10 @@ use crate::{
interrupt::{InterruptConfigurable, InterruptHandler},
peripheral::{Peripheral, PeripheralRef},
peripherals::Interrupt,
system::Cpu,
time::{Duration, Instant},
Async,
Blocking,
Cpu,
DriverMode,
};

View File

@ -26,9 +26,8 @@ use crate::{
peripheral::Peripheral,
peripherals::{Interrupt, SYSTIMER},
sync::{lock, RawMutex},
system::{Peripheral as PeripheralEnable, PeripheralClockControl},
system::{Cpu, Peripheral as PeripheralEnable, PeripheralClockControl},
time::{Duration, Instant},
Cpu,
};
/// The configuration of a unit.
@ -397,7 +396,7 @@ impl Alarm {
_ => unreachable!(),
};
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, interrupt);
}

View File

@ -391,7 +391,7 @@ impl Timer {
_ => unreachable!(),
};
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, interrupt);
}
unsafe { interrupt::bind_interrupt(interrupt, handler.handler()) };

View File

@ -131,7 +131,7 @@ use crate::{
interrupt::InterruptHandler,
pac::twai0::RegisterBlock,
peripheral::{Peripheral, PeripheralRef},
system::PeripheralGuard,
system::{Cpu, PeripheralGuard},
twai::filter::SingleStandardFilter,
Async,
Blocking,
@ -745,7 +745,7 @@ where
}
fn internal_set_interrupt_handler(&mut self, handler: InterruptHandler) {
for core in crate::Cpu::other() {
for core in Cpu::other() {
crate::interrupt::disable(core, self.twai.interrupt());
}
unsafe { crate::interrupt::bind_interrupt(self.twai.interrupt(), handler.handler()) };
@ -986,7 +986,7 @@ impl<'d> TwaiConfiguration<'d, Blocking> {
impl<'d> TwaiConfiguration<'d, Async> {
/// Convert the configuration into a blocking configuration.
pub fn into_blocking(self) -> TwaiConfiguration<'d, Blocking> {
use crate::{interrupt, Cpu};
use crate::{interrupt, system::Cpu};
interrupt::disable(Cpu::current(), self.twai.interrupt());

View File

@ -2234,7 +2234,7 @@ impl Info {
}
fn set_interrupt_handler(&self, handler: InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, self.interrupt);
}
self.enable_listen(EnumSet::all(), false);
@ -2244,7 +2244,7 @@ impl Info {
}
fn disable_interrupts(&self) {
crate::interrupt::disable(crate::Cpu::current(), self.interrupt);
crate::interrupt::disable(crate::system::Cpu::current(), self.interrupt);
}
fn apply_config(&self, config: &Config) -> Result<(), ConfigError> {

View File

@ -132,10 +132,9 @@ use crate::{
pac::usb_device::RegisterBlock,
peripheral::{Peripheral, PeripheralRef},
peripherals::{Interrupt, USB_DEVICE},
system::PeripheralClockControl,
system::{Cpu, PeripheralClockControl},
Async,
Blocking,
Cpu,
DriverMode,
};
@ -447,7 +446,7 @@ where
/// handlers.
#[instability::unstable]
pub fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
for core in crate::Cpu::other() {
for core in crate::system::Cpu::other() {
crate::interrupt::disable(core, Interrupt::USB_DEVICE);
}
unsafe { crate::interrupt::bind_interrupt(Interrupt::USB_DEVICE, handler.handler()) };

View File

@ -306,7 +306,7 @@ pub(crate) unsafe extern "C" fn interrupt_on(intr_num: i32) -> i32 {
pub(crate) unsafe extern "C" fn interrupt_off(intr_num: i32) -> i32 {
trace!("interrupt_off {}", intr_num);
interrupt::disable(
crate::hal::Cpu::ProCpu,
crate::hal::system::Cpu::ProCpu,
Interrupt::try_from(intr_num as u16).unwrap(),
);

View File

@ -53,7 +53,7 @@ pub(crate) fn setup_multitasking() {
}
pub(crate) fn disable_multitasking() {
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::FROM_CPU_INTR3);
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::FROM_CPU_INTR3);
}
extern "C" fn handler(trap_frame: &mut TrapFrame) {

View File

@ -7,16 +7,28 @@ pub(crate) fn setup_radio_isr() {
{
// It's a mystery why these interrupts are enabled now since it worked without
// this before Now at least without disabling these nothing will work
interrupt::disable(crate::hal::Cpu::ProCpu, peripherals::Interrupt::ETH_MAC);
interrupt::disable(crate::hal::Cpu::ProCpu, peripherals::Interrupt::UART0);
interrupt::disable(
crate::hal::system::Cpu::ProCpu,
peripherals::Interrupt::ETH_MAC,
);
interrupt::disable(
crate::hal::system::Cpu::ProCpu,
peripherals::Interrupt::UART0,
);
}
}
pub(crate) fn shutdown_radio_isr() {
#[cfg(feature = "ble")]
{
interrupt::disable(crate::hal::Cpu::ProCpu, peripherals::Interrupt::RWBT);
interrupt::disable(crate::hal::Cpu::ProCpu, peripherals::Interrupt::BT_BB);
interrupt::disable(
crate::hal::system::Cpu::ProCpu,
peripherals::Interrupt::RWBT,
);
interrupt::disable(
crate::hal::system::Cpu::ProCpu,
peripherals::Interrupt::BT_BB,
);
}
}

View File

@ -12,8 +12,8 @@ pub(crate) fn setup_radio_isr() {
pub(crate) fn shutdown_radio_isr() {
#[cfg(feature = "ble")]
{
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::LP_TIMER);
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_MAC);
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::LP_TIMER);
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::BT_MAC);
}
}

View File

@ -12,9 +12,9 @@ pub(crate) fn setup_radio_isr() {
pub(crate) fn shutdown_radio_isr() {
#[cfg(feature = "ble")]
{
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::RWBT);
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::RWBLE);
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_BB);
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::RWBT);
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::RWBLE);
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::BT_BB);
}
}

View File

@ -23,8 +23,8 @@ pub(crate) fn setup_radio_isr() {
pub(crate) fn shutdown_radio_isr() {
#[cfg(feature = "ble")]
{
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::LP_TIMER);
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_MAC);
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::LP_TIMER);
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::BT_MAC);
}
}

View File

@ -11,8 +11,8 @@ pub(crate) fn setup_radio_isr() {
pub(crate) fn shutdown_radio_isr() {
#[cfg(feature = "ble")]
{
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::LP_BLE_TIMER);
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_MAC);
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::LP_BLE_TIMER);
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::BT_MAC);
}
}

View File

@ -9,8 +9,8 @@ pub(crate) fn setup_radio_isr() {
pub(crate) fn shutdown_radio_isr() {
#[cfg(feature = "ble")]
{
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_BB);
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::RWBLE);
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::BT_BB);
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::RWBLE);
}
}

View File

@ -19,10 +19,9 @@ use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal}
use embassy_time::{Duration, Ticker};
use esp_backtrace as _;
use esp_hal::{
cpu_control::{CpuControl, Stack},
gpio::{Level, Output, OutputConfig},
system::{Cpu, CpuControl, Stack},
timer::{timg::TimerGroup, AnyTimer},
Cpu,
};
use esp_hal_embassy::Executor;
use esp_println::println;

View File

@ -18,12 +18,11 @@ use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal}
use embassy_time::{Duration, Ticker};
use esp_backtrace as _;
use esp_hal::{
cpu_control::{CpuControl, Stack},
gpio::{Level, Output, OutputConfig},
interrupt::{software::SoftwareInterruptControl, Priority},
main,
system::{Cpu, CpuControl, Stack},
timer::{timg::TimerGroup, AnyTimer},
Cpu,
};
use esp_hal_embassy::InterruptExecutor;
use esp_println::println;

View File

@ -11,7 +11,7 @@
use esp_backtrace as _;
use esp_hal::{
main,
reset::software_reset,
system::software_reset,
uart::{self, Uart},
};
use esp_ieee802154::{Config, Ieee802154};

View File

@ -15,7 +15,7 @@
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal};
#[cfg(multi_core)]
use esp_hal::cpu_control::{CpuControl, Stack};
use esp_hal::system::{CpuControl, Stack};
use esp_hal::{
interrupt::{
software::{SoftwareInterrupt, SoftwareInterruptControl},

View File

@ -308,7 +308,7 @@ mod test {
}
};
use esp_hal::cpu_control::{CpuControl, Stack};
use esp_hal::system::{CpuControl, Stack};
const DISPLAY_STACK_SIZE: usize = 8192;
let app_core_stack = mk_static!(Stack<DISPLAY_STACK_SIZE>, Stack::new());
let cpu_control = CpuControl::new(peripherals.CPU_CTRL);

View File

@ -42,11 +42,10 @@ cfg_if::cfg_if! {
if #[cfg(multi_core)] {
use core::sync::atomic::{AtomicBool, Ordering};
use esp_hal::cpu_control::CpuControl;
use esp_hal::system::{CpuControl, Stack};
static DONE: AtomicBool = AtomicBool::new(false);
static mut APP_CORE_STACK: esp_hal::cpu_control::Stack<8192> =
esp_hal::cpu_control::Stack::new();
static mut APP_CORE_STACK: Stack<8192> = Stack::new();
}
}

View File

@ -12,7 +12,7 @@ use esp_hal::{
delay::Delay,
main,
rtc_cntl::{reset_reason, sleep::TimerWakeupSource, wakeup_cause, Rtc, SocResetReason},
Cpu,
system::Cpu,
};
use esp_println::println;

View File

@ -22,7 +22,7 @@ use esp_hal::{
Rtc,
SocResetReason,
},
Cpu,
system::Cpu,
};
use esp_println::println;

View File

@ -22,7 +22,7 @@ use esp_hal::{
Rtc,
SocResetReason,
},
Cpu,
system::Cpu,
};
use esp_println::println;

View File

@ -23,7 +23,7 @@ use esp_hal::{
Rtc,
SocResetReason,
},
Cpu,
system::Cpu,
};
use esp_println::println;

View File

@ -27,7 +27,7 @@ use esp_hal::{
Rtc,
SocResetReason,
},
Cpu,
system::Cpu,
};
use esp_println::println;