mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-28 21:00:59 +00:00
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:
parent
bb92715f6b
commit
392d5ccdc1
@ -5,7 +5,7 @@ use core::{cell::UnsafeCell, mem::MaybeUninit};
|
|||||||
use embassy_executor::SendSpawner;
|
use embassy_executor::SendSpawner;
|
||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
interrupt::{self, software::SoftwareInterrupt, InterruptHandler},
|
interrupt::{self, software::SoftwareInterrupt, InterruptHandler},
|
||||||
Cpu,
|
system::Cpu,
|
||||||
};
|
};
|
||||||
use portable_atomic::{AtomicUsize, Ordering};
|
use portable_atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use core::marker::PhantomData;
|
|||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
#[cfg(all(low_power_wait, multi_core))]
|
#[cfg(all(low_power_wait, multi_core))]
|
||||||
use esp_hal::interrupt::software::SoftwareInterrupt;
|
use esp_hal::interrupt::software::SoftwareInterrupt;
|
||||||
use esp_hal::{interrupt::Priority, Cpu};
|
use esp_hal::{interrupt::Priority, system::Cpu};
|
||||||
#[cfg(low_power_wait)]
|
#[cfg(low_power_wait)]
|
||||||
use portable_atomic::{AtomicBool, Ordering};
|
use portable_atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
|
@ -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)
|
- 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 `esp_hal::time` module no longer reexports `fugit` types (#3083)
|
||||||
- The `system::RadioClockController` trait has been replaced by the `clock::RadioClockController` struct. (#3100)
|
- 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)
|
- I2C: Async functions are postfixed with `_async`, non-async functions are available in async-mode (#3056)
|
||||||
|
|
||||||
|
@ -534,7 +534,7 @@ impl<ADCI> crate::private::Sealed for Adc<'_, ADCI, Blocking> {}
|
|||||||
|
|
||||||
impl<ADCI> InterruptConfigurable for Adc<'_, ADCI, Blocking> {
|
impl<ADCI> InterruptConfigurable for Adc<'_, ADCI, Blocking> {
|
||||||
fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, InterruptSource);
|
||||||
}
|
}
|
||||||
unsafe { crate::interrupt::bind_interrupt(InterruptSource, handler.handler()) };
|
unsafe { crate::interrupt::bind_interrupt(InterruptSource, handler.handler()) };
|
||||||
@ -643,7 +643,7 @@ where
|
|||||||
pub fn into_blocking(self) -> Adc<'d, ADCI, Blocking> {
|
pub fn into_blocking(self) -> Adc<'d, ADCI, Blocking> {
|
||||||
if asynch::release_async_adc() {
|
if asynch::release_async_adc() {
|
||||||
// Disable ADC interrupt on all cores if the last async ADC instance is disabled
|
// 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);
|
crate::interrupt::disable(cpu, InterruptSource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ impl<'d> DebugAssist<'d> {
|
|||||||
/// handlers.
|
/// handlers.
|
||||||
#[instability::unstable]
|
#[instability::unstable]
|
||||||
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, Interrupt::ASSIST_DEBUG);
|
||||||
}
|
}
|
||||||
unsafe { crate::interrupt::bind_interrupt(Interrupt::ASSIST_DEBUG, handler.handler()) };
|
unsafe { crate::interrupt::bind_interrupt(Interrupt::ASSIST_DEBUG, handler.handler()) };
|
||||||
|
@ -66,9 +66,9 @@ use crate::{
|
|||||||
peripherals::Interrupt,
|
peripherals::Interrupt,
|
||||||
soc::{is_slice_in_dram, is_valid_memory_address, is_valid_ram_address},
|
soc::{is_slice_in_dram, is_valid_memory_address, is_valid_ram_address},
|
||||||
system,
|
system,
|
||||||
|
system::Cpu,
|
||||||
Async,
|
Async,
|
||||||
Blocking,
|
Blocking,
|
||||||
Cpu,
|
|
||||||
DriverMode,
|
DriverMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1873,7 +1873,7 @@ where
|
|||||||
self.clear_in(EnumSet::all());
|
self.clear_in(EnumSet::all());
|
||||||
|
|
||||||
if let Some(interrupt) = self.rx_impl.peripheral_interrupt() {
|
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);
|
crate::interrupt::disable(core, interrupt);
|
||||||
}
|
}
|
||||||
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
|
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
|
||||||
@ -2168,7 +2168,7 @@ where
|
|||||||
self.clear_out(EnumSet::all());
|
self.clear_out(EnumSet::all());
|
||||||
|
|
||||||
if let Some(interrupt) = self.tx_impl.peripheral_interrupt() {
|
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);
|
crate::interrupt::disable(core, interrupt);
|
||||||
}
|
}
|
||||||
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
|
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
|
||||||
|
@ -992,7 +992,7 @@ impl<Dm: DriverMode> Ecc<'_, Dm> {
|
|||||||
/// handlers.
|
/// handlers.
|
||||||
#[instability::unstable]
|
#[instability::unstable]
|
||||||
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, Interrupt::ECC);
|
||||||
}
|
}
|
||||||
unsafe { crate::interrupt::bind_interrupt(Interrupt::ECC, handler.handler()) };
|
unsafe { crate::interrupt::bind_interrupt(Interrupt::ECC, handler.handler()) };
|
||||||
|
@ -717,7 +717,8 @@ pub(crate) fn bind_default_interrupt_handler() {
|
|||||||
}
|
}
|
||||||
// The vector table doesn't contain a custom entry.Still, the
|
// The vector table doesn't contain a custom entry.Still, the
|
||||||
// peripheral interrupt may already be bound to something else.
|
// 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");
|
info!("Not using default GPIO interrupt handler: peripheral interrupt already in use");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -773,7 +774,7 @@ impl Io {
|
|||||||
/// `None`)
|
/// `None`)
|
||||||
#[instability::unstable]
|
#[instability::unstable]
|
||||||
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, Interrupt::GPIO);
|
||||||
}
|
}
|
||||||
self.set_interrupt_priority(handler.priority());
|
self.set_interrupt_priority(handler.priority());
|
||||||
|
@ -1332,7 +1332,7 @@ impl Info {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_interrupt_handler(&self, handler: InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, self.interrupt);
|
||||||
}
|
}
|
||||||
self.enable_listen(EnumSet::all(), false);
|
self.enable_listen(EnumSet::all(), false);
|
||||||
@ -1342,7 +1342,7 @@ impl Info {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn disable_interrupts(&self) {
|
fn disable_interrupts(&self) {
|
||||||
crate::interrupt::disable(crate::Cpu::current(), self.interrupt);
|
crate::interrupt::disable(crate::system::Cpu::current(), self.interrupt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1518,7 +1518,7 @@ mod private {
|
|||||||
|
|
||||||
impl RegisterAccessPrivate for I2S0 {
|
impl RegisterAccessPrivate for I2S0 {
|
||||||
fn set_interrupt_handler(&self, handler: InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, Interrupt::I2S0);
|
||||||
}
|
}
|
||||||
unsafe { crate::peripherals::I2S0::steal() }.bind_i2s0_interrupt(handler.handler());
|
unsafe { crate::peripherals::I2S0::steal() }.bind_i2s0_interrupt(handler.handler());
|
||||||
@ -1627,7 +1627,7 @@ mod private {
|
|||||||
#[cfg(i2s1)]
|
#[cfg(i2s1)]
|
||||||
impl RegisterAccessPrivate for I2S1 {
|
impl RegisterAccessPrivate for I2S1 {
|
||||||
fn set_interrupt_handler(&self, handler: InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, Interrupt::I2S1);
|
||||||
}
|
}
|
||||||
unsafe { crate::peripherals::I2S1::steal() }.bind_i2s1_interrupt(handler.handler());
|
unsafe { crate::peripherals::I2S1::steal() }.bind_i2s1_interrupt(handler.handler());
|
||||||
|
@ -25,7 +25,7 @@ use super::InterruptStatus;
|
|||||||
use crate::{
|
use crate::{
|
||||||
pac,
|
pac,
|
||||||
peripherals::{Interrupt, INTERRUPT_CORE0},
|
peripherals::{Interrupt, INTERRUPT_CORE0},
|
||||||
Cpu,
|
system::Cpu,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Interrupt Error
|
/// Interrupt Error
|
||||||
@ -560,7 +560,7 @@ mod vectored {
|
|||||||
#[cfg(not(plic))]
|
#[cfg(not(plic))]
|
||||||
mod classic {
|
mod classic {
|
||||||
use super::{CpuInterrupt, InterruptKind, Priority};
|
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")]
|
#[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")]
|
||||||
pub(super) static DISABLED_CPU_INTERRUPT: u32 = 0;
|
pub(super) static DISABLED_CPU_INTERRUPT: u32 = 0;
|
||||||
@ -710,7 +710,7 @@ mod classic {
|
|||||||
#[cfg(plic)]
|
#[cfg(plic)]
|
||||||
mod plic {
|
mod plic {
|
||||||
use super::{CpuInterrupt, InterruptKind, Priority};
|
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")]
|
#[cfg_attr(place_switch_tables_in_ram, link_section = ".rwtext")]
|
||||||
pub(super) static DISABLED_CPU_INTERRUPT: u32 = 31;
|
pub(super) static DISABLED_CPU_INTERRUPT: u32 = 31;
|
||||||
|
@ -66,7 +66,7 @@ impl<const NUM: u8> SoftwareInterrupt<NUM> {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
for core in crate::Cpu::other() {
|
for core in crate::system::Cpu::other() {
|
||||||
crate::interrupt::disable(core, interrupt);
|
crate::interrupt::disable(core, interrupt);
|
||||||
}
|
}
|
||||||
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
|
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
|
||||||
|
@ -6,7 +6,7 @@ use xtensa_lx_rt::exception::Context;
|
|||||||
|
|
||||||
pub use self::vectored::*;
|
pub use self::vectored::*;
|
||||||
use super::InterruptStatus;
|
use super::InterruptStatus;
|
||||||
use crate::{pac, peripherals::Interrupt, Cpu};
|
use crate::{pac, peripherals::Interrupt, system::Cpu};
|
||||||
|
|
||||||
/// Interrupt Error
|
/// Interrupt Error
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
@ -17,10 +17,9 @@ use crate::{
|
|||||||
lcd_cam::{cam::Cam, lcd::Lcd},
|
lcd_cam::{cam::Cam, lcd::Lcd},
|
||||||
peripheral::Peripheral,
|
peripheral::Peripheral,
|
||||||
peripherals::{Interrupt, LCD_CAM},
|
peripherals::{Interrupt, LCD_CAM},
|
||||||
system::GenericPeripheralGuard,
|
system::{Cpu, GenericPeripheralGuard},
|
||||||
Async,
|
Async,
|
||||||
Blocking,
|
Blocking,
|
||||||
Cpu,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents a combined LCD and Camera interface.
|
/// Represents a combined LCD and Camera interface.
|
||||||
@ -71,7 +70,7 @@ impl<'d> LcdCam<'d, Blocking> {
|
|||||||
/// handlers.
|
/// handlers.
|
||||||
#[instability::unstable]
|
#[instability::unstable]
|
||||||
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, Interrupt::LCD_CAM);
|
||||||
}
|
}
|
||||||
unsafe { crate::interrupt::bind_interrupt(Interrupt::LCD_CAM, handler.handler()) };
|
unsafe { crate::interrupt::bind_interrupt(Interrupt::LCD_CAM, handler.handler()) };
|
||||||
|
@ -155,8 +155,6 @@ pub use esp_riscv_rt::{self, riscv};
|
|||||||
pub use xtensa_lx_rt::{self, xtensa_lx};
|
pub use xtensa_lx_rt::{self, xtensa_lx};
|
||||||
|
|
||||||
// TODO what should we reexport stably?
|
// TODO what should we reexport stably?
|
||||||
#[cfg(any(esp32, esp32s3))]
|
|
||||||
pub use self::soc::cpu_control;
|
|
||||||
#[cfg(efuse)]
|
#[cfg(efuse)]
|
||||||
#[instability::unstable]
|
#[instability::unstable]
|
||||||
#[cfg_attr(not(feature = "unstable"), allow(unused))]
|
#[cfg_attr(not(feature = "unstable"), allow(unused))]
|
||||||
@ -186,6 +184,7 @@ pub mod peripheral;
|
|||||||
mod reg_access;
|
mod reg_access;
|
||||||
#[cfg(any(spi0, spi1, spi2, spi3))]
|
#[cfg(any(spi0, spi1, spi2, spi3))]
|
||||||
pub mod spi;
|
pub mod spi;
|
||||||
|
pub mod system;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
#[cfg(any(uart0, uart1, uart2))]
|
#[cfg(any(uart0, uart1, uart2))]
|
||||||
pub mod uart;
|
pub mod uart;
|
||||||
@ -262,8 +261,6 @@ unstable_module! {
|
|||||||
pub mod parl_io;
|
pub mod parl_io;
|
||||||
#[cfg(pcnt)]
|
#[cfg(pcnt)]
|
||||||
pub mod pcnt;
|
pub mod pcnt;
|
||||||
#[cfg(any(lp_clkrst, rtc_cntl))]
|
|
||||||
pub mod reset;
|
|
||||||
#[cfg(rmt)]
|
#[cfg(rmt)]
|
||||||
pub mod rmt;
|
pub mod rmt;
|
||||||
#[cfg(rng)]
|
#[cfg(rng)]
|
||||||
@ -277,8 +274,6 @@ unstable_module! {
|
|||||||
pub mod sha;
|
pub mod sha;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
#[cfg(any(dport, hp_sys, pcr, system))]
|
|
||||||
pub mod system;
|
|
||||||
#[cfg(any(systimer, timg0, timg1))]
|
#[cfg(any(systimer, timg0, timg1))]
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
#[cfg(touch)]
|
#[cfg(touch)]
|
||||||
@ -294,6 +289,8 @@ unstable_module! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// State of the CPU saved when entering exception or interrupt
|
/// State of the CPU saved when entering exception or interrupt
|
||||||
|
#[instability::unstable]
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub mod trapframe {
|
pub mod trapframe {
|
||||||
#[cfg(riscv)]
|
#[cfg(riscv)]
|
||||||
pub use esp_riscv_rt::TrapFrame;
|
pub use esp_riscv_rt::TrapFrame;
|
||||||
@ -404,97 +401,6 @@ pub mod __macro_implementation {
|
|||||||
pub use xtensa_lx_rt::entry as __entry;
|
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)]
|
#[cfg(riscv)]
|
||||||
#[export_name = "hal_main"]
|
#[export_name = "hal_main"]
|
||||||
fn hal_main(a0: usize, a1: usize, a2: usize) -> ! {
|
fn hal_main(a0: usize, a1: usize, a2: usize) -> ! {
|
||||||
|
@ -147,7 +147,7 @@ pub mod asynch {
|
|||||||
use procmacros::handler;
|
use procmacros::handler;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Cpu;
|
use crate::system::Cpu;
|
||||||
|
|
||||||
// From ESP32-S3 TRM:
|
// From ESP32-S3 TRM:
|
||||||
// Six additional endpoints (endpoint numbers 1 to 6), configurable as IN or OUT
|
// Six additional endpoints (endpoint numbers 1 to 6), configurable as IN or OUT
|
||||||
|
@ -985,7 +985,7 @@ fn internal_set_interrupt_handler(handler: InterruptHandler) {
|
|||||||
let mut peri = unsafe { PARL_IO::steal() };
|
let mut peri = unsafe { PARL_IO::steal() };
|
||||||
#[cfg(esp32c6)]
|
#[cfg(esp32c6)]
|
||||||
{
|
{
|
||||||
for core in crate::Cpu::other() {
|
for core in crate::system::Cpu::other() {
|
||||||
crate::interrupt::disable(core, Interrupt::PARL_IO);
|
crate::interrupt::disable(core, Interrupt::PARL_IO);
|
||||||
}
|
}
|
||||||
internal_listen(EnumSet::all(), false);
|
internal_listen(EnumSet::all(), false);
|
||||||
@ -999,7 +999,7 @@ fn internal_set_interrupt_handler(handler: InterruptHandler) {
|
|||||||
}
|
}
|
||||||
#[cfg(esp32h2)]
|
#[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_RX);
|
||||||
crate::interrupt::disable(core, Interrupt::PARL_IO_TX);
|
crate::interrupt::disable(core, Interrupt::PARL_IO_TX);
|
||||||
}
|
}
|
||||||
@ -1107,7 +1107,7 @@ impl<'d> ParlIoFullDuplex<'d, Blocking> {
|
|||||||
|
|
||||||
/// Convert to an async version.
|
/// Convert to an async version.
|
||||||
pub fn into_async(self) -> ParlIoFullDuplex<'d, Async> {
|
pub fn into_async(self) -> ParlIoFullDuplex<'d, Async> {
|
||||||
for core in crate::Cpu::other() {
|
for core in crate::system::Cpu::other() {
|
||||||
#[cfg(esp32c6)]
|
#[cfg(esp32c6)]
|
||||||
{
|
{
|
||||||
crate::interrupt::disable(core, Interrupt::PARL_IO);
|
crate::interrupt::disable(core, Interrupt::PARL_IO);
|
||||||
@ -1244,7 +1244,7 @@ impl<'d> ParlIoTxOnly<'d, Blocking> {
|
|||||||
|
|
||||||
/// Converts to Async mode.
|
/// Converts to Async mode.
|
||||||
pub fn into_async(self) -> ParlIoTxOnly<'d, Async> {
|
pub fn into_async(self) -> ParlIoTxOnly<'d, Async> {
|
||||||
for core in crate::Cpu::other() {
|
for core in crate::system::Cpu::other() {
|
||||||
#[cfg(esp32c6)]
|
#[cfg(esp32c6)]
|
||||||
{
|
{
|
||||||
crate::interrupt::disable(core, Interrupt::PARL_IO);
|
crate::interrupt::disable(core, Interrupt::PARL_IO);
|
||||||
@ -1372,7 +1372,7 @@ impl<'d> ParlIoRxOnly<'d, Blocking> {
|
|||||||
|
|
||||||
/// Converts to Async mode.
|
/// Converts to Async mode.
|
||||||
pub fn into_async(self) -> ParlIoRxOnly<'d, Async> {
|
pub fn into_async(self) -> ParlIoRxOnly<'d, Async> {
|
||||||
for core in crate::Cpu::other() {
|
for core in crate::system::Cpu::other() {
|
||||||
#[cfg(esp32c6)]
|
#[cfg(esp32c6)]
|
||||||
{
|
{
|
||||||
crate::interrupt::disable(core, Interrupt::PARL_IO);
|
crate::interrupt::disable(core, Interrupt::PARL_IO);
|
||||||
|
@ -188,7 +188,7 @@ impl<'d> Pcnt<'d> {
|
|||||||
/// handlers.
|
/// handlers.
|
||||||
#[instability::unstable]
|
#[instability::unstable]
|
||||||
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, Interrupt::PCNT);
|
||||||
}
|
}
|
||||||
unsafe { interrupt::bind_interrupt(Interrupt::PCNT, handler.handler()) };
|
unsafe { interrupt::bind_interrupt(Interrupt::PCNT, handler.handler()) };
|
||||||
|
@ -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()
|
|
||||||
}
|
|
@ -449,7 +449,7 @@ impl<'d> Rmt<'d, Blocking> {
|
|||||||
/// handlers.
|
/// handlers.
|
||||||
#[instability::unstable]
|
#[instability::unstable]
|
||||||
pub fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, Interrupt::RMT);
|
||||||
}
|
}
|
||||||
unsafe { crate::interrupt::bind_interrupt(Interrupt::RMT, handler.handler()) };
|
unsafe { crate::interrupt::bind_interrupt(Interrupt::RMT, handler.handler()) };
|
||||||
|
@ -113,21 +113,21 @@ pub(crate) fn rtc_get_reset_reason(cpu_num: u32) -> u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn software_reset_cpu() {
|
pub(crate) fn software_reset_cpu(cpu_num: u32) {
|
||||||
extern "C" {
|
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)]
|
#[inline(always)]
|
||||||
pub(crate) fn software_reset() {
|
pub(crate) fn software_reset() -> ! {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn software_reset();
|
fn software_reset() -> !;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { software_reset() };
|
unsafe { software_reset() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(esp32s3)]
|
#[cfg(esp32s3)]
|
||||||
|
@ -28,10 +28,9 @@ use crate::{
|
|||||||
pac,
|
pac,
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals::{Interrupt, RSA},
|
peripherals::{Interrupt, RSA},
|
||||||
system::{GenericPeripheralGuard, Peripheral as PeripheralEnable},
|
system::{Cpu, GenericPeripheralGuard, Peripheral as PeripheralEnable},
|
||||||
Async,
|
Async,
|
||||||
Blocking,
|
Blocking,
|
||||||
Cpu,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg_attr(esp32s2, path = "esp32sX.rs")]
|
#[cfg_attr(esp32s2, path = "esp32sX.rs")]
|
||||||
@ -75,7 +74,7 @@ impl<'d> Rsa<'d, Blocking> {
|
|||||||
/// handlers.
|
/// handlers.
|
||||||
#[instability::unstable]
|
#[instability::unstable]
|
||||||
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, Interrupt::RSA);
|
||||||
}
|
}
|
||||||
unsafe { crate::interrupt::bind_interrupt(Interrupt::RSA, handler.handler()) };
|
unsafe { crate::interrupt::bind_interrupt(Interrupt::RSA, handler.handler()) };
|
||||||
|
@ -126,9 +126,8 @@ use crate::{
|
|||||||
interrupt::{self, InterruptHandler},
|
interrupt::{self, InterruptHandler},
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals::Interrupt,
|
peripherals::Interrupt,
|
||||||
reset::{SleepSource, WakeupReason},
|
system::{Cpu, SleepSource},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
Cpu,
|
|
||||||
};
|
};
|
||||||
#[cfg(not(any(esp32c6, esp32h2)))]
|
#[cfg(not(any(esp32c6, esp32h2)))]
|
||||||
use crate::{
|
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)))]
|
#[cfg(not(any(esp32c6, esp32h2)))]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
@ -474,7 +514,7 @@ impl<'d> Rtc<'d> {
|
|||||||
let interrupt = Interrupt::RTC_CORE;
|
let interrupt = Interrupt::RTC_CORE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for core in crate::Cpu::other() {
|
for core in crate::system::Cpu::other() {
|
||||||
crate::interrupt::disable(core, interrupt);
|
crate::interrupt::disable(core, interrupt);
|
||||||
}
|
}
|
||||||
unsafe { interrupt::bind_interrupt(interrupt, handler.handler()) };
|
unsafe { interrupt::bind_interrupt(interrupt, handler.handler()) };
|
||||||
|
@ -56,7 +56,7 @@ pub enum WakeupLevel {
|
|||||||
/// # use core::time::Duration;
|
/// # use core::time::Duration;
|
||||||
/// # use esp_hal::delay::Delay;
|
/// # use esp_hal::delay::Delay;
|
||||||
/// # use esp_hal::rtc_cntl::{reset_reason, sleep::TimerWakeupSource, wakeup_cause, Rtc, SocResetReason};
|
/// # 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 delay = Delay::new();
|
||||||
/// let mut rtc = Rtc::new(peripherals.LPWR);
|
/// let mut rtc = Rtc::new(peripherals.LPWR);
|
||||||
@ -104,7 +104,7 @@ pub enum Error {
|
|||||||
/// # use core::time::Duration;
|
/// # use core::time::Duration;
|
||||||
/// # use esp_hal::delay::Delay;
|
/// # use esp_hal::delay::Delay;
|
||||||
/// # use esp_hal::rtc_cntl::{reset_reason, sleep::{Ext0WakeupSource, TimerWakeupSource, WakeupLevel}, wakeup_cause, Rtc, SocResetReason};
|
/// # 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};
|
/// # use esp_hal::gpio::{Input, InputConfig, Pull};
|
||||||
///
|
///
|
||||||
/// let delay = Delay::new();
|
/// let delay = Delay::new();
|
||||||
@ -157,7 +157,7 @@ impl<'a, P: RtcIoWakeupPinType> Ext0WakeupSource<'a, P> {
|
|||||||
/// # use core::time::Duration;
|
/// # use core::time::Duration;
|
||||||
/// # use esp_hal::delay::Delay;
|
/// # use esp_hal::delay::Delay;
|
||||||
/// # use esp_hal::rtc_cntl::{reset_reason, sleep::{Ext1WakeupSource, TimerWakeupSource, WakeupLevel}, wakeup_cause, Rtc, SocResetReason};
|
/// # 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::gpio::{Input, InputConfig, Pull, RtcPin};
|
||||||
/// # use esp_hal::peripheral::Peripheral;
|
/// # use esp_hal::peripheral::Peripheral;
|
||||||
///
|
///
|
||||||
@ -214,7 +214,7 @@ impl<'a, 'b> Ext1WakeupSource<'a, 'b> {
|
|||||||
/// # use core::time::Duration;
|
/// # use core::time::Duration;
|
||||||
/// # use esp_hal::delay::Delay;
|
/// # use esp_hal::delay::Delay;
|
||||||
/// # use esp_hal::rtc_cntl::{reset_reason, sleep::{Ext1WakeupSource, TimerWakeupSource, WakeupLevel}, wakeup_cause, Rtc, SocResetReason};
|
/// # 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::gpio::{Input, InputConfig, Pull, RtcPinWithResistors};
|
||||||
/// # use esp_hal::peripheral::Peripheral;
|
/// # use esp_hal::peripheral::Peripheral;
|
||||||
///
|
///
|
||||||
@ -276,7 +276,7 @@ impl<'a, 'b> Ext1WakeupSource<'a, 'b> {
|
|||||||
/// # use esp_hal::delay::Delay;
|
/// # use esp_hal::delay::Delay;
|
||||||
/// # use esp_hal::gpio::{self, Input, InputConfig, Pull};
|
/// # 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::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;
|
/// # use esp_hal::peripheral::Peripheral;
|
||||||
///
|
///
|
||||||
/// let mut rtc = Rtc::new(peripherals.LPWR);
|
/// let mut rtc = Rtc::new(peripherals.LPWR);
|
||||||
|
@ -111,7 +111,7 @@ impl crate::private::Sealed for Sha<'_> {}
|
|||||||
#[instability::unstable]
|
#[instability::unstable]
|
||||||
impl crate::interrupt::InterruptConfigurable for Sha<'_> {
|
impl crate::interrupt::InterruptConfigurable for Sha<'_> {
|
||||||
fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, Interrupt::SHA);
|
||||||
}
|
}
|
||||||
unsafe { crate::interrupt::bind_interrupt(Interrupt::SHA, handler.handler()) };
|
unsafe { crate::interrupt::bind_interrupt(Interrupt::SHA, handler.handler()) };
|
||||||
|
@ -4,53 +4,6 @@
|
|||||||
//! This module provides essential functionality for controlling
|
//! This module provides essential functionality for controlling
|
||||||
//! and managing the APP (second) CPU core on the `ESP32` chip. It is used to
|
//! and managing the APP (second) CPU core on the `ESP32` chip. It is used to
|
||||||
//! start and stop program execution on the APP core.
|
//! 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::{
|
use core::{
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
@ -60,7 +13,7 @@ use core::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals::{CPU_CTRL, DPORT, LPWR, SPI0},
|
peripherals::{CPU_CTRL, DPORT, LPWR, SPI0},
|
||||||
Cpu,
|
system::Cpu,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Data type for a properly aligned stack of N bytes
|
/// 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
|
// Stack frame alignment depends on the SIZE as well as the placement of the
|
||||||
// array.
|
// array.
|
||||||
#[repr(C, align(16))]
|
#[repr(C, align(16))]
|
||||||
|
#[instability::unstable]
|
||||||
pub struct Stack<const SIZE: usize> {
|
pub struct Stack<const SIZE: usize> {
|
||||||
/// Memory to be used for the stack
|
/// Memory to be used for the stack
|
||||||
pub mem: MaybeUninit<[u8; SIZE]>,
|
pub mem: MaybeUninit<[u8; SIZE]>,
|
||||||
@ -91,6 +45,7 @@ impl<const SIZE: usize> Default for Stack<SIZE> {
|
|||||||
#[allow(clippy::len_without_is_empty)]
|
#[allow(clippy::len_without_is_empty)]
|
||||||
impl<const SIZE: usize> Stack<SIZE> {
|
impl<const SIZE: usize> Stack<SIZE> {
|
||||||
/// Construct a stack of length SIZE, uninitialized
|
/// Construct a stack of length SIZE, uninitialized
|
||||||
|
#[instability::unstable]
|
||||||
pub const fn new() -> Stack<SIZE> {
|
pub const fn new() -> Stack<SIZE> {
|
||||||
::core::assert!(SIZE % 16 == 0); // Make sure stack top is aligned, too.
|
::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 {
|
pub const fn len(&self) -> usize {
|
||||||
SIZE
|
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 {
|
pub fn bottom(&mut self) -> *mut u32 {
|
||||||
self.mem.as_mut_ptr() as *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 {
|
pub fn top(&mut self) -> *mut u32 {
|
||||||
unsafe { self.bottom().add(SIZE / 4) }
|
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
|
// Pointer to the closure that will be executed on the second core. The closure
|
||||||
// is copied to the core's stack.
|
// is copied to the core's stack.
|
||||||
static mut START_CORE1_FUNCTION: Option<*mut ()> = None;
|
static mut START_CORE1_FUNCTION: Option<*mut ()> = None;
|
||||||
|
|
||||||
static mut APP_CORE_STACK_TOP: Option<*mut u32> = None;
|
static mut APP_CORE_STACK_TOP: Option<*mut u32> = None;
|
||||||
|
|
||||||
/// Will park the APP (second) core when dropped
|
/// 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> {
|
pub struct AppCoreGuard<'a> {
|
||||||
phantom: PhantomData<&'a ()>,
|
phantom: PhantomData<&'a ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for AppCoreGuard<'_> {
|
impl Drop for AppCoreGuard<'_> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe { internal_park_core(Cpu::AppCpu, true) };
|
||||||
internal_park_core(Cpu::AppCpu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents errors that can occur while working with the core.
|
/// Represents errors that can occur while working with the core.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[instability::unstable]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// The core is already running.
|
/// The core is already running.
|
||||||
CoreAlreadyRunning,
|
CoreAlreadyRunning,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Control CPU Cores
|
/// 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> {
|
pub struct CpuControl<'d> {
|
||||||
_cpu_control: PeripheralRef<'d, CPU_CTRL>,
|
_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 {
|
match core {
|
||||||
Cpu::ProCpu => {
|
Cpu::ProCpu => {
|
||||||
LPWR::regs()
|
LPWR::regs()
|
||||||
.sw_cpu_stall()
|
.sw_cpu_stall()
|
||||||
.modify(|_, w| w.sw_stall_procpu_c1().bits(0x21));
|
.modify(|_, w| w.sw_stall_procpu_c1().bits(c1_value));
|
||||||
LPWR::regs()
|
LPWR::regs()
|
||||||
.options0()
|
.options0()
|
||||||
.modify(|_, w| w.sw_stall_procpu_c0().bits(0x02));
|
.modify(|_, w| w.sw_stall_procpu_c0().bits(c0_value));
|
||||||
}
|
}
|
||||||
Cpu::AppCpu => {
|
Cpu::AppCpu => {
|
||||||
LPWR::regs()
|
LPWR::regs()
|
||||||
.sw_cpu_stall()
|
.sw_cpu_stall()
|
||||||
.modify(|_, w| w.sw_stall_appcpu_c1().bits(0x21));
|
.modify(|_, w| w.sw_stall_appcpu_c1().bits(c1_value));
|
||||||
LPWR::regs()
|
LPWR::regs()
|
||||||
.options0()
|
.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
|
/// The user must ensure that the core being parked is not the core which is
|
||||||
/// currently executing their code.
|
/// currently executing their code.
|
||||||
|
#[instability::unstable]
|
||||||
pub unsafe fn park_core(&mut self, core: Cpu) {
|
pub unsafe fn park_core(&mut self, core: Cpu) {
|
||||||
internal_park_core(core);
|
internal_park_core(core, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unpark the given core
|
/// Unpark the given core
|
||||||
|
#[instability::unstable]
|
||||||
pub fn unpark_core(&mut self, core: Cpu) {
|
pub fn unpark_core(&mut self, core: Cpu) {
|
||||||
match core {
|
unsafe { internal_park_core(core, false) };
|
||||||
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) });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush_cache(&mut self, core: Cpu) {
|
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>>()) };
|
let entry = unsafe { ManuallyDrop::take(&mut *entry.cast::<ManuallyDrop<F>>()) };
|
||||||
entry();
|
entry();
|
||||||
loop {
|
loop {
|
||||||
unsafe { internal_park_core(Cpu::current()) };
|
unsafe { internal_park_core(Cpu::current(), true) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => panic!("No start function set"),
|
None => panic!("No start function set"),
|
||||||
@ -336,6 +328,7 @@ impl<'d> CpuControl<'d> {
|
|||||||
/// closure exits, the core will be parked.
|
/// closure exits, the core will be parked.
|
||||||
///
|
///
|
||||||
/// Dropping the returned guard will park the core.
|
/// Dropping the returned guard will park the core.
|
||||||
|
#[instability::unstable]
|
||||||
pub fn start_app_core<'a, const SIZE: usize, F>(
|
pub fn start_app_core<'a, const SIZE: usize, F>(
|
||||||
&mut self,
|
&mut self,
|
||||||
stack: &'static mut Stack<SIZE>,
|
stack: &'static mut Stack<SIZE>,
|
||||||
|
@ -46,7 +46,7 @@ use crate::{
|
|||||||
gpio::{AlternateFunction, GpioPin},
|
gpio::{AlternateFunction, GpioPin},
|
||||||
pac::io_mux,
|
pac::io_mux,
|
||||||
peripherals::{GPIO, IO_MUX},
|
peripherals::{GPIO, IO_MUX},
|
||||||
Cpu,
|
system::Cpu,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The total number of GPIO pins available.
|
/// The total number of GPIO pins available.
|
||||||
|
@ -97,7 +97,7 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
|
|||||||
addr_of_mut!(_rtc_slow_bss_end),
|
addr_of_mut!(_rtc_slow_bss_end),
|
||||||
);
|
);
|
||||||
if matches!(
|
if matches!(
|
||||||
crate::reset::reset_reason(),
|
crate::system::reset_reason(),
|
||||||
None | Some(SocResetReason::ChipPowerOn)
|
None | Some(SocResetReason::ChipPowerOn)
|
||||||
) {
|
) {
|
||||||
xtensa_lx_rt::zero_bss(
|
xtensa_lx_rt::zero_bss(
|
||||||
|
@ -101,7 +101,7 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
|
|||||||
addr_of_mut!(_rtc_slow_bss_end),
|
addr_of_mut!(_rtc_slow_bss_end),
|
||||||
);
|
);
|
||||||
if matches!(
|
if matches!(
|
||||||
crate::reset::reset_reason(),
|
crate::system::reset_reason(),
|
||||||
None | Some(SocResetReason::ChipPowerOn)
|
None | Some(SocResetReason::ChipPowerOn)
|
||||||
) {
|
) {
|
||||||
xtensa_lx_rt::zero_bss(
|
xtensa_lx_rt::zero_bss(
|
||||||
|
@ -5,53 +5,6 @@
|
|||||||
//! This module provides essential functionality for controlling
|
//! This module provides essential functionality for controlling
|
||||||
//! and managing the APP (second) CPU core on the `ESP32-S3` chip. It is used to
|
//! 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.
|
//! 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::{
|
use core::{
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
@ -60,8 +13,8 @@ use core::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals::CPU_CTRL,
|
peripherals::{CPU_CTRL, LPWR, SYSTEM},
|
||||||
Cpu,
|
system::Cpu,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Data type for a properly aligned stack of N bytes
|
/// 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
|
// Stack frame alignment depends on the SIZE as well as the placement of the
|
||||||
// array.
|
// array.
|
||||||
#[repr(C, align(16))]
|
#[repr(C, align(16))]
|
||||||
|
#[instability::unstable]
|
||||||
pub struct Stack<const SIZE: usize> {
|
pub struct Stack<const SIZE: usize> {
|
||||||
/// Memory to be used for the stack
|
/// Memory to be used for the stack
|
||||||
pub mem: MaybeUninit<[u8; SIZE]>,
|
pub mem: MaybeUninit<[u8; SIZE]>,
|
||||||
@ -92,6 +46,7 @@ impl<const SIZE: usize> Default for Stack<SIZE> {
|
|||||||
#[allow(clippy::len_without_is_empty)]
|
#[allow(clippy::len_without_is_empty)]
|
||||||
impl<const SIZE: usize> Stack<SIZE> {
|
impl<const SIZE: usize> Stack<SIZE> {
|
||||||
/// Construct a stack of length SIZE, uninitialized
|
/// Construct a stack of length SIZE, uninitialized
|
||||||
|
#[instability::unstable]
|
||||||
pub const fn new() -> Stack<SIZE> {
|
pub const fn new() -> Stack<SIZE> {
|
||||||
::core::assert!(SIZE % 16 == 0); // Make sure stack top is aligned, too.
|
::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.
|
/// Returns the length of the stack in bytes.
|
||||||
|
#[instability::unstable]
|
||||||
pub const fn len(&self) -> usize {
|
pub const fn len(&self) -> usize {
|
||||||
SIZE
|
SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns 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 {
|
pub fn bottom(&mut self) -> *mut u32 {
|
||||||
self.mem.as_mut_ptr() as *mut u32
|
self.mem.as_mut_ptr() as *mut u32
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns 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 {
|
pub fn top(&mut self) -> *mut u32 {
|
||||||
unsafe { self.bottom().add(SIZE / 4) }
|
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;
|
static mut APP_CORE_STACK_TOP: Option<*mut u32> = None;
|
||||||
|
|
||||||
/// Will park the APP (second) core when dropped
|
/// 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> {
|
pub struct AppCoreGuard<'a> {
|
||||||
phantom: PhantomData<&'a ()>,
|
phantom: PhantomData<&'a ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for AppCoreGuard<'_> {
|
impl Drop for AppCoreGuard<'_> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe { internal_park_core(Cpu::AppCpu, true) };
|
||||||
internal_park_core(Cpu::AppCpu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents errors that can occur while working with the core.
|
/// Represents errors that can occur while working with the core.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[instability::unstable]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// The core is already running.
|
/// The core is already running.
|
||||||
CoreAlreadyRunning,
|
CoreAlreadyRunning,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Control CPU Cores
|
/// 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> {
|
pub struct CpuControl<'d> {
|
||||||
_cpu_control: PeripheralRef<'d, CPU_CTRL>,
|
_cpu_control: PeripheralRef<'d, CPU_CTRL>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn internal_park_core(core: Cpu) {
|
unsafe fn internal_park_core(core: Cpu, park: bool) {
|
||||||
let rtc_control = crate::peripherals::LPWR::regs();
|
let c1_value = if park { 0x21 } else { 0 };
|
||||||
|
let c0_value = if park { 0x02 } else { 0 };
|
||||||
match core {
|
match core {
|
||||||
Cpu::ProCpu => {
|
Cpu::ProCpu => {
|
||||||
rtc_control
|
LPWR::regs()
|
||||||
.sw_cpu_stall()
|
.sw_cpu_stall()
|
||||||
.modify(|_, w| w.sw_stall_procpu_c1().bits(0x21));
|
.modify(|_, w| w.sw_stall_procpu_c1().bits(c1_value));
|
||||||
rtc_control
|
LPWR::regs()
|
||||||
.options0()
|
.options0()
|
||||||
.modify(|_, w| w.sw_stall_procpu_c0().bits(0x02));
|
.modify(|_, w| w.sw_stall_procpu_c0().bits(c0_value));
|
||||||
}
|
}
|
||||||
Cpu::AppCpu => {
|
Cpu::AppCpu => {
|
||||||
rtc_control
|
LPWR::regs()
|
||||||
.sw_cpu_stall()
|
.sw_cpu_stall()
|
||||||
.modify(|_, w| w.sw_stall_appcpu_c1().bits(0x21));
|
.modify(|_, w| w.sw_stall_appcpu_c1().bits(c1_value));
|
||||||
rtc_control
|
LPWR::regs()
|
||||||
.options0()
|
.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
|
/// The user must ensure that the core being parked is not the core which is
|
||||||
/// currently executing their code.
|
/// currently executing their code.
|
||||||
|
#[instability::unstable]
|
||||||
pub unsafe fn park_core(&mut self, core: Cpu) {
|
pub unsafe fn park_core(&mut self, core: Cpu) {
|
||||||
internal_park_core(core);
|
internal_park_core(core, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unpark the given core
|
/// Unpark the given core
|
||||||
|
#[instability::unstable]
|
||||||
pub fn unpark_core(&mut self, core: Cpu) {
|
pub fn unpark_core(&mut self, core: Cpu) {
|
||||||
let rtc_control = crate::peripherals::LPWR::regs();
|
unsafe { internal_park_core(core, false) };
|
||||||
|
|
||||||
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) });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When we get here, the core is out of reset, with a stack setup by ROM
|
/// 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>>()) };
|
let entry = unsafe { ManuallyDrop::take(&mut *entry.cast::<ManuallyDrop<F>>()) };
|
||||||
entry();
|
entry();
|
||||||
loop {
|
loop {
|
||||||
unsafe { internal_park_core(Cpu::current()) };
|
unsafe { internal_park_core(Cpu::current(), true) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => panic!("No start function set"),
|
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
|
/// The second core will start running the closure `entry`. Note that if the
|
||||||
/// closure exits, the core will be parked.
|
/// closure exits, the core will be parked.
|
||||||
///
|
///
|
||||||
/// Dropping the returned guard will park the core.
|
/// Dropping the returned guard will park the core.
|
||||||
|
#[instability::unstable]
|
||||||
pub fn start_app_core<'a, const SIZE: usize, F>(
|
pub fn start_app_core<'a, const SIZE: usize, F>(
|
||||||
&mut self,
|
&mut self,
|
||||||
stack: &'static mut Stack<SIZE>,
|
stack: &'static mut Stack<SIZE>,
|
||||||
@ -287,7 +277,7 @@ impl<'d> CpuControl<'d> {
|
|||||||
F: FnOnce(),
|
F: FnOnce(),
|
||||||
F: Send + 'a,
|
F: Send + 'a,
|
||||||
{
|
{
|
||||||
let system_control = crate::peripherals::SYSTEM::regs();
|
let system_control = SYSTEM::regs();
|
||||||
|
|
||||||
if !xtensa_lx::is_debugger_attached()
|
if !xtensa_lx::is_debugger_attached()
|
||||||
&& system_control
|
&& system_control
|
||||||
|
@ -140,7 +140,7 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
|
|||||||
addr_of_mut!(_rtc_slow_bss_end),
|
addr_of_mut!(_rtc_slow_bss_end),
|
||||||
);
|
);
|
||||||
if matches!(
|
if matches!(
|
||||||
crate::reset::reset_reason(),
|
crate::system::reset_reason(),
|
||||||
None | Some(SocResetReason::ChipPowerOn)
|
None | Some(SocResetReason::ChipPowerOn)
|
||||||
) {
|
) {
|
||||||
xtensa_lx_rt::zero_bss(
|
xtensa_lx_rt::zero_bss(
|
||||||
|
@ -59,11 +59,10 @@ use crate::{
|
|||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
private::{self, Sealed},
|
private::{self, Sealed},
|
||||||
spi::AnySpi,
|
spi::AnySpi,
|
||||||
system::PeripheralGuard,
|
system::{Cpu, PeripheralGuard},
|
||||||
time::Rate,
|
time::Rate,
|
||||||
Async,
|
Async,
|
||||||
Blocking,
|
Blocking,
|
||||||
Cpu,
|
|
||||||
DriverMode,
|
DriverMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1345,7 +1344,7 @@ mod dma {
|
|||||||
/// Interrupts are not enabled at the peripheral level here.
|
/// Interrupts are not enabled at the peripheral level here.
|
||||||
fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
|
fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
|
||||||
let interrupt = self.driver().info.interrupt;
|
let interrupt = self.driver().info.interrupt;
|
||||||
for core in crate::Cpu::other() {
|
for core in crate::system::Cpu::other() {
|
||||||
crate::interrupt::disable(core, interrupt);
|
crate::interrupt::disable(core, interrupt);
|
||||||
}
|
}
|
||||||
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
|
unsafe { crate::interrupt::bind_interrupt(interrupt, handler.handler()) };
|
||||||
|
@ -128,7 +128,7 @@ mod multicore {
|
|||||||
const UNUSED_THREAD_ID_VALUE: usize = 0x100;
|
const UNUSED_THREAD_ID_VALUE: usize = 0x100;
|
||||||
|
|
||||||
pub fn thread_id() -> usize {
|
pub fn thread_id() -> usize {
|
||||||
crate::raw_core()
|
crate::system::raw_core()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct AtomicLock {
|
pub(super) struct AtomicLock {
|
||||||
|
@ -3,19 +3,9 @@
|
|||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
|
|
||||||
use critical_section::{CriticalSection, Mutex};
|
use critical_section::{CriticalSection, Mutex};
|
||||||
use strum::{EnumCount, EnumIter, IntoEnumIterator};
|
|
||||||
|
|
||||||
use crate::peripherals::SYSTEM;
|
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`.
|
/// Peripherals which can be enabled via `PeripheralClockControl`.
|
||||||
///
|
///
|
||||||
/// This enum represents various hardware peripherals that can be enabled
|
/// 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
|
// FIXME: This enum needs to be public because it's exposed via a bunch of traits, but it's not
|
||||||
// useful to users.
|
// useful to users.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, EnumCount, EnumIter)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Peripheral {
|
pub enum Peripheral {
|
||||||
@ -132,6 +122,90 @@ pub enum Peripheral {
|
|||||||
Tsens,
|
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 {
|
impl Peripheral {
|
||||||
pub fn try_from(value: u8) -> Option<Peripheral> {
|
pub fn try_from(value: u8) -> Option<Peripheral> {
|
||||||
if value >= Peripheral::COUNT as u8 {
|
if value >= Peripheral::COUNT as u8 {
|
||||||
@ -151,11 +225,11 @@ static PERIPHERAL_REF_COUNT: Mutex<RefCell<[usize; Peripheral::COUNT]>> =
|
|||||||
pub(crate) fn disable_peripherals() {
|
pub(crate) fn disable_peripherals() {
|
||||||
// Take the critical section up front to avoid taking it multiple times.
|
// Take the critical section up front to avoid taking it multiple times.
|
||||||
critical_section::with(|cs| {
|
critical_section::with(|cs| {
|
||||||
for p in Peripheral::iter() {
|
for p in Peripheral::ALL {
|
||||||
if KEEP_ENABLED.contains(&p) {
|
if Peripheral::KEEP_ENABLED.contains(p) {
|
||||||
continue;
|
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 {
|
impl PeripheralGuard {
|
||||||
pub(crate) fn new_with(p: Peripheral, init: fn()) -> Self {
|
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);
|
PeripheralClockControl::reset(p);
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@ -183,7 +257,7 @@ impl PeripheralGuard {
|
|||||||
|
|
||||||
impl Drop for PeripheralGuard {
|
impl Drop for PeripheralGuard {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if !KEEP_ENABLED.contains(&self.peripheral) {
|
if !Peripheral::KEEP_ENABLED.contains(&self.peripheral) {
|
||||||
PeripheralClockControl::disable(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 {
|
pub(crate) fn new_with(init: fn(CriticalSection<'_>)) -> Self {
|
||||||
let peripheral = unwrap!(Peripheral::try_from(P));
|
let peripheral = unwrap!(Peripheral::try_from(P));
|
||||||
critical_section::with(|cs| {
|
critical_section::with(|cs| {
|
||||||
if !KEEP_ENABLED.contains(&peripheral)
|
if !Peripheral::KEEP_ENABLED.contains(&peripheral)
|
||||||
&& PeripheralClockControl::enable_with_cs(peripheral, cs)
|
&& PeripheralClockControl::enable_with_cs(peripheral, cs)
|
||||||
{
|
{
|
||||||
PeripheralClockControl::reset(peripheral);
|
PeripheralClockControl::reset(peripheral);
|
||||||
@ -216,7 +290,7 @@ impl<const P: u8> GenericPeripheralGuard<P> {
|
|||||||
impl<const P: u8> Drop for GenericPeripheralGuard<P> {
|
impl<const P: u8> Drop for GenericPeripheralGuard<P> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let peripheral = unwrap!(Peripheral::try_from(P));
|
let peripheral = unwrap!(Peripheral::try_from(P));
|
||||||
if !KEEP_ENABLED.contains(&peripheral) {
|
if !Peripheral::KEEP_ENABLED.contains(&peripheral) {
|
||||||
PeripheralClockControl::disable(peripheral);
|
PeripheralClockControl::disable(peripheral);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1075,3 +1149,155 @@ impl PeripheralClockControl {
|
|||||||
true
|
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()
|
||||||
|
}
|
||||||
|
@ -52,10 +52,10 @@ use crate::{
|
|||||||
interrupt::{InterruptConfigurable, InterruptHandler},
|
interrupt::{InterruptConfigurable, InterruptHandler},
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals::Interrupt,
|
peripherals::Interrupt,
|
||||||
|
system::Cpu,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
Async,
|
Async,
|
||||||
Blocking,
|
Blocking,
|
||||||
Cpu,
|
|
||||||
DriverMode,
|
DriverMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,9 +26,8 @@ use crate::{
|
|||||||
peripheral::Peripheral,
|
peripheral::Peripheral,
|
||||||
peripherals::{Interrupt, SYSTIMER},
|
peripherals::{Interrupt, SYSTIMER},
|
||||||
sync::{lock, RawMutex},
|
sync::{lock, RawMutex},
|
||||||
system::{Peripheral as PeripheralEnable, PeripheralClockControl},
|
system::{Cpu, Peripheral as PeripheralEnable, PeripheralClockControl},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
Cpu,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The configuration of a unit.
|
/// The configuration of a unit.
|
||||||
@ -397,7 +396,7 @@ impl Alarm {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
for core in crate::Cpu::other() {
|
for core in crate::system::Cpu::other() {
|
||||||
crate::interrupt::disable(core, interrupt);
|
crate::interrupt::disable(core, interrupt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ impl Timer {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
for core in crate::Cpu::other() {
|
for core in crate::system::Cpu::other() {
|
||||||
crate::interrupt::disable(core, interrupt);
|
crate::interrupt::disable(core, interrupt);
|
||||||
}
|
}
|
||||||
unsafe { interrupt::bind_interrupt(interrupt, handler.handler()) };
|
unsafe { interrupt::bind_interrupt(interrupt, handler.handler()) };
|
||||||
|
@ -131,7 +131,7 @@ use crate::{
|
|||||||
interrupt::InterruptHandler,
|
interrupt::InterruptHandler,
|
||||||
pac::twai0::RegisterBlock,
|
pac::twai0::RegisterBlock,
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
system::PeripheralGuard,
|
system::{Cpu, PeripheralGuard},
|
||||||
twai::filter::SingleStandardFilter,
|
twai::filter::SingleStandardFilter,
|
||||||
Async,
|
Async,
|
||||||
Blocking,
|
Blocking,
|
||||||
@ -745,7 +745,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn internal_set_interrupt_handler(&mut self, handler: InterruptHandler) {
|
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());
|
crate::interrupt::disable(core, self.twai.interrupt());
|
||||||
}
|
}
|
||||||
unsafe { crate::interrupt::bind_interrupt(self.twai.interrupt(), handler.handler()) };
|
unsafe { crate::interrupt::bind_interrupt(self.twai.interrupt(), handler.handler()) };
|
||||||
@ -986,7 +986,7 @@ impl<'d> TwaiConfiguration<'d, Blocking> {
|
|||||||
impl<'d> TwaiConfiguration<'d, Async> {
|
impl<'d> TwaiConfiguration<'d, Async> {
|
||||||
/// Convert the configuration into a blocking configuration.
|
/// Convert the configuration into a blocking configuration.
|
||||||
pub fn into_blocking(self) -> TwaiConfiguration<'d, Blocking> {
|
pub fn into_blocking(self) -> TwaiConfiguration<'d, Blocking> {
|
||||||
use crate::{interrupt, Cpu};
|
use crate::{interrupt, system::Cpu};
|
||||||
|
|
||||||
interrupt::disable(Cpu::current(), self.twai.interrupt());
|
interrupt::disable(Cpu::current(), self.twai.interrupt());
|
||||||
|
|
||||||
|
@ -2234,7 +2234,7 @@ impl Info {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_interrupt_handler(&self, handler: InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, self.interrupt);
|
||||||
}
|
}
|
||||||
self.enable_listen(EnumSet::all(), false);
|
self.enable_listen(EnumSet::all(), false);
|
||||||
@ -2244,7 +2244,7 @@ impl Info {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn disable_interrupts(&self) {
|
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> {
|
fn apply_config(&self, config: &Config) -> Result<(), ConfigError> {
|
||||||
|
@ -132,10 +132,9 @@ use crate::{
|
|||||||
pac::usb_device::RegisterBlock,
|
pac::usb_device::RegisterBlock,
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals::{Interrupt, USB_DEVICE},
|
peripherals::{Interrupt, USB_DEVICE},
|
||||||
system::PeripheralClockControl,
|
system::{Cpu, PeripheralClockControl},
|
||||||
Async,
|
Async,
|
||||||
Blocking,
|
Blocking,
|
||||||
Cpu,
|
|
||||||
DriverMode,
|
DriverMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -447,7 +446,7 @@ where
|
|||||||
/// handlers.
|
/// handlers.
|
||||||
#[instability::unstable]
|
#[instability::unstable]
|
||||||
pub fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
|
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);
|
crate::interrupt::disable(core, Interrupt::USB_DEVICE);
|
||||||
}
|
}
|
||||||
unsafe { crate::interrupt::bind_interrupt(Interrupt::USB_DEVICE, handler.handler()) };
|
unsafe { crate::interrupt::bind_interrupt(Interrupt::USB_DEVICE, handler.handler()) };
|
||||||
|
@ -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 {
|
pub(crate) unsafe extern "C" fn interrupt_off(intr_num: i32) -> i32 {
|
||||||
trace!("interrupt_off {}", intr_num);
|
trace!("interrupt_off {}", intr_num);
|
||||||
interrupt::disable(
|
interrupt::disable(
|
||||||
crate::hal::Cpu::ProCpu,
|
crate::hal::system::Cpu::ProCpu,
|
||||||
Interrupt::try_from(intr_num as u16).unwrap(),
|
Interrupt::try_from(intr_num as u16).unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ pub(crate) fn setup_multitasking() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn disable_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) {
|
extern "C" fn handler(trap_frame: &mut TrapFrame) {
|
||||||
|
@ -7,16 +7,28 @@ pub(crate) fn setup_radio_isr() {
|
|||||||
{
|
{
|
||||||
// It's a mystery why these interrupts are enabled now since it worked without
|
// 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
|
// this before Now at least without disabling these nothing will work
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, peripherals::Interrupt::ETH_MAC);
|
interrupt::disable(
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, peripherals::Interrupt::UART0);
|
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() {
|
pub(crate) fn shutdown_radio_isr() {
|
||||||
#[cfg(feature = "ble")]
|
#[cfg(feature = "ble")]
|
||||||
{
|
{
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, peripherals::Interrupt::RWBT);
|
interrupt::disable(
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, peripherals::Interrupt::BT_BB);
|
crate::hal::system::Cpu::ProCpu,
|
||||||
|
peripherals::Interrupt::RWBT,
|
||||||
|
);
|
||||||
|
interrupt::disable(
|
||||||
|
crate::hal::system::Cpu::ProCpu,
|
||||||
|
peripherals::Interrupt::BT_BB,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ pub(crate) fn setup_radio_isr() {
|
|||||||
pub(crate) fn shutdown_radio_isr() {
|
pub(crate) fn shutdown_radio_isr() {
|
||||||
#[cfg(feature = "ble")]
|
#[cfg(feature = "ble")]
|
||||||
{
|
{
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::LP_TIMER);
|
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::LP_TIMER);
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_MAC);
|
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::BT_MAC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,9 @@ pub(crate) fn setup_radio_isr() {
|
|||||||
pub(crate) fn shutdown_radio_isr() {
|
pub(crate) fn shutdown_radio_isr() {
|
||||||
#[cfg(feature = "ble")]
|
#[cfg(feature = "ble")]
|
||||||
{
|
{
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::RWBT);
|
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::RWBT);
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::RWBLE);
|
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::RWBLE);
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_BB);
|
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::BT_BB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ pub(crate) fn setup_radio_isr() {
|
|||||||
pub(crate) fn shutdown_radio_isr() {
|
pub(crate) fn shutdown_radio_isr() {
|
||||||
#[cfg(feature = "ble")]
|
#[cfg(feature = "ble")]
|
||||||
{
|
{
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::LP_TIMER);
|
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::LP_TIMER);
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_MAC);
|
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::BT_MAC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ pub(crate) fn setup_radio_isr() {
|
|||||||
pub(crate) fn shutdown_radio_isr() {
|
pub(crate) fn shutdown_radio_isr() {
|
||||||
#[cfg(feature = "ble")]
|
#[cfg(feature = "ble")]
|
||||||
{
|
{
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::LP_BLE_TIMER);
|
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::LP_BLE_TIMER);
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_MAC);
|
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::BT_MAC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@ pub(crate) fn setup_radio_isr() {
|
|||||||
pub(crate) fn shutdown_radio_isr() {
|
pub(crate) fn shutdown_radio_isr() {
|
||||||
#[cfg(feature = "ble")]
|
#[cfg(feature = "ble")]
|
||||||
{
|
{
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_BB);
|
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::BT_BB);
|
||||||
interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::RWBLE);
|
interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::RWBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,10 +19,9 @@ use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal}
|
|||||||
use embassy_time::{Duration, Ticker};
|
use embassy_time::{Duration, Ticker};
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
cpu_control::{CpuControl, Stack},
|
|
||||||
gpio::{Level, Output, OutputConfig},
|
gpio::{Level, Output, OutputConfig},
|
||||||
|
system::{Cpu, CpuControl, Stack},
|
||||||
timer::{timg::TimerGroup, AnyTimer},
|
timer::{timg::TimerGroup, AnyTimer},
|
||||||
Cpu,
|
|
||||||
};
|
};
|
||||||
use esp_hal_embassy::Executor;
|
use esp_hal_embassy::Executor;
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
|
@ -18,12 +18,11 @@ use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal}
|
|||||||
use embassy_time::{Duration, Ticker};
|
use embassy_time::{Duration, Ticker};
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
cpu_control::{CpuControl, Stack},
|
|
||||||
gpio::{Level, Output, OutputConfig},
|
gpio::{Level, Output, OutputConfig},
|
||||||
interrupt::{software::SoftwareInterruptControl, Priority},
|
interrupt::{software::SoftwareInterruptControl, Priority},
|
||||||
main,
|
main,
|
||||||
|
system::{Cpu, CpuControl, Stack},
|
||||||
timer::{timg::TimerGroup, AnyTimer},
|
timer::{timg::TimerGroup, AnyTimer},
|
||||||
Cpu,
|
|
||||||
};
|
};
|
||||||
use esp_hal_embassy::InterruptExecutor;
|
use esp_hal_embassy::InterruptExecutor;
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
main,
|
main,
|
||||||
reset::software_reset,
|
system::software_reset,
|
||||||
uart::{self, Uart},
|
uart::{self, Uart},
|
||||||
};
|
};
|
||||||
use esp_ieee802154::{Config, Ieee802154};
|
use esp_ieee802154::{Config, Ieee802154};
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal};
|
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal};
|
||||||
#[cfg(multi_core)]
|
#[cfg(multi_core)]
|
||||||
use esp_hal::cpu_control::{CpuControl, Stack};
|
use esp_hal::system::{CpuControl, Stack};
|
||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
interrupt::{
|
interrupt::{
|
||||||
software::{SoftwareInterrupt, SoftwareInterruptControl},
|
software::{SoftwareInterrupt, SoftwareInterruptControl},
|
||||||
|
@ -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;
|
const DISPLAY_STACK_SIZE: usize = 8192;
|
||||||
let app_core_stack = mk_static!(Stack<DISPLAY_STACK_SIZE>, Stack::new());
|
let app_core_stack = mk_static!(Stack<DISPLAY_STACK_SIZE>, Stack::new());
|
||||||
let cpu_control = CpuControl::new(peripherals.CPU_CTRL);
|
let cpu_control = CpuControl::new(peripherals.CPU_CTRL);
|
||||||
|
@ -42,11 +42,10 @@ cfg_if::cfg_if! {
|
|||||||
if #[cfg(multi_core)] {
|
if #[cfg(multi_core)] {
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
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 DONE: AtomicBool = AtomicBool::new(false);
|
||||||
static mut APP_CORE_STACK: esp_hal::cpu_control::Stack<8192> =
|
static mut APP_CORE_STACK: Stack<8192> = Stack::new();
|
||||||
esp_hal::cpu_control::Stack::new();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use esp_hal::{
|
|||||||
delay::Delay,
|
delay::Delay,
|
||||||
main,
|
main,
|
||||||
rtc_cntl::{reset_reason, sleep::TimerWakeupSource, wakeup_cause, Rtc, SocResetReason},
|
rtc_cntl::{reset_reason, sleep::TimerWakeupSource, wakeup_cause, Rtc, SocResetReason},
|
||||||
Cpu,
|
system::Cpu,
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ use esp_hal::{
|
|||||||
Rtc,
|
Rtc,
|
||||||
SocResetReason,
|
SocResetReason,
|
||||||
},
|
},
|
||||||
Cpu,
|
system::Cpu,
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ use esp_hal::{
|
|||||||
Rtc,
|
Rtc,
|
||||||
SocResetReason,
|
SocResetReason,
|
||||||
},
|
},
|
||||||
Cpu,
|
system::Cpu,
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ use esp_hal::{
|
|||||||
Rtc,
|
Rtc,
|
||||||
SocResetReason,
|
SocResetReason,
|
||||||
},
|
},
|
||||||
Cpu,
|
system::Cpu,
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ use esp_hal::{
|
|||||||
Rtc,
|
Rtc,
|
||||||
SocResetReason,
|
SocResetReason,
|
||||||
},
|
},
|
||||||
Cpu,
|
system::Cpu,
|
||||||
};
|
};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user