#[cfg(feature = "std")]
use std::sync::OnceLock;
#[cfg(not(feature = "std"))]
pub struct OnceLock<T> {
data: core::cell::UnsafeCell<Option<T>>,
initialized: core::sync::atomic::AtomicBool,
}
#[cfg(not(feature = "std"))]
unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
#[cfg(not(feature = "std"))]
unsafe impl<T: Send> Send for OnceLock<T> {}
#[cfg(not(feature = "std"))]
impl<T> OnceLock<T> {
pub const fn new() -> Self {
OnceLock {
data: core::cell::UnsafeCell::new(None),
initialized: core::sync::atomic::AtomicBool::new(false),
}
}
pub fn get(&self) -> Option<&T> {
if self.initialized.load(core::sync::atomic::Ordering::Acquire) {
unsafe { (*self.data.get()).as_ref() }
} else {
None
}
}
pub fn set(&self, value: T) -> core::result::Result<(), T> {
if self
.initialized
.swap(true, core::sync::atomic::Ordering::AcqRel)
{
Err(value)
} else {
unsafe {
*self.data.get() = Some(value);
}
Ok(())
}
}
}
pub type FileResult<T> = core::result::Result<T, ()>;
pub trait Platform: Send + Sync {
fn get_timestamp(&self) -> u64;
fn get_timestamp_us(&self) -> u64;
fn spin_lock(&self, lock: &mut u32);
fn spin_unlock(&self, lock: &mut u32);
fn compiler_barrier(&self);
fn full_memory_barrier(&self);
fn memcpy(&self, dest: *mut u8, src: *const u8, size: usize);
fn memset(&self, dest: *mut u8, value: u8, size: usize);
fn delay_ms(&self, ms: u32);
fn delay_us(&self, us: u32);
fn file_open(&self, path: &str, mode: FileMode) -> FileResult<FileHandle>;
fn file_close(&self, handle: FileHandle) -> FileResult<()>;
fn file_write(&self, handle: FileHandle, buffer: *const u8, size: usize) -> FileResult<usize>;
fn file_read(&self, handle: FileHandle, buffer: *mut u8, size: usize) -> FileResult<usize>;
fn file_seek(&self, handle: FileHandle, offset: i64, whence: SeekWhence) -> FileResult<u64>;
fn file_remove(&self, path: &str) -> FileResult<()>;
fn file_size(&self, path: &str) -> FileResult<usize>;
fn crc32(&self, data: *const u8, size: usize) -> u32;
}
#[derive(Copy, Clone)]
pub enum FileMode {
Read,
Write,
ReadWrite,
Append,
}
pub type FileHandle = *const u8;
#[derive(Copy, Clone)]
pub enum SeekWhence {
SeekSet,
SeekCur,
SeekEnd,
}
pub static PLATFORM: OnceLock<&'static dyn Platform> = OnceLock::new();
pub fn init_platform(platform: &'static dyn Platform) {
PLATFORM.set(platform).ok();
}
#[cfg(test)]
pub fn reset_platform() {
unsafe {
#[cfg(not(feature = "std"))]
{
let platform_ptr = &PLATFORM as *const OnceLock<&'static dyn Platform>
as *mut OnceLock<&'static dyn Platform>;
(*platform_ptr)
.initialized
.store(false, core::sync::atomic::Ordering::Release);
*(*platform_ptr).data.get() = None;
}
}
}
pub fn get_timestamp() -> u64 {
if let Some(platform) = PLATFORM.get() {
platform.get_timestamp()
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
0
}
}
pub fn get_timestamp_us() -> u64 {
if let Some(platform) = PLATFORM.get() {
platform.get_timestamp_us()
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
0
}
}
pub fn spin_lock(lock: &mut u32) {
if let Some(platform) = PLATFORM.get() {
platform.spin_lock(lock)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
}
}
pub fn spin_unlock(lock: &mut u32) {
if let Some(platform) = PLATFORM.get() {
platform.spin_unlock(lock)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
}
}
pub fn compiler_barrier() {
if let Some(platform) = PLATFORM.get() {
platform.compiler_barrier()
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
}
}
pub fn full_memory_barrier() {
if let Some(platform) = PLATFORM.get() {
platform.full_memory_barrier()
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
}
}
pub fn memcpy(dest: *mut u8, src: *const u8, size: usize) {
if let Some(platform) = PLATFORM.get() {
platform.memcpy(dest, src, size)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
}
}
pub fn memset(dest: *mut u8, value: u8, size: usize) {
if let Some(platform) = PLATFORM.get() {
platform.memset(dest, value, size)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
}
}
pub fn delay_ms(ms: u32) {
if let Some(platform) = PLATFORM.get() {
platform.delay_ms(ms)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
}
}
pub fn delay_us(us: u32) {
if let Some(platform) = PLATFORM.get() {
platform.delay_us(us)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
}
}
pub fn file_open(path: &str, mode: FileMode) -> FileResult<FileHandle> {
if let Some(platform) = PLATFORM.get() {
platform.file_open(path, mode)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
Err(())
}
}
pub fn file_close(handle: FileHandle) -> FileResult<()> {
if let Some(platform) = PLATFORM.get() {
platform.file_close(handle)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
Err(())
}
}
pub fn file_write(handle: FileHandle, buffer: *const u8, size: usize) -> FileResult<usize> {
if let Some(platform) = PLATFORM.get() {
platform.file_write(handle, buffer, size)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
Err(())
}
}
pub fn file_read(handle: FileHandle, buffer: *mut u8, size: usize) -> FileResult<usize> {
if let Some(platform) = PLATFORM.get() {
platform.file_read(handle, buffer, size)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
Err(())
}
}
pub fn file_seek(handle: FileHandle, offset: i64, whence: SeekWhence) -> FileResult<u64> {
if let Some(platform) = PLATFORM.get() {
platform.file_seek(handle, offset, whence)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
Err(())
}
}
pub fn file_remove(path: &str) -> FileResult<()> {
if let Some(platform) = PLATFORM.get() {
platform.file_remove(path)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
Err(())
}
}
pub fn file_size(path: &str) -> FileResult<usize> {
if let Some(platform) = PLATFORM.get() {
platform.file_size(path)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
Err(())
}
}
pub fn crc32(data: *const u8, size: usize) -> u32 {
if let Some(platform) = PLATFORM.get() {
platform.crc32(data, size)
} else {
#[cfg(feature = "log")]
crate::log::error!("Platform not initialized");
0
}
}
pub mod baremetal;
pub mod posix;