diff --git a/esp-hal-procmacros/Cargo.toml b/esp-hal-procmacros/Cargo.toml index 53eab3aa737..4193040a424 100644 --- a/esp-hal-procmacros/Cargo.toml +++ b/esp-hal-procmacros/Cargo.toml @@ -33,7 +33,7 @@ enum-dispatch = [] interrupt = [] ## Provide a `#[ram]` procmacro to place functions in RAM instead of flash. ram = [] -## Indicates the target devices has RTC slow memory available. +## Indicates the target device has RTC slow memory available. rtc_slow = [] #! ### Low-power Core Feature Flags diff --git a/esp-hal-procmacros/src/lib.rs b/esp-hal-procmacros/src/lib.rs index e108fcfb0b3..6bec2d198f1 100644 --- a/esp-hal-procmacros/src/lib.rs +++ b/esp-hal-procmacros/src/lib.rs @@ -16,25 +16,22 @@ //! optimized memory usage and precise handling of hardware interrupts. //! //! Key Components: -//! - [interrupt](attr.interrupt.html) - Attribute macro for marking interrupt -//! handlers. Interrupt handlers are used to handle specific hardware -//! interrupts generated by peripherals.
The macro allows users to -//! specify the interrupt name explicitly or use the function name to match -//! the interrupt. -//! - [main](attr.main.html) - Creates a new `executor`` instance and declares +//! - [`interrupt`](attr.interrupt.html) - Attribute macro for marking +//! interrupt handlers. Interrupt handlers are used to handle specific +//! hardware interrupts generated by peripherals. +//! +//! The macro allows users to specify the interrupt name explicitly or use +//! 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 //! async task. -//! - [ram](attr.ram.html) - Attribute macro for placing statics and functions -//! into specific memory sections, such as SRAM or RTC RAM (slow or fast) -//! with different initialization options. Supported options are: -//! - `rtc_fast` - Use RTC fast RAM -//! - `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 +//! - [`ram`](attr.ram.html) - Attribute macro for placing statics and +//! functions into specific memory sections, such as SRAM or RTC RAM (slow or +//! fast) with different initialization options. See its documentation for +//! details. //! //! ## Examples //! -//! //! #### `main` macro //! //! 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 #![doc = document_features::document_features!()] #![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")] @@ -88,19 +70,64 @@ mod lp_core; struct RamArgs { rtc_fast: bool, rtc_slow: bool, - uninitialized: bool, + persistent: 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. +/// +/// Requires the `ram` feature. +/// +/// # Options +/// +/// - `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`]. /// -/// Options that can be specified are rtc_slow or rtc_fast to use the -/// RTC slow or RTC fast ram instead of the normal SRAM. +/// ### Warnings /// -/// The uninitialized option will skip initialization of the memory -/// (e.g. to persist it across resets or deep sleep mode for the RTC RAM) +/// - 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. /// -/// Not all targets support RTC slow ram. +/// 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")] #[proc_macro_attribute] #[proc_macro_error::proc_macro_error] @@ -120,7 +147,7 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream { let RamArgs { rtc_fast, rtc_slow, - uninitialized, + persistent, zeroed, } = match FromMeta::from_list(&attr_args) { Ok(v) => v, @@ -140,7 +167,7 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream { } 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, true, false, false, false) => Ok(".rtc_fast.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, 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, 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"), _ => 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! { #section #item + #trait_check }; output.into() diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index f3af559724c..fd6d4d960bb 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -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) - dma: add Mem2Mem to support memory to memory transfer (#1738) - Add `uart` wake source (#1727) +- `#[ram(persistent)]` option to replace the unsound `uninitialized` option (#1677) - uart: Make `rx_timeout` optional in Config struct (#1759) - 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) - ROM Functions: Fix address of `ets_update_cpu_frequency_rom` (#1722) - 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 ### Changed @@ -45,6 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed - uart: Removed `configure_pins` methods (#1592) - 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 diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 0187dac56c5..8c70ad3b690 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -16,6 +16,7 @@ rustdoc-args = ["--cfg", "docsrs"] [dependencies] bitflags = "2.5.0" +bytemuck = "1.0.0" bitfield = "0.15.0" cfg-if = "1.0.0" critical-section = "1.1.2" @@ -77,7 +78,7 @@ serde = { version = "1.0.203", features = ["derive"] } [features] 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"] bluetooth = [] @@ -105,11 +106,11 @@ esp32 = ["dep:esp32", "xtensa", "xtensa-lx/spin", "xtensa-lx-rt/esp32"] # Target the ESP32-C2. esp32c2 = ["dep:esp32c2", "riscv", "portable-atomic/unsafe-assume-single-core"] # 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. -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. -esp32h2 = ["dep:esp32h2", "riscv", "rv-zero-rtc-bss"] +esp32h2 = ["dep:esp32h2", "riscv", "esp-riscv-rt/rtc-ram"] # Target the ESP32-S2. esp32s2 = ["dep:esp32s2", "xtensa", "portable-atomic/critical-section", "procmacros/has-ulp-core", "xtensa-lx-rt/esp32s2", "usb-otg"] # 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 ## (ESP32-C6 and ESPS32-H2 only!). 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 ## Enable support for asynchronous operation, with interfaces provided by diff --git a/esp-hal/ld/sections/rtc_fast.x b/esp-hal/ld/sections/rtc_fast.x index 3bf5e1dd2f7..ea2ffb76d64 100644 --- a/esp-hal/ld/sections/rtc_fast.x +++ b/esp-hal/ld/sections/rtc_fast.x @@ -25,10 +25,12 @@ SECTIONS { . = ALIGN(4); } > RTC_FAST_RWDATA - .rtc_fast.noinit (NOLOAD) : + .rtc_fast.persistent (NOLOAD) : { . = 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); } > RTC_FAST_RWDATA } \ No newline at end of file diff --git a/esp-hal/ld/sections/rtc_slow.x b/esp-hal/ld/sections/rtc_slow.x index 035e95ca9a5..fe864dfc8bd 100644 --- a/esp-hal/ld/sections/rtc_slow.x +++ b/esp-hal/ld/sections/rtc_slow.x @@ -25,10 +25,12 @@ SECTIONS { . = ALIGN(4); } > rtc_slow_seg - .rtc_slow.noinit (NOLOAD) : + .rtc_slow.persistent (NOLOAD) : { . = 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); } > rtc_slow_seg } \ No newline at end of file diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index f853f6741d2..a3fbed98576 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -288,6 +288,39 @@ pub(crate) mod private { 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 Persistable for [T; N] {} + +#[doc(hidden)] +pub mod __macro_implementation { + //! Unstable private implementation details of esp-hal-procmacros. + + pub const fn assert_is_zeroable() {} + pub const fn assert_is_persistable() {} +} + /// Available CPU cores /// /// The actual number of available cores depends on the target. diff --git a/esp-hal/src/soc/esp32/mod.rs b/esp-hal/src/soc/esp32/mod.rs index 4d10c0be1be..bff898dfd5a 100644 --- a/esp-hal/src/soc/esp32/mod.rs +++ b/esp-hal/src/soc/esp32/mod.rs @@ -8,7 +8,10 @@ use core::ptr::addr_of_mut; 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 efuse; @@ -55,9 +58,13 @@ pub unsafe extern "C" fn ESP32Reset() -> ! { extern "C" { static mut _rtc_fast_bss_start: 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_end: u32; + static mut _rtc_slow_persistent_start: u32; + static mut _rtc_slow_persistent_end: 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_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 { let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard); diff --git a/esp-hal/src/soc/esp32s2/mod.rs b/esp-hal/src/soc/esp32s2/mod.rs index 8fbf4a6390d..5a7b61ded07 100644 --- a/esp-hal/src/soc/esp32s2/mod.rs +++ b/esp-hal/src/soc/esp32s2/mod.rs @@ -12,7 +12,10 @@ use core::ptr::addr_of_mut; 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 gpio; @@ -60,9 +63,13 @@ pub unsafe extern "C" fn ESP32Reset() -> ! { extern "C" { static mut _rtc_fast_bss_start: 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_end: u32; + static mut _rtc_slow_persistent_start: u32; + static mut _rtc_slow_persistent_end: 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_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 { let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard); diff --git a/esp-hal/src/soc/esp32s3/mod.rs b/esp-hal/src/soc/esp32s3/mod.rs index 5a76765f722..fdda6395f5b 100644 --- a/esp-hal/src/soc/esp32s3/mod.rs +++ b/esp-hal/src/soc/esp32s3/mod.rs @@ -12,7 +12,10 @@ use core::ptr::addr_of_mut; 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 efuse; @@ -94,9 +97,13 @@ pub unsafe extern "C" fn ESP32Reset() -> ! { extern "C" { static mut _rtc_fast_bss_start: 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_end: u32; + static mut _rtc_slow_persistent_start: u32; + static mut _rtc_slow_persistent_end: 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_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 { let stack_chk_guard = core::ptr::addr_of_mut!(__stack_chk_guard); diff --git a/esp-riscv-rt/CHANGELOG.md b/esp-riscv-rt/CHANGELOG.md index 324b2a2c89d..9383611740d 100644 --- a/esp-riscv-rt/CHANGELOG.md +++ b/esp-riscv-rt/CHANGELOG.md @@ -9,12 +9,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- `rtc-ram` feature used by `esp-hal` to control rtc ram initialization (#1677) + ### Fixed ### Changed ### 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 ### Fixed diff --git a/esp-riscv-rt/Cargo.toml b/esp-riscv-rt/Cargo.toml index ae45b80ca12..9198eb98694 100644 --- a/esp-riscv-rt/Cargo.toml +++ b/esp-riscv-rt/Cargo.toml @@ -20,29 +20,12 @@ riscv-rt-macros = "0.2.1" fix-sp = [] ## Indicate that the device supports `mie` and `mip` instructions. has-mie-mip = [] - -#! ### Memory Initialization Feature Flags -## 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 = [] +## Indicate that the device has RTC RAM. +rtc-ram = [] # This feature is intended for testing; you probably don't want to enable it: ci = [ "fix-sp", "has-mie-mip", - "init-data", - "init-rtc-fast-data", - "init-rtc-fast-text", - "init-rw-text", - "zero-bss", - "zero-rtc-fast-bss", + "rtc-ram", ] diff --git a/esp-riscv-rt/src/lib.rs b/esp-riscv-rt/src/lib.rs index 3ff1f837a06..2283280c96d 100644 --- a/esp-riscv-rt/src/lib.rs +++ b/esp-riscv-rt/src/lib.rs @@ -298,7 +298,6 @@ _abs_start: csrw mie, 0 csrw mip, 0 "#, -#[cfg(feature = "zero-bss")] r#" la a0, _bss_start la a1, _bss_end @@ -310,7 +309,7 @@ _abs_start: blt a0, a1, 1b 2: "#, -#[cfg(feature = "zero-rtc-fast-bss")] +#[cfg(feature = "rtc-ram")] r#" la a0, _rtc_fast_bss_start la a1, _rtc_fast_bss_end @@ -322,59 +321,20 @@ _abs_start: blt a0, a1, 1b 2: "#, -#[cfg(feature = "init-data")] + // Zero .rtc_fast.persistent iff the chip just powered on +#[cfg(feature = "rtc-ram")] r#" - la a0, _data_start - la a1, _data_end + mv a0, zero + 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 - la a2, _sidata - 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-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 + mv a3, x0 1: - lw a3, 0(a2) sw a3, 0(a0) addi a0, a0, 4 - addi a2, a2, 4 blt a0, a1, 1b 2: "#, diff --git a/examples/src/bin/ram.rs b/examples/src/bin/ram.rs index db406ae5a85..7e71ba5972f 100644 --- a/examples/src/bin/ram.rs +++ b/examples/src/bin/ram.rs @@ -4,8 +4,8 @@ //! //! Initialized memory is always re-initialized on startup. //! -//! Uninitialzed memory isn't initialized on startup and can be used to keep -//! data during resets. +//! Persistent memory is not zeroed after resets that preserve RTC ram. See the +//! documentation for `esp-hal-procmacros` for the full list. //! //! Zeroed memory is initialized to zero on startup. //! @@ -31,8 +31,8 @@ use esp_println::println; #[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, persistent)] +static mut SOME_PERSISTENT_DATA: [u8; 2] = [0; 2]; #[ram(rtc_fast, zeroed)] static mut SOME_ZEROED_DATA: [u8; 8] = [0; 8]; @@ -56,27 +56,22 @@ fn main() -> ! { ); unsafe { 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); SOME_INITED_DATA[0] = 0xff; SOME_ZEROED_DATA[0] = 0xff; 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); - if SOME_UNINITED_DATA[0] != 0 { - SOME_UNINITED_DATA[0] = 0; - SOME_UNINITED_DATA[1] = 0; + if SOME_PERSISTENT_DATA[1] == 0xff { + SOME_PERSISTENT_DATA[1] = 0; } - if SOME_UNINITED_DATA[1] == 0xff { - SOME_UNINITED_DATA[1] = 0; - } - - println!("Counter {}", SOME_UNINITED_DATA[1]); - SOME_UNINITED_DATA[1] += 1; + println!("Counter {}", SOME_PERSISTENT_DATA[1]); + SOME_PERSISTENT_DATA[1] += 1; } println!(