Melis4.0[D1s]:6.mango-MQ-R基于Melis移植lvgl
文章目录
上一篇文章《Melis4.0[D1s]:5.测试笔记 - 修改显示测试源码》可以通过C代码控制显示,就可以移植lvgl。目前只移植显示部分,没有按键或者触摸输入。
1.下载lvgl源码到《D1s-Melis/ekernel/drivers/hal/test/disp2》目录
我使用的源码是https://github.com/lvgl/lv_port_pc_eclipse,克隆到 《D1s-Melis/ekernel/drivers/hal/test/disp2》 目录。然后在 《D1s-Melis/ekernel/drivers/hal/test/disp2/lv_port_pc_eclipse》 目录下建立一个Makefile,把全部的C文件都包含进来编译的。这是因为lvgl的所有非必要的C文件都可以通过宏定义配置是否编译。例如lv_bmp.c里面的代码是否编译,取决于 宏定义 LV_USE_BMP:
为了简单起见,很多非必要的组件我都没有包含进来,详情见 lv_conf.h(完整内容点击超链接) 。
1.1 修改Makefile
先在《disp2》目录下的Makefile(完整内容点击超链接)把子目录《disp2/lv_port_pc_eclipse》包含进来:
obj-y += lv_port_pc_eclipse/
再将《disp2/lv_port_pc_eclipse》目录下的Makefile(完整内容点击超链接)改为下面内容(节选):
obj-y += lv_main.o
obj-y += \
lvgl/demos/benchmark/assets/img_benchmark_cogwheel_alpha16.o \
lvgl/demos/benchmark/assets/img_benchmark_cogwheel_argb.o \
lvgl/demos/benchmark/assets/img_benchmark_cogwheel_chroma_keyed.o \
lvgl/demos/benchmark/assets/img_benchmark_cogwheel_indexed16.o \
lvgl/demos/benchmark/assets/img_benchmark_cogwheel_rgb.o \
lvgl/demos/benchmark/assets/img_benchmark_cogwheel_rgb565a8.o \
lvgl/demos/benchmark/assets/lv_font_bechmark_montserrat_12_compr_az.c.o \
lvgl/demos/benchmark/assets/lv_font_bechmark_montserrat_16_compr_az.c.o \
lvgl/demos/benchmark/assets/lv_font_bechmark_montserrat_28_compr_az.c.o \
lvgl/demos/benchmark/lv_demo_benchmark.o \
......
1.2 快速测试Makefile修改是否有效
把主函数中和硬件相关的显示,输入等初始化代码屏蔽,main改为lv_main,并把lv_main变成一个命令:
int lv_main(int argc, char **argv)
{
//(void *)argc; /*Unused*/ //(void)argv; /*Unused*/
printf("lv_main.");
#if 0
/*Initialize LVGL*/
lv_init();
/*Create a default group for keyboard navigation*/
lv_group_set_default(lv_group_create());
/*Initialize the HAL (display, input devices, tick) for LVGL*/
hal_init();
.....
#endif
return 0;
}
static lv_disp_t * hal_init(void )
{
#if 0
disp_layer_cfg_def();
static lv_disp_draw_buf_t draw_buf;
lv_disp_draw_buf_init(&draw_buf, disp_buf1, disp_buf2, HOR_RES * VER_RES);
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
......
lv_disp_drv_register(&disp_drv);
#endif
lv_disp_t * disp = NULL;
return disp;
}
FINSH_FUNCTION_EXPORT_ALIAS(lv_main, lv_main, lv_main );
编译通过,烧录测试。输入help,可以看到lv_main命令,输入lv_main,打印“lv_main”:
msh />help
RT-Thread shell commands:
......
lv_main - lv_main
......
msh />lv_main
lv_main
2.移植刷新显示内存函数dummy_flush_cb
上一篇文章《Melis4.0[D1s]:5.测试笔记 - 修改显示测试源码》的《2.disp_mem源码阅读》知道,只要往显存地址 mem = g_disp_mm[mem_id].info_base里面填写像素数据,就可以得到我们要显示的内容,把这个地址传给一个全局变量,在lvgl中使用这个全局变量即可。
于是我们在disp_mem源码所在的C文件声明一个全局变量:
uint32_t * g_p_mem_base;
把显存地址传给g_p_mem_base:
g_p_mem_base = g_disp_mm[mem_id].info_base;
有了这个地址,我们就可以编写自己的显示回调函数:
#define HOR_RES 800
#define VER_RES 480
extern uint32_t * g_p_mem_base;
#define line_length 800 * sizeof(rt_uint32_t) / 4
static void dummy_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
/*Truncate the area to the screen*/
int32_t act_x1 = area->x1 < 0 ? 0 : area->x1;
int32_t act_y1 = area->y1 < 0 ? 0 : area->y1;
int32_t act_x2 = area->x2 > (int32_t)HOR_RES - 1 ? (int32_t)HOR_RES - 1 : area->x2;
int32_t act_y2 = area->y2 > (int32_t)VER_RES - 1 ? (int32_t)VER_RES - 1 : area->y2;
lv_coord_t w = (act_x2 - act_x1 + 1);
long int location = 0;
/* 32 bit per pixel */
uint32_t *fbp32 = (uint32_t *)g_p_mem_base;
uint32_t y;
for (y = act_y1; y <= act_y2; y++)
{
location = act_x1 + y * line_length;
rt_memcpy(&fbp32[location], (uint32_t *)color_p, (act_x2 - act_x1 + 1) * 4);
color_p += w;
}
lv_disp_flush_ready(disp_drv);
}
static lv_color_t disp_buf1[HOR_RES * VER_RES];
static lv_color_t disp_buf2[HOR_RES * VER_RES];
int disp_layer_cfg_def(void);
static lv_disp_t * hal_init(void )
{
#if 1
disp_layer_cfg_def();
static lv_disp_draw_buf_t draw_buf;
lv_disp_draw_buf_init(&draw_buf, disp_buf1, disp_buf2, HOR_RES * VER_RES);
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.draw_buf = &draw_buf;
disp_drv.flush_cb = dummy_flush_cb;
disp_drv.hor_res = HOR_RES;
disp_drv.ver_res = VER_RES;
lv_disp_drv_register(&disp_drv);
#endif
lv_disp_t * disp = NULL;
return disp;
}
再make编译,通过。
3.创建一个定时器调用lvgl心跳lv_tick_inc()
Melis使用rt-thread内核,rt-thread的节拍由宏定义 CONFIG_HZ决定:
#define RT_TICK_PER_SECOND CONFIG_HZ
CONFIG_HZ通过 命令 make menuconfig 配置:
这里是200Hz,也就是一个时钟节拍为5ms。
static rt_timer_t timer1;
// lv_tick_inc(5);
static lv_disp_t * hal_init(void )
{
#if 1
/* 创建定时器1 周期定时器 */
timer1 = rt_timer_create("timer1",
lv_tick_inc, // 回调函数
5, // 回调函数的传入参数
1, // 一个时钟节拍调用一次回调函数,具体是5ms
RT_TIMER_FLAG_PERIODIC);
/* 启动定时器1 */
if (timer1 != RT_NULL)
rt_timer_start(timer1);
disp_layer_cfg_def();
......
#endif
lv_disp_t * disp = NULL;
return disp;
}
lv_timer_handler()调用间隔是10ms,而lv_tick_inc()调用间隔是5ms,这样比较合理。
4.pack打包出错:
root@SK-JNTINRTMRDZW:/home/book/D1s-Melis-master# pack
INFO: temporarily Enter pack directory: "/home/book/D1s-Melis-master/out/d1s-mq/image", will be back when terminated
INFO: copying config/boot binary/phoenix plugin files
/home/book/D1s-Melis-master/tools/phoenixplugin/Tools.fex
......
......
INFO: running the function do_finish "sys_partition_nor.bin"
partitation file Path=/home/book/D1s-Melis-master/out/d1s-mq/image/sys_partition_nor.bin
mbr_name file Path=/home/book/D1s-Melis-master/out/d1s-mq/image/sunxi_mbr_nor.fex
download_name file Path=/home/book/D1s-Melis-master/out/d1s-mq/image/dlinfo.fex
ERROR: dl file melis_pkg_nor.fex size too large
ERROR: filename = melis_pkg_nor.fex
ERROR: dl_file_size = 2272 sector
ERROR: part_size = 2048 sector
ERROR: update mbr file fail
ERROR: update_mbr failed
《melis_pkg_nor.fex》文件比分配的空间要大,装不下。
修改分区文件《D1s-Melis/projects/d1s-mq/configs/sys_partition_nor.fex》第44,45行:
;---------------------------------------------------------------------------------------------------------
; 说明: 脚本中的字符串区分大小写,用户可以修改"="后面的数值,但是不要修改前面的字符串
;---------------------------------------------------------------------------------------------------------
;--------------------------------------------------------------------------------------------------
; 固件下载参数配置
;--------------------------------------------------------------------------------------------------
;****************************************************
; mbr的大小, 以Kbyte为单位
;****************************************************
[mbr]
size = 16
;********************************************************************************************************
; 分区配置
;
;
; partition 定义范例:
; [partition] ; //表示是一个分区
; name = USERFS2 ; //分区名称
; size = 16384 ; //分区大小 单位: 扇区.分区表示个数最多2^31 * 512 = 2T
; downloadfile = "123.fex" ; //下载文件的路径和名称,可以使用相对路径,相对是指相对于image.cfg文件所在分区。也可以使用绝对路径
; keydata = 1 ; //私有数据分区,重新量产数据将不丢失
; encrypt = 1 ; //采用加密方式烧录,将提供数据加密,但损失烧录速度
; user_type = ? ; //私有用法
; verify = 1 ; //要求量产完成后校验是否正确
;
; 注:1、name唯一, 不允许同名
; 2、name最大12个字符
; 3、size = 0, 将创建一个无大小的空分区
; 4、为了安全和效率考虑,分区大小最好保证为16M字节的整数倍
;********************************************************************************************************
[partition_start]
;[partition]
; name = boot
; size = 6656
; downloadfile = "boot.fex"
; user_type = 0x8000
[partition]
name = bootA
;size = 2048
size = 4096
downloadfile = "melis_pkg_nor.fex"
user_type = 0x8000
;[partition]
; name = bootB
; size = 6144
; downloadfile = "melis_pkg_nor.fex"
; user_type = 0x8000
;[partition]
; name = env
; size = 8
; downloadfile = "env.fex"
; user_type = 0x8000
;[partition]
; name = env-redund
; size = 8
; downloadfile = "env.fex"
; user_type = 0x8000
;rootfs 7616 sector in rootfs.ini make 7616*1024/512=15232 sectors for it.
[partition]
name = ROOTFS
size = 10240
;size = 20336
downloadfile = "data_udisk.fex"
user_type = 0x8000
[partition]
name = UDISK
;size = flash size - (boot0 + mbr) size - env - env-redund - ROOTFS
;8(or 16) * 1024 * 2 - 64 * 2 - 5632 - 8 - 8 - 10240
;size = 20336
;downloadfile = "data_udisk.fex"
user_type = 0x8000
再次pack打包成功。烧录运行,输入lv_main命令:
msh />lv_main
5.设置开机启动
修改《startup.sh》(位于目录 D1s-Melis/projects/d1s-mq/data/UDISK/startup.sh):
echo "Execute startup script begin.............."
#insmod d:\mod\display.mod
#insmod d:\mod\orange.mod
#insmod d:\apps\desktop.mod
lv_main
echo "...............Execute startup script end"
6.源码下载
源码没有startup.sh 和 melis_pkg_nor.fex ,这两个文件的修改比较简单。
源码链接:https://gitee.com/huangweide001/linux-d1-h-test/tree/master/disp2
源码包含了可以直接烧录的img文件 melis_d1s-mq_uart0_8Mnor_lvgl.img 。
7.lvgl与播放视频混合显示
请阅读下一篇文章:《Melis4.0[D1s]:9.测试cedar多媒体解码库,视频和lvgl混合显示》。