diff --git a/lvgl/Cargo.toml b/lvgl/Cargo.toml index 46a1737..dfa8971 100644 --- a/lvgl/Cargo.toml +++ b/lvgl/Cargo.toml @@ -17,10 +17,10 @@ cty = "0.2.1" embedded-graphics = "0.6.2" cstr_core = "0.2.3" bitflags = "1.2.1" -lazy_static = { version = "1.4.0", features = ["spin_no_std"] } [features] -lvgl_alloc = [] +alloc = ["cstr_core/alloc"] +lvgl_alloc = ["alloc"] [build-dependencies] quote = "1.0.9" @@ -28,23 +28,24 @@ proc-macro2 = "1.0.24" lvgl-codegen = { version = "0.5.2", path = "../lvgl-codegen" } lvgl-sys = { version = "0.5.2", path = "../lvgl-sys" } - [dev-dependencies] embedded-graphics-simulator = "0.2.1" heapless = "0.5.5" -cstr_core = { version = "0.2.0", features = ["alloc"] } [[example]] name = "demo" path = "../examples/demo.rs" +required-features = ["alloc"] [[example]] name = "bar" path = "../examples/bar.rs" +required-features = ["alloc"] [[example]] name = "button_click" path = "../examples/button_click.rs" +required-features = ["alloc"] [[example]] name = "gauge" @@ -53,3 +54,4 @@ path = "../examples/gauge.rs" [[example]] name = "arc" path = "../examples/arc.rs" +required-features = ["lvgl_alloc"] diff --git a/lvgl/src/allocator.rs b/lvgl/src/allocator.rs index f375df9..90e60fd 100644 --- a/lvgl/src/allocator.rs +++ b/lvgl/src/allocator.rs @@ -9,12 +9,12 @@ pub struct LvglAlloc; unsafe impl GlobalAlloc for LvglAlloc { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { // Make sure LVGL is initialized! - let _ = *crate::LVGL_INITIALIZED; + crate::lvgl_init(); lvgl_sys::lv_mem_alloc(layout.size() as lvgl_sys::size_t) as *mut u8 } unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { - let _ = *crate::LVGL_INITIALIZED; + crate::lvgl_init(); lvgl_sys::lv_mem_free(ptr as *const cty::c_void) } } diff --git a/lvgl/src/lib.rs b/lvgl/src/lib.rs index 1d6fc76..e46452c 100644 --- a/lvgl/src/lib.rs +++ b/lvgl/src/lib.rs @@ -20,21 +20,30 @@ extern crate bitflags; #[cfg(feature = "lvgl_alloc")] extern crate alloc; +// We can ONLY use `alloc::boxed::Box` if `lvgl_alloc` is enabled. +// That is because we use `Box` to send memory references to LVGL. Since the global allocator, when +// `lvgl_alloc` feature is enabled, is the LVGL memory manager then everything is in LVGL +// managed memory anyways. In that case we can use the Rust's provided Box definition. +// +#[cfg(feature = "lvgl_alloc")] +use ::alloc::boxed::Box; + +#[cfg(feature = "lvgl_alloc")] +mod allocator; + mod support; mod ui; #[macro_use] mod lv_core; pub mod widgets; -#[cfg(feature = "lvgl_alloc")] -mod allocator; - -#[cfg(feature = "lvgl_alloc")] -use ::alloc::boxed::Box; - #[cfg(not(feature = "lvgl_alloc"))] pub(crate) mod mem; +// When LVGL allocator is not used on the Rust code, we need a way to add objects to the LVGL +// managed memory. We implement a very simple `Box` that has the minimal features to copy memory +// safely to the LVGL managed memory. +// #[cfg(not(feature = "lvgl_alloc"))] use crate::mem::Box; @@ -42,12 +51,18 @@ pub use lv_core::*; pub use support::*; pub use ui::*; +use core::sync::atomic::{AtomicBool, Ordering}; + // Initialize LVGL only once. -lazy_static::lazy_static! { - static ref LVGL_INITIALIZED: bool = { +static LVGL_INITIALIZED: AtomicBool = AtomicBool::new(false); + +pub(crate) fn lvgl_init() { + if LVGL_INITIALIZED + .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) + .is_ok() + { unsafe { lvgl_sys::lv_init(); } - true - }; + } } diff --git a/lvgl/src/mem.rs b/lvgl/src/mem.rs index b91725f..0d193d7 100644 --- a/lvgl/src/mem.rs +++ b/lvgl/src/mem.rs @@ -72,22 +72,11 @@ impl AsMut for Box { #[cfg(test)] mod test { use super::*; - use std::sync::Once; use std::vec::Vec; - static INIT_LVGL: Once = Once::new(); - - fn init() { - INIT_LVGL.call_once(|| { - unsafe { - lvgl_sys::lv_init(); - }; - }); - } - #[test] fn place_value_in_lv_mem() { - init(); + crate::lvgl_init(); let v = Box::new(5); drop(v); @@ -97,7 +86,7 @@ mod test { #[test] fn place_complex_value_in_lv_mem() { - init(); + crate::lvgl_init(); #[repr(C)] #[derive(Debug)] diff --git a/lvgl/src/ui.rs b/lvgl/src/ui.rs index 2d4751c..b6190ed 100644 --- a/lvgl/src/ui.rs +++ b/lvgl/src/ui.rs @@ -47,7 +47,7 @@ where .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) .is_ok() { - let _ = *crate::LVGL_INITIALIZED; + crate::lvgl_init(); Ok(Self { _not_sync: PhantomData, display_data: None,