diff --git a/examples/button_click.rs b/examples/button_click.rs index db1b22c..47ed94a 100644 --- a/examples/button_click.rs +++ b/examples/button_click.rs @@ -44,16 +44,14 @@ fn main() -> Result<(), LvError> { button.on_event(|mut btn, event| { if let lvgl::Event::Clicked = event { if btn_state { - btn_lbl - .set_text(CString::new("Click me!").unwrap().as_c_str()) - .unwrap(); + let nt = CString::new("Click me!").unwrap(); + btn_lbl.set_text(nt.as_c_str()).unwrap(); } else { - btn_lbl - .set_text(CString::new("Clicked!").unwrap().as_c_str()) - .unwrap(); + let nt = CString::new("Clicked!").unwrap(); + btn_lbl.set_text(nt.as_c_str()).unwrap(); } btn_state = !btn_state; - println!("Clicked!"); + println!("Clicked! Inner.."); btn.toggle().unwrap(); } })?; diff --git a/lvgl-sys/src/lib.rs b/lvgl-sys/src/lib.rs index 3e79a69..e824396 100644 --- a/lvgl-sys/src/lib.rs +++ b/lvgl-sys/src/lib.rs @@ -22,11 +22,11 @@ mod tests { unsafe { lv_init(); - let horizontal_resolution = lv_disp_get_hor_res(std::ptr::null_mut()); - assert_eq!(horizontal_resolution, 480); + let horizontal_resolution = lv_disp_get_hor_res(core::ptr::null_mut()); + assert_eq!(horizontal_resolution, 240); - let vertical_resolution = lv_disp_get_ver_res(std::ptr::null_mut()); - assert_eq!(vertical_resolution, 320); + let vertical_resolution = lv_disp_get_ver_res(core::ptr::null_mut()); + assert_eq!(vertical_resolution, 240); } } } diff --git a/lvgl/src/lib.rs b/lvgl/src/lib.rs index 6ef5b17..8042594 100644 --- a/lvgl/src/lib.rs +++ b/lvgl/src/lib.rs @@ -1,9 +1,9 @@ -#![no_std] +#![cfg_attr(not(test), no_std)] #[macro_use] extern crate bitflags; -pub mod mem; +pub(crate) mod mem; mod support; mod ui; #[macro_use] diff --git a/lvgl/src/mem.rs b/lvgl/src/mem.rs index 984d8c8..a8cbc40 100644 --- a/lvgl/src/mem.rs +++ b/lvgl/src/mem.rs @@ -1,21 +1,30 @@ use crate::{LvError, LvResult}; use core::mem; -use core::ops::{Deref, DerefMut}; -use core::ptr; use core::ptr::NonNull; /// Places `T` into LVGL memory. -pub struct Box(NonNull); +pub(crate) struct Box(NonNull); impl Box { pub fn new(inner: T) -> LvResult> { - let layout = mem::size_of::(); + assert_ne!(mem::size_of::(), 0, "We don't handle ZSTs"); + + let size = mem::size_of::(); let inner = unsafe { - let ptr = lvgl_sys::lv_mem_alloc(layout as lvgl_sys::size_t) as *mut T; + // LVGL already aligns the memory address for us + let ptr = lvgl_sys::lv_mem_alloc(size as lvgl_sys::size_t) as *mut T; + + assert_eq!( + ptr as usize % mem::align_of::(), + 0, + "Memory address not aligned!" + ); + match NonNull::new(ptr) { Some(v) => { // Move `T` to LVGL managed memory - ptr::write(ptr, inner); + // It will panic if LVGL memory is not aligned + ptr.write(inner); Ok(v) } None => Err(LvError::LvOOMemory), @@ -24,8 +33,8 @@ impl Box { Ok(Box(inner?)) } - pub fn into_raw(b: Box) -> *mut T { - let b = mem::ManuallyDrop::new(b); + pub fn into_raw(self) -> *mut T { + let b = mem::ManuallyDrop::new(self); b.0.as_ptr() } } @@ -38,20 +47,6 @@ impl Drop for Box { } } -impl Deref for Box { - type Target = T; - - fn deref(&self) -> &T { - unsafe { self.0.as_ref() } - } -} - -impl DerefMut for Box { - fn deref_mut(&mut self) -> &mut T { - unsafe { self.0.as_mut() } - } -} - impl AsMut for Box { fn as_mut(&mut self) -> &mut T { unsafe { self.0.as_mut() } @@ -61,12 +56,23 @@ impl AsMut for Box { #[cfg(test)] mod test { use super::*; + use core::mem::MaybeUninit; + use std::sync::Once; + + static INIT_LVGL: Once = Once::new(); + + fn init() { + INIT_LVGL.call_once(|| { + unsafe { + lvgl_sys::lv_init(); + }; + }); + } #[test] fn place_value_in_lv_mem() { - unsafe { - lvgl_sys::_lv_mem_init(); - }; + init(); + let v = Box::new(5).unwrap(); drop(v); let v = Box::new(10).unwrap(); @@ -75,26 +81,51 @@ mod test { #[test] fn place_complex_value_in_lv_mem() { - unsafe { - lvgl_sys::_lv_mem_init(); - }; + init(); + #[repr(C)] + #[derive(Debug)] struct Point { x: u64, - y: u64, + y: i8, + t: i32, disp: i32, } - let p = Point { - x: 32, - y: 240, - disp: -100, - }; + for i in 0..100 { + let p = Point { + x: i, + y: 42, + t: 0, + disp: -100, + }; - let b = Box::new(p).unwrap(); + println!("{:?}", p); + let mut b = Box::new(p).unwrap_or_else(|_| { + print_mem_info(); + panic!("OOM"); + }); - assert_eq!(b.x, 32); - assert_eq!(b.y, 240); - assert_eq!(b.disp, -100); + println!("memory address is {:p}", b.as_mut()); + + let point = b.as_mut(); + if point.x != i { + print_mem_info(); + + println!("{:?}", point); + } + assert_eq!(point.x, i); + } + } + + fn print_mem_info() { + let mut info = MaybeUninit::uninit(); + unsafe { + lvgl_sys::lv_mem_monitor(info.as_mut_ptr()); + } + if !info.as_ptr().is_null() { + let info = unsafe { info.assume_init() }; + println!("mem info: {:?}", info); + } } } diff --git a/lvgl/src/ui.rs b/lvgl/src/ui.rs index 7902c1b..1309723 100644 --- a/lvgl/src/ui.rs +++ b/lvgl/src/ui.rs @@ -16,7 +16,7 @@ static LVGL_IN_USE: AtomicBool = AtomicBool::new(false); // TODO: Make this an external configuration const REFRESH_BUFFER_LEN: usize = 2; // Declare a buffer for the refresh rate -const BUF_SIZE: usize = lvgl_sys::LV_HOR_RES_MAX as usize * REFRESH_BUFFER_LEN; +pub(crate) const BUF_SIZE: usize = lvgl_sys::LV_HOR_RES_MAX as usize * REFRESH_BUFFER_LEN; pub struct UI where