Take 2 on #[ram] soundness (#1677)
* Improve `#[ram]` soundness * Allow `Atomic*` in `#[ram(persistent)]` --------- Co-authored-by: Scott Mabin <scott@mabez.dev>
This commit is contained in:
parent
2bef914e7c
commit
a2883ac318
@ -33,7 +33,7 @@ enum-dispatch = []
|
|||||||
interrupt = []
|
interrupt = []
|
||||||
## Provide a `#[ram]` procmacro to place functions in RAM instead of flash.
|
## Provide a `#[ram]` procmacro to place functions in RAM instead of flash.
|
||||||
ram = []
|
ram = []
|
||||||
## Indicates the target devices has RTC slow memory available.
|
## Indicates the target device has RTC slow memory available.
|
||||||
rtc_slow = []
|
rtc_slow = []
|
||||||
|
|
||||||
#! ### Low-power Core Feature Flags
|
#! ### Low-power Core Feature Flags
|
||||||
|
|||||||
@ -16,25 +16,22 @@
|
|||||||
//! optimized memory usage and precise handling of hardware interrupts.
|
//! optimized memory usage and precise handling of hardware interrupts.
|
||||||
//!
|
//!
|
||||||
//! Key Components:
|
//! Key Components:
|
||||||
//! - [interrupt](attr.interrupt.html) - Attribute macro for marking interrupt
|
//! - [`interrupt`](attr.interrupt.html) - Attribute macro for marking
|
||||||
//! handlers. Interrupt handlers are used to handle specific hardware
|
//! interrupt handlers. Interrupt handlers are used to handle specific
|
||||||
//! interrupts generated by peripherals.<br> The macro allows users to
|
//! hardware interrupts generated by peripherals.
|
||||||
//! specify the interrupt name explicitly or use the function name to match
|
//!
|
||||||
//! the interrupt.
|
//! The macro allows users to specify the interrupt name explicitly or use
|
||||||
//! - [main](attr.main.html) - Creates a new `executor`` instance and declares
|
//! the function name to match the interrupt.
|
||||||
|
//! - [`main`](attr.main.html) - Creates a new `executor` instance and declares
|
||||||
//! an application entry point spawning the corresponding function body as an
|
//! an application entry point spawning the corresponding function body as an
|
||||||
//! async task.
|
//! async task.
|
||||||
//! - [ram](attr.ram.html) - Attribute macro for placing statics and functions
|
//! - [`ram`](attr.ram.html) - Attribute macro for placing statics and
|
||||||
//! into specific memory sections, such as SRAM or RTC RAM (slow or fast)
|
//! functions into specific memory sections, such as SRAM or RTC RAM (slow or
|
||||||
//! with different initialization options. Supported options are:
|
//! fast) with different initialization options. See its documentation for
|
||||||
//! - `rtc_fast` - Use RTC fast RAM
|
//! details.
|
||||||
//! - `rtc_slow` - Use RTC slow RAM (not all targets support slow RTC RAM)
|
|
||||||
//! - `uninitialized` - Skip initialization of the memory
|
|
||||||
//! - `zeroed` - Initialize the memory to zero
|
|
||||||
//!
|
//!
|
||||||
//! ## Examples
|
//! ## Examples
|
||||||
//!
|
//!
|
||||||
//!
|
|
||||||
//! #### `main` macro
|
//! #### `main` macro
|
||||||
//!
|
//!
|
||||||
//! Requires the `embassy` feature to be enabled.
|
//! Requires the `embassy` feature to be enabled.
|
||||||
@ -46,21 +43,6 @@
|
|||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! #### `ram` macro
|
|
||||||
//!
|
|
||||||
//! Requires the `ram` feature to be enabled.
|
|
||||||
//!
|
|
||||||
//! ```rust, no_run
|
|
||||||
//! #[ram(rtc_fast)]
|
|
||||||
//! static mut SOME_INITED_DATA: [u8; 2] = [0xaa, 0xbb];
|
|
||||||
//!
|
|
||||||
//! #[ram(rtc_fast, uninitialized)]
|
|
||||||
//! static mut SOME_UNINITED_DATA: [u8; 2] = [0; 2];
|
|
||||||
//!
|
|
||||||
//! #[ram(rtc_fast, zeroed)]
|
|
||||||
//! static mut SOME_ZEROED_DATA: [u8; 8] = [0; 8];
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! ## Feature Flags
|
//! ## Feature Flags
|
||||||
#![doc = document_features::document_features!()]
|
#![doc = document_features::document_features!()]
|
||||||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
|
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
|
||||||
@ -88,19 +70,64 @@ mod lp_core;
|
|||||||
struct RamArgs {
|
struct RamArgs {
|
||||||
rtc_fast: bool,
|
rtc_fast: bool,
|
||||||
rtc_slow: bool,
|
rtc_slow: bool,
|
||||||
uninitialized: bool,
|
persistent: bool,
|
||||||
zeroed: bool,
|
zeroed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This attribute allows placing statics and functions into ram.
|
/// Sets which segment of RAM to use for a function or static and how it should
|
||||||
|
/// be initialized.
|
||||||
///
|
///
|
||||||
/// Options that can be specified are rtc_slow or rtc_fast to use the
|
/// Requires the `ram` feature.
|
||||||
/// RTC slow or RTC fast ram instead of the normal SRAM.
|
|
||||||
///
|
///
|
||||||
/// The uninitialized option will skip initialization of the memory
|
/// # Options
|
||||||
/// (e.g. to persist it across resets or deep sleep mode for the RTC RAM)
|
|
||||||
///
|
///
|
||||||
/// Not all targets support RTC slow ram.
|
/// - `rtc_fast`: Use RTC fast RAM.
|
||||||
|
/// - `rtc_slow`: Use RTC slow RAM. **Note**: not available on all targets
|
||||||
|
/// - `persistent`: Persist the contents of the `static` across resets. See [the
|
||||||
|
/// section below](#persistent) for details.
|
||||||
|
/// - `zeroed`: Initialize the memory of the `static` to zero. The initializer
|
||||||
|
/// expression will be discarded. Types used must implement
|
||||||
|
/// [`bytemuck::Zeroable`].
|
||||||
|
///
|
||||||
|
/// Using both `rtc_fast` and `rtc_slow` or `persistent` and `zeroed` together
|
||||||
|
/// is an error.
|
||||||
|
///
|
||||||
|
/// ## `persistent`
|
||||||
|
///
|
||||||
|
/// Initialize the memory to zero after the initial boot. Thereafter,
|
||||||
|
/// initialization is skipped to allow communication across `software_reset()`,
|
||||||
|
/// deep sleep, watchdog timeouts, etc.
|
||||||
|
///
|
||||||
|
/// Types used must implement [`bytemuck::AnyBitPattern`].
|
||||||
|
///
|
||||||
|
/// ### Warnings
|
||||||
|
///
|
||||||
|
/// - A system-level or lesser reset occurring before the ram has been zeroed
|
||||||
|
/// *could* skip initialization and start the application with the static
|
||||||
|
/// filled with random bytes.
|
||||||
|
/// - There is no way to keep some kinds of resets from happening while updating
|
||||||
|
/// a persistent static—not even a critical section.
|
||||||
|
///
|
||||||
|
/// If these are issues for your application, consider adding a checksum
|
||||||
|
/// alongside the data.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust, no_run
|
||||||
|
/// #[ram(rtc_fast)]
|
||||||
|
/// static mut SOME_INITED_DATA: [u8; 2] = [0xaa, 0xbb];
|
||||||
|
///
|
||||||
|
/// #[ram(rtc_fast, persistent)]
|
||||||
|
/// static mut SOME_PERSISTENT_DATA: [u8; 2] = [0; 2];
|
||||||
|
///
|
||||||
|
/// #[ram(rtc_fast, zeroed)]
|
||||||
|
/// static mut SOME_ZEROED_DATA: [u8; 8] = [0; 8];
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// See the `ram` example in the esp-hal repository for a full usage example.
|
||||||
|
///
|
||||||
|
/// [`bytemuck::AnyBitPattern`]: https://docs.rs/bytemuck/1.9.0/bytemuck/trait.AnyBitPattern.html
|
||||||
|
/// [`bytemuck::Zeroable`]: https://docs.rs/bytemuck/1.9.0/bytemuck/trait.Zeroable.html
|
||||||
#[cfg(feature = "ram")]
|
#[cfg(feature = "ram")]
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
#[proc_macro_error::proc_macro_error]
|
#[proc_macro_error::proc_macro_error]
|
||||||
@ -120,7 +147,7 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
let RamArgs {
|
let RamArgs {
|
||||||
rtc_fast,
|
rtc_fast,
|
||||||
rtc_slow,
|
rtc_slow,
|
||||||
uninitialized,
|
persistent,
|
||||||
zeroed,
|
zeroed,
|
||||||
} = match FromMeta::from_list(&attr_args) {
|
} = match FromMeta::from_list(&attr_args) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
@ -140,7 +167,7 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let is_fn = matches!(item, Item::Fn(_));
|
let is_fn = matches!(item, Item::Fn(_));
|
||||||
let section_name = match (is_fn, rtc_fast, rtc_slow, uninitialized, zeroed) {
|
let section_name = match (is_fn, rtc_fast, rtc_slow, persistent, zeroed) {
|
||||||
(true, false, false, false, false) => Ok(".rwtext"),
|
(true, false, false, false, false) => Ok(".rwtext"),
|
||||||
(true, true, false, false, false) => Ok(".rtc_fast.text"),
|
(true, true, false, false, false) => Ok(".rtc_fast.text"),
|
||||||
(true, false, true, false, false) => Ok(".rtc_slow.text"),
|
(true, false, true, false, false) => Ok(".rtc_slow.text"),
|
||||||
@ -148,11 +175,11 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
(false, false, false, false, false) => Ok(".data"),
|
(false, false, false, false, false) => Ok(".data"),
|
||||||
|
|
||||||
(false, true, false, false, false) => Ok(".rtc_fast.data"),
|
(false, true, false, false, false) => Ok(".rtc_fast.data"),
|
||||||
(false, true, false, true, false) => Ok(".rtc_fast.noinit"),
|
(false, true, false, true, false) => Ok(".rtc_fast.persistent"),
|
||||||
(false, true, false, false, true) => Ok(".rtc_fast.bss"),
|
(false, true, false, false, true) => Ok(".rtc_fast.bss"),
|
||||||
|
|
||||||
(false, false, true, false, false) => Ok(".rtc_slow.data"),
|
(false, false, true, false, false) => Ok(".rtc_slow.data"),
|
||||||
(false, false, true, true, false) => Ok(".rtc_slow.noinit"),
|
(false, false, true, true, false) => Ok(".rtc_slow.persistent"),
|
||||||
(false, false, true, false, true) => Ok(".rtc_slow.bss"),
|
(false, false, true, false, true) => Ok(".rtc_slow.bss"),
|
||||||
|
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
@ -171,9 +198,39 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let trait_check = if zeroed {
|
||||||
|
Some("zeroable")
|
||||||
|
} else if persistent {
|
||||||
|
Some("persistable")
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let trait_check = trait_check.map(|name| {
|
||||||
|
use proc_macro_crate::{crate_name, FoundCrate};
|
||||||
|
|
||||||
|
let hal = proc_macro2::Ident::new(
|
||||||
|
if let Ok(FoundCrate::Name(ref name)) = crate_name("esp-hal") {
|
||||||
|
&name
|
||||||
|
} else {
|
||||||
|
"crate"
|
||||||
|
},
|
||||||
|
Span::call_site().into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let assertion = quote::format_ident!("assert_is_{name}");
|
||||||
|
let Item::Static(ref item) = item else {
|
||||||
|
abort!(item, "Expected a `static`");
|
||||||
|
};
|
||||||
|
let ty = &item.ty;
|
||||||
|
quote::quote! {
|
||||||
|
const _: () = #hal::__macro_implementation::#assertion::<#ty>();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let output = quote::quote! {
|
let output = quote::quote! {
|
||||||
#section
|
#section
|
||||||
#item
|
#item
|
||||||
|
#trait_check
|
||||||
};
|
};
|
||||||
|
|
||||||
output.into()
|
output.into()
|
||||||
|
|||||||
@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Add support for GPIO wake-up source (#1724)
|
- Add support for GPIO wake-up source (#1724)
|
||||||
- dma: add Mem2Mem to support memory to memory transfer (#1738)
|
- dma: add Mem2Mem to support memory to memory transfer (#1738)
|
||||||
- Add `uart` wake source (#1727)
|
- Add `uart` wake source (#1727)
|
||||||
|
- `#[ram(persistent)]` option to replace the unsound `uninitialized` option (#1677)
|
||||||
- uart: Make `rx_timeout` optional in Config struct (#1759)
|
- uart: Make `rx_timeout` optional in Config struct (#1759)
|
||||||
- Add interrupt related functions to `PeriodicTimer`/`OneShotTimer`, added `ErasedTimer` (#1753)
|
- Add interrupt related functions to `PeriodicTimer`/`OneShotTimer`, added `ErasedTimer` (#1753)
|
||||||
|
|
||||||
@ -31,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Fix `sleep_light` for ESP32-C6 (#1720)
|
- Fix `sleep_light` for ESP32-C6 (#1720)
|
||||||
- ROM Functions: Fix address of `ets_update_cpu_frequency_rom` (#1722)
|
- ROM Functions: Fix address of `ets_update_cpu_frequency_rom` (#1722)
|
||||||
- Fix `regi2c_*` functions for `esp32h2` (#1737)
|
- Fix `regi2c_*` functions for `esp32h2` (#1737)
|
||||||
|
- Improved `#[ram(zeroed)]` soundness by adding a `bytemuck::Zeroable` type bound (#1677)
|
||||||
- EESP32-S2 / ESP32-S3: Fix UsbDm and UsbDp for Gpio19 and Gpio20
|
- EESP32-S2 / ESP32-S3: Fix UsbDm and UsbDp for Gpio19 and Gpio20
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
@ -45,6 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Removed
|
### Removed
|
||||||
- uart: Removed `configure_pins` methods (#1592)
|
- uart: Removed `configure_pins` methods (#1592)
|
||||||
- Removed `DmaError::Exhausted` error by improving the implementation of the `pop` function (#1664)
|
- Removed `DmaError::Exhausted` error by improving the implementation of the `pop` function (#1664)
|
||||||
|
- Unsound `#[ram(uninitialized)]` option in favor of the new `persistent` option (#1677)
|
||||||
|
|
||||||
## [0.18.0] - 2024-06-04
|
## [0.18.0] - 2024-06-04
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "2.5.0"
|
bitflags = "2.5.0"
|
||||||
|
bytemuck = "1.0.0"
|
||||||
bitfield = "0.15.0"
|
bitfield = "0.15.0"
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
critical-section = "1.1.2"
|
critical-section = "1.1.2"
|
||||||
@ -77,7 +78,7 @@ serde = { version = "1.0.203", features = ["derive"] }
|
|||||||
[features]
|
[features]
|
||||||
default = ["embedded-hal"]
|
default = ["embedded-hal"]
|
||||||
|
|
||||||
riscv = ["dep:riscv", "critical-section/restore-state-u8", "esp-riscv-rt/zero-bss"]
|
riscv = ["dep:riscv", "critical-section/restore-state-u8"]
|
||||||
xtensa = ["dep:xtensa-lx", "critical-section/restore-state-u32"]
|
xtensa = ["dep:xtensa-lx", "critical-section/restore-state-u32"]
|
||||||
|
|
||||||
bluetooth = []
|
bluetooth = []
|
||||||
@ -105,11 +106,11 @@ esp32 = ["dep:esp32", "xtensa", "xtensa-lx/spin", "xtensa-lx-rt/esp32"]
|
|||||||
# Target the ESP32-C2.
|
# Target the ESP32-C2.
|
||||||
esp32c2 = ["dep:esp32c2", "riscv", "portable-atomic/unsafe-assume-single-core"]
|
esp32c2 = ["dep:esp32c2", "riscv", "portable-atomic/unsafe-assume-single-core"]
|
||||||
# Target the ESP32-C3.
|
# Target the ESP32-C3.
|
||||||
esp32c3 = ["dep:esp32c3", "riscv", "portable-atomic/unsafe-assume-single-core", "rv-zero-rtc-bss"]
|
esp32c3 = ["dep:esp32c3", "riscv", "portable-atomic/unsafe-assume-single-core", "esp-riscv-rt/rtc-ram"]
|
||||||
# Target the ESP32-C6.
|
# Target the ESP32-C6.
|
||||||
esp32c6 = ["dep:esp32c6", "riscv", "procmacros/has-lp-core", "rv-zero-rtc-bss"]
|
esp32c6 = ["dep:esp32c6", "riscv", "procmacros/has-lp-core", "esp-riscv-rt/rtc-ram"]
|
||||||
# Target the ESP32-H2.
|
# Target the ESP32-H2.
|
||||||
esp32h2 = ["dep:esp32h2", "riscv", "rv-zero-rtc-bss"]
|
esp32h2 = ["dep:esp32h2", "riscv", "esp-riscv-rt/rtc-ram"]
|
||||||
# Target the ESP32-S2.
|
# Target the ESP32-S2.
|
||||||
esp32s2 = ["dep:esp32s2", "xtensa", "portable-atomic/critical-section", "procmacros/has-ulp-core", "xtensa-lx-rt/esp32s2", "usb-otg"]
|
esp32s2 = ["dep:esp32s2", "xtensa", "portable-atomic/critical-section", "procmacros/has-ulp-core", "xtensa-lx-rt/esp32s2", "usb-otg"]
|
||||||
# Target the ESP32-S3.
|
# Target the ESP32-S3.
|
||||||
@ -119,12 +120,6 @@ esp32s3 = ["dep:esp32s3", "xtensa", "procmacros/has-ulp-core", "xtensa-lx/spin",
|
|||||||
## Move the stack to start of RAM to get zero-cost stack overflow protection
|
## Move the stack to start of RAM to get zero-cost stack overflow protection
|
||||||
## (ESP32-C6 and ESPS32-H2 only!).
|
## (ESP32-C6 and ESPS32-H2 only!).
|
||||||
flip-link = ["esp-riscv-rt/fix-sp"]
|
flip-link = ["esp-riscv-rt/fix-sp"]
|
||||||
## Initialize the `.data` section of memory.
|
|
||||||
rv-init-data = ["esp-riscv-rt/init-data", "esp-riscv-rt/init-rw-text"]
|
|
||||||
## Zero the `.bss` section of low-power memory.
|
|
||||||
rv-zero-rtc-bss = ["esp-riscv-rt/zero-rtc-fast-bss"]
|
|
||||||
## Initialize the `.data` section of low-power memory.
|
|
||||||
rv-init-rtc-data = ["esp-riscv-rt/init-rtc-fast-data", "esp-riscv-rt/init-rtc-fast-text"]
|
|
||||||
|
|
||||||
#! ### Trait Implementation Feature Flags
|
#! ### Trait Implementation Feature Flags
|
||||||
## Enable support for asynchronous operation, with interfaces provided by
|
## Enable support for asynchronous operation, with interfaces provided by
|
||||||
|
|||||||
@ -25,10 +25,12 @@ SECTIONS {
|
|||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} > RTC_FAST_RWDATA
|
} > RTC_FAST_RWDATA
|
||||||
|
|
||||||
.rtc_fast.noinit (NOLOAD) :
|
.rtc_fast.persistent (NOLOAD) :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
*(.rtc_fast.noinit .rtc_fast.noinit.*)
|
_rtc_fast_persistent_start = ABSOLUTE(.);
|
||||||
|
*(.rtc_fast.persistent .rtc_fast.persistent.*)
|
||||||
|
_rtc_fast_persistent_end = ABSOLUTE(.);
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} > RTC_FAST_RWDATA
|
} > RTC_FAST_RWDATA
|
||||||
}
|
}
|
||||||
@ -25,10 +25,12 @@ SECTIONS {
|
|||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} > rtc_slow_seg
|
} > rtc_slow_seg
|
||||||
|
|
||||||
.rtc_slow.noinit (NOLOAD) :
|
.rtc_slow.persistent (NOLOAD) :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
*(.rtc_slow.noinit .rtc_slow.noinit.*)
|
_rtc_slow_persistent_start = ABSOLUTE(.);
|
||||||
|
*(.rtc_slow.persistent .rtc_slow.persistent.*)
|
||||||
|
_rtc_slow_persistent_end = ABSOLUTE(.);
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} > rtc_slow_seg
|
} > rtc_slow_seg
|
||||||
}
|
}
|
||||||
@ -288,6 +288,39 @@ pub(crate) mod private {
|
|||||||
pub struct Internal;
|
pub struct Internal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Marker trait for types that can be safely used in `#[ram(persistent)]`.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// - The type must be inhabited
|
||||||
|
/// - The type must be valid for any bit pattern of its backing memory in case a
|
||||||
|
/// reset occurs during a write or a reset interrupts the zero initialization
|
||||||
|
/// on first boot.
|
||||||
|
/// - Structs must contain only `Persistable` fields and padding
|
||||||
|
pub unsafe trait Persistable: Sized {}
|
||||||
|
|
||||||
|
macro_rules! impl_persistable {
|
||||||
|
($($t:ty),+) => {$(
|
||||||
|
unsafe impl Persistable for $t {}
|
||||||
|
)+};
|
||||||
|
(atomic $($t:ident),+) => {$(
|
||||||
|
unsafe impl Persistable for portable_atomic::$t {}
|
||||||
|
)+};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_persistable!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize, f32, f64);
|
||||||
|
impl_persistable!(atomic AtomicU8, AtomicI8, AtomicU16, AtomicI16, AtomicU32, AtomicI32, AtomicUsize, AtomicIsize);
|
||||||
|
|
||||||
|
unsafe impl<T: Persistable, const N: usize> Persistable for [T; N] {}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod __macro_implementation {
|
||||||
|
//! Unstable private implementation details of esp-hal-procmacros.
|
||||||
|
|
||||||
|
pub const fn assert_is_zeroable<T: bytemuck::Zeroable>() {}
|
||||||
|
pub const fn assert_is_persistable<T: super::Persistable>() {}
|
||||||
|
}
|
||||||
|
|
||||||
/// Available CPU cores
|
/// Available CPU cores
|
||||||
///
|
///
|
||||||
/// The actual number of available cores depends on the target.
|
/// The actual number of available cores depends on the target.
|
||||||
|
|||||||
@ -8,7 +8,10 @@
|
|||||||
use core::ptr::addr_of_mut;
|
use core::ptr::addr_of_mut;
|
||||||
|
|
||||||
use self::peripherals::{LPWR, TIMG0, TIMG1};
|
use self::peripherals::{LPWR, TIMG0, TIMG1};
|
||||||
use crate::{rtc_cntl::Rtc, timer::timg::Wdt};
|
use crate::{
|
||||||
|
rtc_cntl::{Rtc, SocResetReason},
|
||||||
|
timer::timg::Wdt,
|
||||||
|
};
|
||||||
|
|
||||||
pub mod cpu_control;
|
pub mod cpu_control;
|
||||||
pub mod efuse;
|
pub mod efuse;
|
||||||
@ -55,9 +58,13 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
static mut _rtc_fast_bss_start: u32;
|
static mut _rtc_fast_bss_start: u32;
|
||||||
static mut _rtc_fast_bss_end: u32;
|
static mut _rtc_fast_bss_end: u32;
|
||||||
|
static mut _rtc_fast_persistent_start: u32;
|
||||||
|
static mut _rtc_fast_persistent_end: u32;
|
||||||
|
|
||||||
static mut _rtc_slow_bss_start: u32;
|
static mut _rtc_slow_bss_start: u32;
|
||||||
static mut _rtc_slow_bss_end: u32;
|
static mut _rtc_slow_bss_end: u32;
|
||||||
|
static mut _rtc_slow_persistent_start: u32;
|
||||||
|
static mut _rtc_slow_persistent_end: u32;
|
||||||
|
|
||||||
static mut _stack_start_cpu0: u32;
|
static mut _stack_start_cpu0: u32;
|
||||||
|
|
||||||
@ -79,6 +86,19 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
|
|||||||
addr_of_mut!(_rtc_slow_bss_start),
|
addr_of_mut!(_rtc_slow_bss_start),
|
||||||
addr_of_mut!(_rtc_slow_bss_end),
|
addr_of_mut!(_rtc_slow_bss_end),
|
||||||
);
|
);
|
||||||
|
if matches!(
|
||||||
|
crate::reset::get_reset_reason(),
|
||||||
|
None | Some(SocResetReason::ChipPowerOn)
|
||||||
|
) {
|
||||||
|
xtensa_lx_rt::zero_bss(
|
||||||
|
addr_of_mut!(_rtc_fast_persistent_start),
|
||||||
|
addr_of_mut!(_rtc_fast_persistent_end),
|
||||||
|
);
|
||||||
|
xtensa_lx_rt::zero_bss(
|
||||||
|
addr_of_mut!(_rtc_slow_persistent_start),
|
||||||
|
addr_of_mut!(_rtc_slow_persistent_end),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard);
|
let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard);
|
||||||
|
|||||||
@ -12,7 +12,10 @@
|
|||||||
use core::ptr::addr_of_mut;
|
use core::ptr::addr_of_mut;
|
||||||
|
|
||||||
use self::peripherals::{LPWR, TIMG0, TIMG1};
|
use self::peripherals::{LPWR, TIMG0, TIMG1};
|
||||||
use crate::{rtc_cntl::Rtc, timer::timg::Wdt};
|
use crate::{
|
||||||
|
rtc_cntl::{Rtc, SocResetReason},
|
||||||
|
timer::timg::Wdt,
|
||||||
|
};
|
||||||
|
|
||||||
pub mod efuse;
|
pub mod efuse;
|
||||||
pub mod gpio;
|
pub mod gpio;
|
||||||
@ -60,9 +63,13 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
static mut _rtc_fast_bss_start: u32;
|
static mut _rtc_fast_bss_start: u32;
|
||||||
static mut _rtc_fast_bss_end: u32;
|
static mut _rtc_fast_bss_end: u32;
|
||||||
|
static mut _rtc_fast_persistent_start: u32;
|
||||||
|
static mut _rtc_fast_persistent_end: u32;
|
||||||
|
|
||||||
static mut _rtc_slow_bss_start: u32;
|
static mut _rtc_slow_bss_start: u32;
|
||||||
static mut _rtc_slow_bss_end: u32;
|
static mut _rtc_slow_bss_end: u32;
|
||||||
|
static mut _rtc_slow_persistent_start: u32;
|
||||||
|
static mut _rtc_slow_persistent_end: u32;
|
||||||
|
|
||||||
static mut _stack_start_cpu0: u32;
|
static mut _stack_start_cpu0: u32;
|
||||||
|
|
||||||
@ -84,6 +91,19 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
|
|||||||
addr_of_mut!(_rtc_slow_bss_start),
|
addr_of_mut!(_rtc_slow_bss_start),
|
||||||
addr_of_mut!(_rtc_slow_bss_end),
|
addr_of_mut!(_rtc_slow_bss_end),
|
||||||
);
|
);
|
||||||
|
if matches!(
|
||||||
|
crate::reset::get_reset_reason(),
|
||||||
|
None | Some(SocResetReason::ChipPowerOn)
|
||||||
|
) {
|
||||||
|
xtensa_lx_rt::zero_bss(
|
||||||
|
addr_of_mut!(_rtc_fast_persistent_start),
|
||||||
|
addr_of_mut!(_rtc_fast_persistent_end),
|
||||||
|
);
|
||||||
|
xtensa_lx_rt::zero_bss(
|
||||||
|
addr_of_mut!(_rtc_slow_persistent_start),
|
||||||
|
addr_of_mut!(_rtc_slow_persistent_end),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard);
|
let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard);
|
||||||
|
|||||||
@ -12,7 +12,10 @@
|
|||||||
use core::ptr::addr_of_mut;
|
use core::ptr::addr_of_mut;
|
||||||
|
|
||||||
use self::peripherals::{LPWR, TIMG0, TIMG1};
|
use self::peripherals::{LPWR, TIMG0, TIMG1};
|
||||||
use crate::{rtc_cntl::Rtc, timer::timg::Wdt};
|
use crate::{
|
||||||
|
rtc_cntl::{Rtc, SocResetReason},
|
||||||
|
timer::timg::Wdt,
|
||||||
|
};
|
||||||
|
|
||||||
pub mod cpu_control;
|
pub mod cpu_control;
|
||||||
pub mod efuse;
|
pub mod efuse;
|
||||||
@ -94,9 +97,13 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
static mut _rtc_fast_bss_start: u32;
|
static mut _rtc_fast_bss_start: u32;
|
||||||
static mut _rtc_fast_bss_end: u32;
|
static mut _rtc_fast_bss_end: u32;
|
||||||
|
static mut _rtc_fast_persistent_start: u32;
|
||||||
|
static mut _rtc_fast_persistent_end: u32;
|
||||||
|
|
||||||
static mut _rtc_slow_bss_start: u32;
|
static mut _rtc_slow_bss_start: u32;
|
||||||
static mut _rtc_slow_bss_end: u32;
|
static mut _rtc_slow_bss_end: u32;
|
||||||
|
static mut _rtc_slow_persistent_start: u32;
|
||||||
|
static mut _rtc_slow_persistent_end: u32;
|
||||||
|
|
||||||
static mut _stack_start_cpu0: u32;
|
static mut _stack_start_cpu0: u32;
|
||||||
|
|
||||||
@ -118,6 +125,19 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
|
|||||||
addr_of_mut!(_rtc_slow_bss_start),
|
addr_of_mut!(_rtc_slow_bss_start),
|
||||||
addr_of_mut!(_rtc_slow_bss_end),
|
addr_of_mut!(_rtc_slow_bss_end),
|
||||||
);
|
);
|
||||||
|
if matches!(
|
||||||
|
crate::reset::get_reset_reason(),
|
||||||
|
None | Some(SocResetReason::ChipPowerOn)
|
||||||
|
) {
|
||||||
|
xtensa_lx_rt::zero_bss(
|
||||||
|
addr_of_mut!(_rtc_fast_persistent_start),
|
||||||
|
addr_of_mut!(_rtc_fast_persistent_end),
|
||||||
|
);
|
||||||
|
xtensa_lx_rt::zero_bss(
|
||||||
|
addr_of_mut!(_rtc_slow_persistent_start),
|
||||||
|
addr_of_mut!(_rtc_slow_persistent_end),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard);
|
let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard);
|
||||||
|
|||||||
@ -9,12 +9,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- `rtc-ram` feature used by `esp-hal` to control rtc ram initialization (#1677)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
- All existing features controlling ram initialization. Most (`init-data`, `init-rw-text`,
|
||||||
|
`init-rtc-fast-data`, and `init-rtc-fast-text`) were only used for the (already removed) direct
|
||||||
|
boot support. `zero-bss` is now enabled unconditionally. `zero-rtc-fast-bss` was merged into the
|
||||||
|
new `rtc-ram` feature. (#1677)
|
||||||
|
|
||||||
## 0.8.0 - 2024-04-18
|
## 0.8.0 - 2024-04-18
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@ -20,29 +20,12 @@ riscv-rt-macros = "0.2.1"
|
|||||||
fix-sp = []
|
fix-sp = []
|
||||||
## Indicate that the device supports `mie` and `mip` instructions.
|
## Indicate that the device supports `mie` and `mip` instructions.
|
||||||
has-mie-mip = []
|
has-mie-mip = []
|
||||||
|
## Indicate that the device has RTC RAM.
|
||||||
#! ### Memory Initialization Feature Flags
|
rtc-ram = []
|
||||||
## Initialize the `data` section.
|
|
||||||
init-data = []
|
|
||||||
## Initialize the `.rtc_fast.data` section.
|
|
||||||
init-rtc-fast-data = []
|
|
||||||
## Initialize the `.rtc_fast.text` section.
|
|
||||||
init-rtc-fast-text = []
|
|
||||||
## Initialize the `.rwtext` section.
|
|
||||||
init-rw-text = []
|
|
||||||
## Zero the `.bss` section.
|
|
||||||
zero-bss = []
|
|
||||||
## Zero the `.rtc_fast.bss` section.
|
|
||||||
zero-rtc-fast-bss = []
|
|
||||||
|
|
||||||
# This feature is intended for testing; you probably don't want to enable it:
|
# This feature is intended for testing; you probably don't want to enable it:
|
||||||
ci = [
|
ci = [
|
||||||
"fix-sp",
|
"fix-sp",
|
||||||
"has-mie-mip",
|
"has-mie-mip",
|
||||||
"init-data",
|
"rtc-ram",
|
||||||
"init-rtc-fast-data",
|
|
||||||
"init-rtc-fast-text",
|
|
||||||
"init-rw-text",
|
|
||||||
"zero-bss",
|
|
||||||
"zero-rtc-fast-bss",
|
|
||||||
]
|
]
|
||||||
|
|||||||
@ -298,7 +298,6 @@ _abs_start:
|
|||||||
csrw mie, 0
|
csrw mie, 0
|
||||||
csrw mip, 0
|
csrw mip, 0
|
||||||
"#,
|
"#,
|
||||||
#[cfg(feature = "zero-bss")]
|
|
||||||
r#"
|
r#"
|
||||||
la a0, _bss_start
|
la a0, _bss_start
|
||||||
la a1, _bss_end
|
la a1, _bss_end
|
||||||
@ -310,7 +309,7 @@ _abs_start:
|
|||||||
blt a0, a1, 1b
|
blt a0, a1, 1b
|
||||||
2:
|
2:
|
||||||
"#,
|
"#,
|
||||||
#[cfg(feature = "zero-rtc-fast-bss")]
|
#[cfg(feature = "rtc-ram")]
|
||||||
r#"
|
r#"
|
||||||
la a0, _rtc_fast_bss_start
|
la a0, _rtc_fast_bss_start
|
||||||
la a1, _rtc_fast_bss_end
|
la a1, _rtc_fast_bss_end
|
||||||
@ -322,59 +321,20 @@ _abs_start:
|
|||||||
blt a0, a1, 1b
|
blt a0, a1, 1b
|
||||||
2:
|
2:
|
||||||
"#,
|
"#,
|
||||||
#[cfg(feature = "init-data")]
|
// Zero .rtc_fast.persistent iff the chip just powered on
|
||||||
|
#[cfg(feature = "rtc-ram")]
|
||||||
r#"
|
r#"
|
||||||
la a0, _data_start
|
mv a0, zero
|
||||||
la a1, _data_end
|
call rtc_get_reset_reason
|
||||||
|
addi a1, zero, 1
|
||||||
|
bne a0, a1, 2f
|
||||||
|
la a0, _rtc_fast_persistent_start
|
||||||
|
la a1, _rtc_fast_persistent_end
|
||||||
bge a0, a1, 2f
|
bge a0, a1, 2f
|
||||||
la a2, _sidata
|
mv a3, x0
|
||||||
1:
|
1:
|
||||||
lw a3, 0(a2)
|
|
||||||
sw a3, 0(a0)
|
sw a3, 0(a0)
|
||||||
addi a0, a0, 4
|
addi a0, a0, 4
|
||||||
addi a2, a2, 4
|
|
||||||
blt a0, a1, 1b
|
|
||||||
2:
|
|
||||||
"#,
|
|
||||||
#[cfg(feature = "init-rw-text")]
|
|
||||||
r#"
|
|
||||||
la a0, _srwtext
|
|
||||||
la a1, _erwtext
|
|
||||||
bge a0, a1, 2f
|
|
||||||
la a2, _irwtext
|
|
||||||
1:
|
|
||||||
lw a3, 0(a2)
|
|
||||||
sw a3, 0(a0)
|
|
||||||
addi a0, a0, 4
|
|
||||||
addi a2, a2, 4
|
|
||||||
blt a0, a1, 1b
|
|
||||||
2:
|
|
||||||
"#,
|
|
||||||
#[cfg(feature = "init-rtc-fast-data")]
|
|
||||||
r#"
|
|
||||||
la a0, _rtc_fast_data_start
|
|
||||||
la a1, _rtc_fast_data_end
|
|
||||||
bge a0, a1, 2f
|
|
||||||
la a2, _irtc_fast_data
|
|
||||||
1:
|
|
||||||
lw a3, 0(a2)
|
|
||||||
sw a3, 0(a0)
|
|
||||||
addi a0, a0, 4
|
|
||||||
addi a2, a2, 4
|
|
||||||
blt a0, a1, 1b
|
|
||||||
2:
|
|
||||||
"#,
|
|
||||||
#[cfg(feature = "init-rtc-fast-text")]
|
|
||||||
r#"
|
|
||||||
la a0, _srtc_fast_text
|
|
||||||
la a1, _ertc_fast_text
|
|
||||||
bge a0, a1, 2f
|
|
||||||
la a2, _irtc_fast_text
|
|
||||||
1:
|
|
||||||
lw a3, 0(a2)
|
|
||||||
sw a3, 0(a0)
|
|
||||||
addi a0, a0, 4
|
|
||||||
addi a2, a2, 4
|
|
||||||
blt a0, a1, 1b
|
blt a0, a1, 1b
|
||||||
2:
|
2:
|
||||||
"#,
|
"#,
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
//!
|
//!
|
||||||
//! Initialized memory is always re-initialized on startup.
|
//! Initialized memory is always re-initialized on startup.
|
||||||
//!
|
//!
|
||||||
//! Uninitialzed memory isn't initialized on startup and can be used to keep
|
//! Persistent memory is not zeroed after resets that preserve RTC ram. See the
|
||||||
//! data during resets.
|
//! documentation for `esp-hal-procmacros` for the full list.
|
||||||
//!
|
//!
|
||||||
//! Zeroed memory is initialized to zero on startup.
|
//! Zeroed memory is initialized to zero on startup.
|
||||||
//!
|
//!
|
||||||
@ -31,8 +31,8 @@ use esp_println::println;
|
|||||||
#[ram(rtc_fast)]
|
#[ram(rtc_fast)]
|
||||||
static mut SOME_INITED_DATA: [u8; 2] = [0xaa, 0xbb];
|
static mut SOME_INITED_DATA: [u8; 2] = [0xaa, 0xbb];
|
||||||
|
|
||||||
#[ram(rtc_fast, uninitialized)]
|
#[ram(rtc_fast, persistent)]
|
||||||
static mut SOME_UNINITED_DATA: [u8; 2] = [0; 2];
|
static mut SOME_PERSISTENT_DATA: [u8; 2] = [0; 2];
|
||||||
|
|
||||||
#[ram(rtc_fast, zeroed)]
|
#[ram(rtc_fast, zeroed)]
|
||||||
static mut SOME_ZEROED_DATA: [u8; 8] = [0; 8];
|
static mut SOME_ZEROED_DATA: [u8; 8] = [0; 8];
|
||||||
@ -56,27 +56,22 @@ fn main() -> ! {
|
|||||||
);
|
);
|
||||||
unsafe {
|
unsafe {
|
||||||
println!("SOME_INITED_DATA {:x?}", SOME_INITED_DATA);
|
println!("SOME_INITED_DATA {:x?}", SOME_INITED_DATA);
|
||||||
println!("SOME_UNINITED_DATA {:x?}", SOME_UNINITED_DATA);
|
println!("SOME_PERSISTENT_DATA {:x?}", SOME_PERSISTENT_DATA);
|
||||||
println!("SOME_ZEROED_DATA {:x?}", SOME_ZEROED_DATA);
|
println!("SOME_ZEROED_DATA {:x?}", SOME_ZEROED_DATA);
|
||||||
|
|
||||||
SOME_INITED_DATA[0] = 0xff;
|
SOME_INITED_DATA[0] = 0xff;
|
||||||
SOME_ZEROED_DATA[0] = 0xff;
|
SOME_ZEROED_DATA[0] = 0xff;
|
||||||
|
|
||||||
println!("SOME_INITED_DATA {:x?}", SOME_INITED_DATA);
|
println!("SOME_INITED_DATA {:x?}", SOME_INITED_DATA);
|
||||||
println!("SOME_UNINITED_DATA {:x?}", SOME_UNINITED_DATA);
|
println!("SOME_PERSISTENT_DATA {:x?}", SOME_PERSISTENT_DATA);
|
||||||
println!("SOME_ZEROED_DATA {:x?}", SOME_ZEROED_DATA);
|
println!("SOME_ZEROED_DATA {:x?}", SOME_ZEROED_DATA);
|
||||||
|
|
||||||
if SOME_UNINITED_DATA[0] != 0 {
|
if SOME_PERSISTENT_DATA[1] == 0xff {
|
||||||
SOME_UNINITED_DATA[0] = 0;
|
SOME_PERSISTENT_DATA[1] = 0;
|
||||||
SOME_UNINITED_DATA[1] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if SOME_UNINITED_DATA[1] == 0xff {
|
println!("Counter {}", SOME_PERSISTENT_DATA[1]);
|
||||||
SOME_UNINITED_DATA[1] = 0;
|
SOME_PERSISTENT_DATA[1] += 1;
|
||||||
}
|
|
||||||
|
|
||||||
println!("Counter {}", SOME_UNINITED_DATA[1]);
|
|
||||||
SOME_UNINITED_DATA[1] += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user