文章目录
说在前面 关于slint 关于no-std 关于dma 准备工作 相关依赖 代码 结果 参考
说在前面
esp32版本:s3 运行环境:no-std 开发环境:wsl2 LCD模块:ST7789V2 240*280 LCD Slint版本:master分支 github地址:这里
关于slint
官网 为啥不用lvgl
? 只能说rust的生态还是不太行,lvgl的rust binding似乎还在开发中,已经有仓库了,但是还在开发中。 slint
目前比较完善,但是相关资料也少。 反正已经在折腾rust
了,也不在乎再多折腾个小众点的。
关于no-std
上一篇还是std
环境,怎么就变成no-std
了? std
环境下也折腾了slint
,但是fps就是不怎么高 (可能哪里写的不对) ,然后就试了下no-std
,稍微丝滑点,并且编译也快。
关于dma
rust
生态下dma
的资料更是少的可怜,找了好久也没啥进展,所以本文不涉及dma
准备工作
引脚连接见上篇 开发环境部分,由于不需要esp idf
,简单很多,cargo
直接搞定
相关依赖
Cargo.toml[ dependencies]
hal = { package = "esp32s3- hal", version = "0.13.0"}
esp- backtrace = { version = "0.9.0", features = [ "esp32s3" , "panic-handler" , "exception-handler" , "print-uart" ] }
esp- println = { version = "0.7.0", features = [ "esp32s3" , "log" ] }
log = { version = "0.4.18" }
esp- alloc = { version = "0.3.0" }
embedded- hal = "0.2.7"
embedded- graphics- core = "0.4.0"
embedded- graphics = "0.8.1"
embedded- graphics- framebuf = "0.5.0"
display- interface = "0.4"
display- interface- spi = "0.4"
mipidsi = "0.7.1"
slint = { git = "https: //githubfast.com/slint- ui/slint", default- features = false, features = [ "compat-1-2" , "unsafe-single-threaded" , "libm" , "renderer-software" ] }
[ build- dependencies]
slint- build = { git = "https: //githubfast.com/slint- ui/slint" }
代码
#![no_std]
#![no_main]
extern crate alloc ;
use alloc:: boxed:: Box ;
use alloc:: rc:: Rc ;
use rs_esp32s3_no_std_st7789_demo:: dma:: DmaBackend ;
use core:: cell:: RefCell ;
use core:: mem:: MaybeUninit ;
use display_interface_spi:: SPIInterfaceNoCS ;
use embedded_graphics_core:: prelude:: { DrawTarget , Point , RgbColor , Size } ;
use embedded_graphics_core:: { pixelcolor:: raw:: RawU16 , primitives:: Rectangle } ;
use esp_backtrace as _;
use esp_println:: println;
use hal:: spi:: master:: { Spi , dma} ;
use hal:: {
clock:: { ClockControl , CpuClock } ,
peripherals:: Peripherals ,
prelude:: * ,
spi:: SpiMode ,
systimer:: SystemTimer ,
timer:: TimerGroup ,
Delay , Rtc , IO ,
} ;
use mipidsi:: Display ;
#[global_allocator]
static ALLOCATOR : esp_alloc:: EspHeap = esp_alloc:: EspHeap :: empty ( ) ;
fn init_heap ( ) {
const HEAP_SIZE : usize = 250 * 1024 ;
static mut HEAP : MaybeUninit < [ u8 ; HEAP_SIZE ] > = MaybeUninit :: uninit ( ) ;
unsafe {
ALLOCATOR . init ( HEAP . as_mut_ptr ( ) as * mut u8 , HEAP_SIZE ) ;
}
}
slint:: include_modules! ( ) ;
#[entry]
fn main ( ) -> ! {
init_heap ( ) ;
slint:: platform:: set_platform ( Box :: new ( EspBackend :: default ( ) ) )
. expect ( "backend already initialized" ) ;
let main_window = Recipe :: new ( ) . unwrap ( ) ;
let strong = main_window. clone_strong ( ) ;
let timer = slint:: Timer :: default ( ) ;
timer. start (
slint:: TimerMode :: Repeated ,
core:: time:: Duration :: from_millis ( 1000 ) ,
move | | {
if strong. get_counter ( ) <= 0 {
strong. set_counter ( 25 ) ;
} else {
strong. set_counter ( 0 ) ;
}
} ,
) ;
main_window. run ( ) . unwrap ( ) ;
panic! ( "The MCU demo should not quit" ) ;
}
#[derive(Default)]
pub struct EspBackend {
window: RefCell < Option < Rc < slint:: platform:: software_renderer:: MinimalSoftwareWindow >> > ,
}
impl slint:: platform:: Platform for EspBackend {
fn create_window_adapter (
& self ,
) -> Result < Rc < dyn slint:: platform:: WindowAdapter > , slint:: PlatformError > {
let window = slint:: platform:: software_renderer:: MinimalSoftwareWindow :: new (
slint:: platform:: software_renderer:: RepaintBufferType :: ReusedBuffer ,
) ;
self . window. replace ( Some ( window. clone ( ) ) ) ;
Ok ( window)
}
fn duration_since_start ( & self ) -> core:: time:: Duration {
core:: time:: Duration :: from_millis (
SystemTimer :: now ( ) / ( SystemTimer :: TICKS_PER_SECOND / 1000 ) ,
)
}
fn run_event_loop ( & self ) -> Result < ( ) , slint:: PlatformError > {
let peripherals = Peripherals :: take ( ) ;
let mut system = peripherals. SYSTEM . split ( ) ;
let clocks = ClockControl :: configure ( system. clock_control, CpuClock :: Clock240MHz ) . freeze ( ) ;
let mut rtc = Rtc :: new ( peripherals. RTC_CNTL ) ;
let timer_group0 = TimerGroup :: new ( peripherals. TIMG0 , & clocks) ;
let mut wdt0 = timer_group0. wdt;
let timer_group1 = TimerGroup :: new ( peripherals. TIMG1 , & clocks) ;
let mut wdt1 = timer_group1. wdt;
rtc. rwdt. disable ( ) ;
wdt0. disable ( ) ;
wdt1. disable ( ) ;
let mut delay = Delay :: new ( & clocks) ;
let io = IO :: new ( peripherals. GPIO , peripherals. IO_MUX ) ;
let clk = io. pins. gpio18;
let sdo = io. pins. gpio17;
let cs = io. pins. gpio14;
let spi = Spi :: new_no_miso (
peripherals. SPI2 ,
clk,
sdo,
cs,
60u32 . MHz ( ) ,
SpiMode :: Mode0 ,
& clocks,
) ;
println! ( "spi init." ) ;
let dc = io. pins. gpio15. into_push_pull_output ( ) ;
let rst = io. pins. gpio16. into_push_pull_output ( ) ;
let di = SPIInterfaceNoCS :: new ( spi, dc) ;
let mut display = mipidsi:: Builder :: st7789 ( di)
. with_display_size ( 240 , 280 )
. with_window_offset_handler ( | _| ( 0 , 20 ) )
. with_framebuffer_size ( 240 , 280 )
. with_invert_colors ( mipidsi:: ColorInversion :: Inverted )
. init ( & mut delay, Some ( rst) )
. unwrap ( ) ;
println! ( "display init." ) ;
let mut bl = io. pins. gpio13. into_push_pull_output ( ) ;
bl. set_high ( ) . unwrap ( ) ;
let size = slint:: PhysicalSize :: new ( 240 , 280 ) ;
self . window. borrow ( ) . as_ref ( ) . unwrap ( ) . set_size ( size) ;
let mut buffer_provider = DrawBuffer {
display,
buffer: & mut [ slint:: platform:: software_renderer:: Rgb565Pixel :: default ( ) ; 240 ] ,
} ;
loop {
slint:: platform:: update_timers_and_animations ( ) ;
if let Some ( window) = self . window. borrow ( ) . clone ( ) {
window. draw_if_needed ( | renderer| {
renderer. render_by_line ( & mut buffer_provider) ;
} ) ;
if window. has_active_animations ( ) {
continue ;
}
}
}
}
fn debug_log ( & self , arguments: core:: fmt:: Arguments ) {
println! ( "{}" , arguments) ;
}
}
struct DrawBuffer < 'a , Display > {
display: Display ,
buffer: & 'a mut [ slint:: platform:: software_renderer:: Rgb565Pixel ] ,
}
impl < DI : display_interface:: WriteOnlyDataCommand , RST : embedded_hal:: digital:: v2:: OutputPin >
slint:: platform:: software_renderer:: LineBufferProvider
for & mut DrawBuffer < '_ , Display < DI , mipidsi:: models:: ST7789 , RST >>
{
type TargetPixel = slint:: platform:: software_renderer:: Rgb565Pixel ;
fn process_line (
& mut self ,
line: usize ,
range: core:: ops:: Range < usize > ,
render_fn: impl FnOnce ( & mut [ slint:: platform:: software_renderer:: Rgb565Pixel ] ) ,
) {
let buffer = & mut self . buffer[ range. clone ( ) ] ;
render_fn ( buffer) ;
self . display
. set_pixels (
range. start as u16 ,
line as _,
range. end as u16 ,
line as u16 ,
buffer
. iter ( )
. map ( | x| embedded_graphics_core:: pixelcolor:: raw:: RawU16 :: new ( x.0 ) . into ( ) ) ,
)
. unwrap ( ) ;
}
}
结果
还是有卡顿的感觉
参考