RT-Thread NUC97x 移植 LVGL

作者:出出啊
链接:
https://club.rt-thread.org/ask/article/64a11e0669eabd42.html
前言 严格讲,这一篇不涉及 rt-thread 驱动,但是它是 lvgl 和 rt-thread 的接口。lvgl 在 rt-thread 上运行的基石。
移植过程 前人植树,后人纳凉。首先得感谢 meco 大佬做的工作,他给我们带了全新的 lvgl 接口。
第一步,打开 menuconfig。定位到 lvgl: powerful and easy-to-use embedded gui library
选择 “lvgl (official)” 以及 “enable lvgl music player demo for rt-thread” 两项,不用选 “littlevgl2rtt (legacy)” 。
保存退出。
第二步,执行 pkgs --update 下载 lvgl 及 demo 包。
第三步,在 bsp 目录下搜索 lvgl 文件夹。随便选一个拷贝到自己项目的 application 目录下。笔者这里从 “nuvoton k-980iot” 下拷贝了一份。如果你使用 rt-studio 拷贝过来就可以了,如果是使用 keil,需要之后手动把 这个文件夹的文件添加的项目,并添加头文件路径。
第四步,找到 lv_port_indev.c 文件,先注释掉 #include touch.h 及 nu_touch_inputevent_cb 两个函数,input 驱动先放一放。
第五步,打开 lv_port_disp.c 文件,注释掉 lv_port_disp_init 部分与 lcd_device 相关的部分,因为 drv_lcd 里并不一定实现了 lcd 设备注册。修改 draw buffer 的申请内存,以及屏幕尺寸
draw_buf1 =(void*)rt_malloc(lcd_width *50*sizeof(lv_color_t));
lv_disp_draw_buf_init(&disp_buf, draw_buf1, rt_null, lcd_width *50);
...
disp_drv.hor_res = lcd_width;
disp_drv.ver_res = lcd_height;
这个 draw buffer 不一定要按照全屏尺寸申请缓存,可以只申请十分之一行的,但是这样一整屏数据刷新会分 10 次,优点儿就是内存占用少。笔者的屏幕是 480*272 的,试过只申请 20 行的缓存,刷新显示没压力。
第六步,添加 flush_cb 回调函数。flush_cb 的原型是 void (*flush_cb)(struct _lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p); 。
staticvoid tft_flush(lv_disp_drv_t*disp_drv,constlv_area_t*area,lv_color_t*color_p)
{
rt_int32_t x, y;
lv_coord_t hres = disp_drv->hor_res;
lv_coord_t vres = disp_drv->ver_res;
/*return if the area is out the screen*/
if(area->x2 y2 x1 > hres -1|| area->y1 > vres -1){
lv_disp_flush_ready(disp_drv);
return;
}
for(y = area->y1; y y2 && y ver_res; y++){
for(x = area->x1; x x2 && x hor_res; x++){
((uint16*)u8framebufptr)[y * disp_drv->hor_res + x]= lv_color_to16(*color_p);
color_p++;
}
}
lv_disp_flush_ready(disp_drv);
}
同时,指定 disp_drv.flush_cb = tft_flush; 指向我自己的 flush_cb 。
第七步,显示驱动搞好了,是不是可以运行起来了呢?编译、调试运行。demo 应该可以跑起来了。
ge2d 的使用 但是上面的 tft_flush 回调函数是用 for 循环拷贝显示数据的。这样效率会不会低?nuc97x 系列带 ge2d 图形加速引擎,是否可以把它用上?
第一步,修改 drv_lcd ,初始化 lcm 的时候执行 vpostvastarttrigger 之前,添加 ge2d 初始化
ge2dinit(16,800,480,(void*)u8framebufptr);// 这里的参数根据实际屏幕参数而定
ge2dclearscreen(0x0);
第二步,修改 tft_flush 函数
staticvoid tft_flush(lv_disp_drv_t*disp_drv,constlv_area_t*area,lv_color_t*color_p)
{
unsignedint cmd32 =0xcc410000;
unsignedint src_x =0;
unsignedint src_y =0;
unsignedint src_width = lv_area_get_width(area);
unsignedint src_height = lv_area_get_height(area);
unsignedint dst_x = area->x1;
unsignedint dst_y = area->y1;
sysflushcache(i_d_cache);
outpw(reg_ge2d_ctl, cmd32);
switch(lv_color_depth){
case8:
cmd32 =0x00;
break;
case16:
cmd32 =0x10;
break;
case32:
cmd32 =0x20;
break;
}
cmd32 |=(inpw(reg_ge2d_misctl)&0xfffffff8);
outpw(reg_ge2d_misctl, cmd32);
outpw(reg_ge2d_sdpitch,((disp_drv->hor_res <<16)| src_width));
outpw(reg_ge2d_srcspa,0);
outpw(reg_ge2d_dstspa,((dst_y <<16)| dst_x));
outpw(reg_ge2d_rtglsz,((src_height draw_buf->last_part =0;
#if lv_color_depth == 16
if((disp_refr->inv_areas[i].x2 - disp_refr->inv_areas[i].x1)%2==0){
if(disp_refr->inv_areas[i].x1 ==0){
disp_refr->inv_areas[i].x2++;
}else{
disp_refr->inv_areas[i].x1--;
}
}
#endif
lv_refr_area(&disp_refr->inv_areas[i]);
结束语 ge2d 的效率:实测,启用 full_refresh 的时候 ge2d 有 30% 的 fps 提升。不启用的时候 fps 提升就没那么明显了,可能只有 10%。
rt-thread 的 lvgl 接口还有些欠缺的地方。lvgl 8.x 有两个 conf.h ,lv_conf.h lv_drv_conf.h lv_demo_conf.h。能用上 lvgl 提供的模板文件,从模板文件修改是最好的了。而不是把这几个文件合并成一个 lv_rt_thread_conf.h ,删掉了很多配置项。

常见的永磁电机的应用场景
UV LED的发展历史与市场趋势
国内电力企业正在大面积推广智能巡检机器人
三星公布了新一代高端处理器 性能提升关键在于7纳米制程
鸿蒙系统和安卓系统哪个好
RT-Thread NUC97x 移植 LVGL
树根互联联合创始人、CEO贺东东:树大根深,中国智造
Qualcomm:使用QDN异构计算工具开发项目
VR用于研究人类思维与行为方式与实际情况相比存在很大的差异
中国移动扛起了5G建设大旗承担了争抢5G全球领先的重任
如何看待设计工程师的职业道路?
iPhone XR 2无敌真香:续航持久感人!
基于机器学习的隐私工具具有广泛的适用性,发现其实正在泄露隐私
阿里巴巴牵手英国电信 云计算行业万亿市场空间
年度最强拍照手机会是金立S10和OPPO R11吗
中国移动目前专注于物联网通讯芯片(NB-IoT)的研发和销售
魅族Pro7价格、配置没优势导致销量不佳,魅族MX7赶来救场,网友:又要砸手机换7了!
MAX2769 GPS参考设计
LED电动车灯升降压恒流芯片OC4000故障处理
航天器或卫星的七个基本子系统简单说明