mirror of
https://github.com/esp-rs/esp-hal.git
synced 2026-05-01 23:41:00 +00:00
Make a singleton form FlashStorage constructor, removed Default (#4132)
* Make a singleton form FlashStorage constructor, removed Default * changelog * Simplify, don't need the Singleton * changelog * reviews and build errors * fix dead links * fmt
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
//! ## Examples
|
||||
//! Visit the [ECC] test for an example of using the ECC Accelerator.
|
||||
//!
|
||||
//! [ECC]: https://github.com/esp-rs/esp-hal/blob/main/hil-test/tests/ecc.rs
|
||||
//! [ECC]: https://github.com/esp-rs/esp-hal/blob/main/hil-test/src/bin/ecc.rs
|
||||
|
||||
use core::marker::PhantomData;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//! ### Modular Exponentiation, Modular Multiplication, and Multiplication
|
||||
//! Visit the [RSA test suite] for an example of using the peripheral.
|
||||
//!
|
||||
//! [RSA test suite]: https://github.com/esp-rs/esp-hal/blob/main/hil-test/tests/rsa.rs
|
||||
//! [RSA test suite]: https://github.com/esp-rs/esp-hal/blob/main/hil-test/src/bin/rsa.rs
|
||||
|
||||
use core::{marker::PhantomData, ptr::NonNull, task::Poll};
|
||||
|
||||
|
||||
@@ -9,16 +9,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Added
|
||||
|
||||
- `defmt` feature and `FlashStorage`, `FlashStorageError` now implements `Defmt` (#4127)
|
||||
- `defmt` feature and `FlashStorage`, `FlashStorageError` now implements `Defmt` (#4127)
|
||||
- `Drop` impl for `FlashStorage` (#4132)
|
||||
|
||||
### Changed
|
||||
|
||||
- `FlashStorage::new()` now panics when it's already being in use (#4132)
|
||||
|
||||
### Fixed
|
||||
|
||||
|
||||
### Removed
|
||||
|
||||
- `Default` impl for `FlashStorage` (#4132)
|
||||
|
||||
## [v0.8.0] - 2025-09-10
|
||||
|
||||
### Added
|
||||
|
||||
@@ -21,6 +21,7 @@ bench = false
|
||||
embedded-storage = "0.3.1"
|
||||
procmacros = { version = "0.19.0", package = "esp-hal-procmacros", path = "../esp-hal-procmacros" }
|
||||
cfg-if = "1.0.0"
|
||||
portable-atomic = { version = "1.11.0", default-features = false }
|
||||
|
||||
# Optional dependencies
|
||||
esp-sync = { version = "0.0.0", path = "../esp-sync", optional = true }
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
use core::mem::MaybeUninit;
|
||||
use core::{
|
||||
mem::MaybeUninit,
|
||||
sync::atomic::Ordering::{Acquire, Release},
|
||||
};
|
||||
|
||||
use portable_atomic::AtomicBool;
|
||||
|
||||
use crate::chip_specific;
|
||||
#[cfg(multi_core)]
|
||||
use crate::multi_core::MultiCoreStrategy;
|
||||
|
||||
static IS_TAKEN: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[non_exhaustive]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
@@ -63,21 +70,30 @@ impl FlashStorage {
|
||||
pub const SECTOR_SIZE: u32 = 4096;
|
||||
|
||||
/// Create a new flash storage instance.
|
||||
pub fn new() -> FlashStorage {
|
||||
let mut storage = FlashStorage {
|
||||
capacity: 0,
|
||||
unlocked: false,
|
||||
#[cfg(multi_core)]
|
||||
multi_core_strategy: MultiCoreStrategy::Error,
|
||||
};
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if called more than once.
|
||||
pub fn new() -> Self {
|
||||
if IS_TAKEN.fetch_or(true, Acquire) {
|
||||
panic!("FlashStorage::new() called more than once!");
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "esp32", feature = "esp32s2")))]
|
||||
const ADDR: u32 = 0x0000;
|
||||
#[cfg(any(feature = "esp32", feature = "esp32s2"))]
|
||||
const ADDR: u32 = 0x1000;
|
||||
|
||||
let mut storage = Self {
|
||||
capacity: 0,
|
||||
unlocked: false,
|
||||
#[cfg(multi_core)]
|
||||
multi_core_strategy: MultiCoreStrategy::Error,
|
||||
};
|
||||
|
||||
let mut buffer = crate::buffer::FlashWordBuffer::uninit();
|
||||
storage.internal_read(ADDR, buffer.as_bytes_mut()).unwrap();
|
||||
|
||||
let buffer = unsafe { buffer.assume_init_bytes() };
|
||||
let mb = match buffer[3] & 0xf0 {
|
||||
0x00 => 1,
|
||||
@@ -89,6 +105,7 @@ impl FlashStorage {
|
||||
_ => 0,
|
||||
};
|
||||
storage.capacity = mb * 1024 * 1024;
|
||||
|
||||
storage
|
||||
}
|
||||
|
||||
@@ -171,3 +188,39 @@ impl FlashStorage {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FlashStorage {
|
||||
fn drop(&mut self) {
|
||||
IS_TAKEN.store(false, Release);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::FlashStorage;
|
||||
#[test]
|
||||
fn test_singleton_behavior() {
|
||||
// First call should succeed
|
||||
let flash1 = FlashStorage::new();
|
||||
assert_eq!(flash1.capacity > 0, true); // or check some field
|
||||
|
||||
// Second call should panic
|
||||
let result = std::panic::catch_unwind(|| {
|
||||
FlashStorage::new();
|
||||
});
|
||||
assert!(result.is_err(), "expected panic on second init");
|
||||
|
||||
// Third call should also panic
|
||||
let result = std::panic::catch_unwind(|| {
|
||||
FlashStorage::new();
|
||||
});
|
||||
assert!(result.is_err(), "expected panic on third init");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "FlashStorage::new() called more than once!")]
|
||||
fn test_expect_panics() {
|
||||
let _flash1 = FlashStorage::new(); // first call is fine
|
||||
let _flash2 = FlashStorage::new(); // this panics
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,6 +319,7 @@ mod tests {
|
||||
#[cfg(feature = "bytewise-read")]
|
||||
fn bytewise_read_aligned_buffer() {
|
||||
let mut flash = FlashStorage::new();
|
||||
|
||||
flash.capacity = 4 * 4096;
|
||||
let src = TestBuffer::seq();
|
||||
let mut data = TestBuffer::default();
|
||||
@@ -339,6 +340,7 @@ mod tests {
|
||||
#[cfg(feature = "bytewise-read")]
|
||||
fn bytewise_read_not_aligned_buffer() {
|
||||
let mut flash = FlashStorage::new();
|
||||
|
||||
flash.capacity = 4 * 4096;
|
||||
let src = TestBuffer::seq();
|
||||
let mut data = TestBuffer::default();
|
||||
|
||||
@@ -45,6 +45,7 @@ use esp_hal::{
|
||||
main,
|
||||
};
|
||||
use esp_println::println;
|
||||
use esp_storage::FlashStorage;
|
||||
|
||||
esp_bootloader_esp_idf::esp_app_desc!();
|
||||
|
||||
@@ -55,11 +56,11 @@ fn main() -> ! {
|
||||
esp_println::logger::init_logger_from_env();
|
||||
let peripherals = esp_hal::init(esp_hal::Config::default());
|
||||
|
||||
let mut storage = esp_storage::FlashStorage::new();
|
||||
let mut flash = FlashStorage::new();
|
||||
|
||||
let mut buffer = [0u8; esp_bootloader_esp_idf::partitions::PARTITION_TABLE_MAX_LEN];
|
||||
let pt = esp_bootloader_esp_idf::partitions::read_partition_table(&mut storage, &mut buffer)
|
||||
.unwrap();
|
||||
let pt =
|
||||
esp_bootloader_esp_idf::partitions::read_partition_table(&mut flash, &mut buffer).unwrap();
|
||||
|
||||
// List all partitions - this is just FYI
|
||||
for i in 0..pt.len() {
|
||||
@@ -75,7 +76,7 @@ fn main() -> ! {
|
||||
))
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let mut ota_part = ota_part.as_embedded_storage(&mut storage);
|
||||
let mut ota_part = ota_part.as_embedded_storage(&mut flash);
|
||||
println!("Found ota data");
|
||||
|
||||
let mut ota = esp_bootloader_esp_idf::ota::Ota::new(&mut ota_part).unwrap();
|
||||
@@ -140,7 +141,7 @@ fn main() -> ! {
|
||||
}
|
||||
.unwrap();
|
||||
println!("Found partition: {:?}", next_app_partition);
|
||||
let mut next_app_partition = next_app_partition.as_embedded_storage(&mut storage);
|
||||
let mut next_app_partition = next_app_partition.as_embedded_storage(&mut flash);
|
||||
|
||||
// write to the app partition
|
||||
for (sector, chunk) in OTA_IMAGE.chunks(4096).enumerate() {
|
||||
@@ -157,7 +158,7 @@ fn main() -> ! {
|
||||
))
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let mut ota_part = ota_part.as_embedded_storage(&mut storage);
|
||||
let mut ota_part = ota_part.as_embedded_storage(&mut flash);
|
||||
let mut ota = esp_bootloader_esp_idf::ota::Ota::new(&mut ota_part).unwrap();
|
||||
ota.set_current_slot(next_slot).unwrap();
|
||||
ota.set_current_ota_state(esp_bootloader_esp_idf::ota::OtaImageState::New)
|
||||
|
||||
@@ -277,7 +277,15 @@ impl Package {
|
||||
features.push("defmt-espflash".to_owned());
|
||||
features.push("critical-section".to_owned());
|
||||
}
|
||||
Package::EspStorage => {}
|
||||
Package::EspStorage => {
|
||||
if config.name() == "esp32c2"
|
||||
|| config.name() == "esp32c3"
|
||||
|| config.name() == "esp32s2"
|
||||
{
|
||||
println!("pizda usho");
|
||||
features.push("portable-atomic/unsafe-assume-single-core".to_owned());
|
||||
}
|
||||
}
|
||||
Package::EspBootloaderEspIdf => {
|
||||
features.push("defmt".to_owned());
|
||||
features.push("validation".to_owned());
|
||||
@@ -389,7 +397,19 @@ impl Package {
|
||||
cases.push(vec!["esp-alloc".to_owned(), "esp-hal/unstable".to_owned()])
|
||||
}
|
||||
Package::EspStorage => {
|
||||
cases.push(vec!["defmt".to_owned()]);
|
||||
// TODO: https://github.com/esp-rs/esp-hal/issues/4136
|
||||
if config.name() == "esp32c2"
|
||||
|| config.name() == "esp32c3"
|
||||
|| config.name() == "esp32s2"
|
||||
{
|
||||
// println!("kokot usho");
|
||||
cases.push(vec![
|
||||
"defmt".to_owned(),
|
||||
"portable-atomic/unsafe-assume-single-core".to_owned(),
|
||||
]);
|
||||
} else {
|
||||
cases.push(vec!["defmt".to_owned()]);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user