esp-hal/esp-storage/src/stub.rs
Dániel Buga 08d406ee2b
storage: Clean up ROM function declarations (#2058)
* Clean up external function declarations

* Tweak syntax
2024-09-02 15:24:41 +00:00

108 lines
3.1 KiB
Rust

use core::{ptr, slice};
use crate::maybe_with_critical_section;
const SUCCESS_CODE: i32 = 0;
const ERROR_CODE: i32 = 1;
const ERASE_BYTE: u8 = 0xff;
const WORD_SIZE: u32 = 4;
const SECTOR_SIZE: u32 = 4 << 10;
const NUM_SECTORS: u32 = 4;
const FLASH_SIZE: u32 = SECTOR_SIZE * NUM_SECTORS;
static mut FLASH_LOCK: bool = true;
static mut FLASH_DATA: [u8; FLASH_SIZE as usize] = [0u8; FLASH_SIZE as usize];
macro_rules! print_error {
($($tt:tt)*) => {
#[cfg(all(test, feature = "emulation"))]
eprintln!($($tt)*)
};
}
fn check<const ALIGN: u32, const SIZE: u32, const MAX_LEN: u32>(
offset: u32,
length: u32,
data: *const u32,
) -> bool {
if offset % ALIGN > 0 {
print_error!("Not aligned offset: {offset}");
return false;
}
if length % ALIGN > 0 {
print_error!("Not aligned length: {length}");
return false;
}
if offset > SIZE {
print_error!("Offset out of range: {offset} > {SIZE}");
return false;
}
if offset + length > SIZE {
print_error!("Length out of range: {offset} + {length} > {SIZE}");
return false;
}
if length > MAX_LEN {
print_error!("Length out of range: {length} > {MAX_LEN}");
return false;
}
let addr = unsafe { (data as *const u8).offset_from(ptr::null()) } as u32;
if addr % ALIGN > 0 {
print_error!("Not aligned data: {addr:#0x}");
return false;
}
if unsafe { FLASH_LOCK } {
print_error!("Flash locked");
return false;
}
true
}
pub(crate) fn spiflash_read(src_addr: u32, data: *mut u32, len: u32) -> i32 {
if check::<WORD_SIZE, FLASH_SIZE, SECTOR_SIZE>(src_addr, len, data) {
maybe_with_critical_section(|| {
let src = unsafe { slice::from_raw_parts_mut(data as *mut u8, len as _) };
unsafe { src.copy_from_slice(&FLASH_DATA[src_addr as usize..][..len as usize]) };
});
SUCCESS_CODE
} else {
ERROR_CODE
}
}
pub(crate) fn spiflash_unlock() -> i32 {
maybe_with_critical_section(|| {
unsafe { FLASH_LOCK = false };
});
SUCCESS_CODE
}
pub(crate) fn spiflash_erase_sector(sector_number: u32) -> i32 {
if check::<1, NUM_SECTORS, 1>(sector_number, 1, ptr::null()) {
maybe_with_critical_section(|| {
let dst_addr = sector_number * SECTOR_SIZE;
let len = SECTOR_SIZE;
unsafe { FLASH_DATA[dst_addr as usize..][..len as usize].fill(ERASE_BYTE) };
});
SUCCESS_CODE
} else {
ERROR_CODE
}
}
pub(crate) fn spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> i32 {
if check::<WORD_SIZE, FLASH_SIZE, SECTOR_SIZE>(dest_addr, len, data) {
maybe_with_critical_section(|| {
let dst = unsafe { slice::from_raw_parts(data as *const u8, len as _) };
for (d, s) in unsafe { &mut FLASH_DATA[dest_addr as usize..][..len as usize] }
.iter_mut()
.zip(dst)
{
*d &= *s;
}
});
SUCCESS_CODE
} else {
ERROR_CODE
}
}