Upgrade to lvgl v7.10.1 #47
7 changed files with 66 additions and 52 deletions
|
@ -8,8 +8,8 @@ publish = false
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
lvgl = { path = "../lvgl" }
|
lvgl = { path = "../lvgl" }
|
||||||
lvgl-sys = { path = "../lvgl-sys" }
|
lvgl-sys = { path = "../lvgl-sys" }
|
||||||
embedded-graphics = "0.6"
|
embedded-graphics = "0.6.2"
|
||||||
embedded-graphics-simulator = "0.2.0"
|
embedded-graphics-simulator = "0.2.1"
|
||||||
heapless = "0.5.5"
|
heapless = "0.5.5"
|
||||||
cstr_core = { version = "0.2.0", features = ["alloc"] }
|
cstr_core = { version = "0.2.0", features = ["alloc"] }
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use cstr_core::{CStr, CString};
|
use cstr_core::CString;
|
||||||
use embedded_graphics::pixelcolor::Rgb565;
|
use embedded_graphics::pixelcolor::Rgb565;
|
||||||
use embedded_graphics::prelude::*;
|
use embedded_graphics::prelude::*;
|
||||||
use embedded_graphics_simulator::{
|
use embedded_graphics_simulator::{
|
||||||
|
@ -52,20 +52,6 @@ fn main() -> Result<(), LvError> {
|
||||||
bt.set_label_align(LabelAlign::Left)?;
|
bt.set_label_align(LabelAlign::Left)?;
|
||||||
bt.set_align(&mut screen, Align::InTopLeft, 0, 0)?;
|
bt.set_align(&mut screen, Align::InTopLeft, 0, 0)?;
|
||||||
|
|
||||||
fn set_text<S>(text: S) -> Result<(), ()>
|
|
||||||
where
|
|
||||||
S: AsRef<cstr_core::CStr>,
|
|
||||||
{
|
|
||||||
let _v: *const i8 = text.as_ref().as_ptr();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut t: heapless::String<heapless::consts::U8> = heapless::String::from("test");
|
|
||||||
t.push('\0').unwrap();
|
|
||||||
set_text(CStr::from_bytes_with_nul(t.as_bytes()).unwrap()).unwrap();
|
|
||||||
set_text(cstr_core::CStr::from_bytes_with_nul("test\0".as_bytes()).unwrap()).unwrap();
|
|
||||||
set_text(cstr_core::CString::new("test").unwrap().as_c_str()).unwrap();
|
|
||||||
|
|
||||||
let mut power = Label::new(&mut screen)?;
|
let mut power = Label::new(&mut screen)?;
|
||||||
power.set_recolor(true)?;
|
power.set_recolor(true)?;
|
||||||
power.set_width(80)?;
|
power.set_width(80)?;
|
||||||
|
@ -80,8 +66,8 @@ fn main() -> Result<(), LvError> {
|
||||||
if i > 59 {
|
if i > 59 {
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
let val = format!("21:{:02}", i);
|
let val = CString::new(format!("21:{:02}", i)).unwrap();
|
||||||
time.set_text(CString::new(val.as_str()).unwrap().as_c_str())?;
|
time.set_text(&val)?;
|
||||||
i = 1 + i;
|
i = 1 + i;
|
||||||
|
|
||||||
ui.task_handler();
|
ui.task_handler();
|
||||||
|
|
|
@ -12,7 +12,7 @@ repository = "https://github.com/rafaelcaricio/lvgl-rs"
|
||||||
regex = "1.4.3"
|
regex = "1.4.3"
|
||||||
quote = "1.0.9"
|
quote = "1.0.9"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
proc-macro2 = "1.0.24"
|
proc-macro2 = "1.0.27"
|
||||||
Inflector = "0.11.4"
|
Inflector = "0.11.4"
|
||||||
syn = { version = "1.0.62", features = ["full"]}
|
syn = { version = "1.0.72", features = ["full"]}
|
||||||
|
|
||||||
|
|
|
@ -20,5 +20,5 @@ name = "lvgl_sys"
|
||||||
cty = "0.2.1"
|
cty = "0.2.1"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cc = "1.0.67"
|
cc = "1.0.68"
|
||||||
bindgen = "0.57.0"
|
bindgen = "0.58.1"
|
||||||
|
|
|
@ -29,21 +29,21 @@ fn main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
if !conf_path.exists() {
|
if !conf_path.exists() {
|
||||||
panic!(format!(
|
panic!(
|
||||||
"Directory {} referenced by {} needs to exist",
|
"Directory {} referenced by {} needs to exist",
|
||||||
conf_path.to_string_lossy(),
|
conf_path.to_string_lossy(),
|
||||||
CONFIG_NAME
|
CONFIG_NAME
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
if !conf_path.is_dir() {
|
if !conf_path.is_dir() {
|
||||||
panic!(format!("{} needs to be a directory", CONFIG_NAME));
|
panic!("{} needs to be a directory", CONFIG_NAME);
|
||||||
}
|
}
|
||||||
if !conf_path.join("lv_conf.h").exists() {
|
if !conf_path.join("lv_conf.h").exists() {
|
||||||
panic!(format!(
|
panic!(
|
||||||
"Directory {} referenced by {} needs to contain a file called lv_conf.h",
|
"Directory {} referenced by {} needs to contain a file called lv_conf.h",
|
||||||
conf_path.to_string_lossy(),
|
conf_path.to_string_lossy(),
|
||||||
CONFIG_NAME
|
CONFIG_NAME
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
|
|
|
@ -3,11 +3,16 @@ use core::mem;
|
||||||
use core::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut};
|
||||||
use core::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
|
|
||||||
/// Places `T` into LVGL memory.
|
/// Places a sized `T` into LVGL memory.
|
||||||
|
///
|
||||||
|
/// This is useful for cases when we need to allocate memory on Rust side
|
||||||
|
/// and handover the management of that memory to LVGL. May also be used in cases we
|
||||||
|
/// want to use dynamic memory in the Rust side.
|
||||||
pub(crate) struct Box<T>(NonNull<T>);
|
pub(crate) struct Box<T>(NonNull<T>);
|
||||||
|
|
||||||
impl<T> Box<T> {
|
impl<T> Box<T> {
|
||||||
pub fn new(inner: T) -> LvResult<Box<T>> {
|
/// Allocate memory using LVGL memory API and place `T` in the LVGL tracked memory.
|
||||||
|
pub fn new(value: T) -> LvResult<Box<T>> {
|
||||||
let size = mem::size_of::<T>();
|
let size = mem::size_of::<T>();
|
||||||
let inner = unsafe {
|
let inner = unsafe {
|
||||||
let ptr = lvgl_sys::lv_mem_alloc(size as lvgl_sys::size_t) as *mut T;
|
let ptr = lvgl_sys::lv_mem_alloc(size as lvgl_sys::size_t) as *mut T;
|
||||||
|
@ -19,17 +24,14 @@ impl<T> Box<T> {
|
||||||
"Memory address not aligned!"
|
"Memory address not aligned!"
|
||||||
);
|
);
|
||||||
|
|
||||||
match NonNull::new(ptr) {
|
NonNull::new(ptr)
|
||||||
Some(v) => {
|
.map(|p| {
|
||||||
// Move `T` to LVGL managed memory
|
p.as_ptr().write(value);
|
||||||
// It will panic if LVGL memory is not aligned
|
p
|
||||||
ptr.write(inner);
|
})
|
||||||
Ok(v)
|
.ok_or(LvError::LvOOMemory)?
|
||||||
}
|
|
||||||
None => Err(LvError::LvOOMemory),
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Ok(Box(inner?))
|
Ok(Box(inner))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_raw(self) -> *mut T {
|
pub fn into_raw(self) -> *mut T {
|
||||||
|
@ -69,8 +71,8 @@ impl<T> AsMut<T> for Box<T> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use core::mem::MaybeUninit;
|
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
use std::vec::Vec;
|
||||||
|
|
||||||
static INIT_LVGL: Once = Once::new();
|
static INIT_LVGL: Once = Once::new();
|
||||||
|
|
||||||
|
@ -105,6 +107,9 @@ mod test {
|
||||||
disp: i32,
|
disp: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let initial_mem_info = mem_info();
|
||||||
|
|
||||||
|
let mut keep = Vec::new();
|
||||||
for i in 0..100 {
|
for i in 0..100 {
|
||||||
let p = Point {
|
let p = Point {
|
||||||
x: i,
|
x: i,
|
||||||
|
@ -115,7 +120,8 @@ mod test {
|
||||||
|
|
||||||
println!("{:?}", p);
|
println!("{:?}", p);
|
||||||
let mut b = Box::new(p).unwrap_or_else(|_| {
|
let mut b = Box::new(p).unwrap_or_else(|_| {
|
||||||
print_mem_info();
|
let info = mem_info();
|
||||||
|
println!("mem info: {:?}", &info);
|
||||||
panic!("OOM");
|
panic!("OOM");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -123,22 +129,41 @@ mod test {
|
||||||
|
|
||||||
let point = b.as_mut();
|
let point = b.as_mut();
|
||||||
if point.x != i {
|
if point.x != i {
|
||||||
print_mem_info();
|
|
||||||
|
|
||||||
println!("{:?}", point);
|
println!("{:?}", point);
|
||||||
}
|
}
|
||||||
assert_eq!(point.x, i);
|
assert_eq!(point.x, i);
|
||||||
|
|
||||||
|
let info = mem_info();
|
||||||
|
println!("mem info: {:?}", &info);
|
||||||
|
keep.push(b);
|
||||||
}
|
}
|
||||||
|
drop(keep);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
lvgl_sys::lv_mem_defrag();
|
||||||
|
}
|
||||||
|
|
||||||
|
let final_info = mem_info();
|
||||||
|
println!("mem info: {:?}", &final_info);
|
||||||
|
|
||||||
|
// If this fails, we are leaking memory! BOOM! \o/
|
||||||
|
assert_eq!(initial_mem_info.free_size, final_info.free_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_mem_info() {
|
fn mem_info() -> lvgl_sys::lv_mem_monitor_t {
|
||||||
let mut info = MaybeUninit::uninit();
|
let mut info = lvgl_sys::lv_mem_monitor_t {
|
||||||
|
total_size: 0,
|
||||||
|
free_cnt: 0,
|
||||||
|
free_size: 0,
|
||||||
|
free_biggest_size: 0,
|
||||||
|
used_cnt: 0,
|
||||||
|
max_used: 0,
|
||||||
|
used_pct: 0,
|
||||||
|
frag_pct: 0
|
||||||
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
lvgl_sys::lv_mem_monitor(info.as_mut_ptr());
|
lvgl_sys::lv_mem_monitor(&mut info as *mut _);
|
||||||
}
|
|
||||||
if !info.as_ptr().is_null() {
|
|
||||||
let info = unsafe { info.assume_init() };
|
|
||||||
println!("mem info: {:?}", info);
|
|
||||||
}
|
}
|
||||||
|
info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,10 @@ where
|
||||||
C: PixelColor + From<Color>,
|
C: PixelColor + From<Color>,
|
||||||
{
|
{
|
||||||
pub fn init() -> LvResult<Self> {
|
pub fn init() -> LvResult<Self> {
|
||||||
if !LVGL_IN_USE.compare_and_swap(false, true, Ordering::SeqCst) {
|
if LVGL_IN_USE
|
||||||
|
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
lvgl_sys::lv_init();
|
lvgl_sys::lv_init();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue