> 文章列表 > Melis4.0[D1s]:6.mango-MQ-R基于Melis移植lvgl

Melis4.0[D1s]:6.mango-MQ-R基于Melis移植lvgl

Melis4.0[D1s]:6.mango-MQ-R基于Melis移植lvgl

文章目录

  • 1.下载lvgl源码到《D1s-Melis/ekernel/drivers/hal/test/disp2》目录
    • 1.1 修改Makefile
    • 1.2 快速测试Makefile修改是否有效
  • 2.移植刷新显示内存函数dummy_flush_cb
  • 3.创建一个定时器调用lvgl心跳lv_tick_inc()
  • 4.pack打包出错:
  • 5.设置开机启动
  • 6.源码下载

上一篇文章《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
Melis4.0[D1s]:6.mango-MQ-R基于Melis移植lvgl
为了简单起见,很多非必要的组件我都没有包含进来,详情见 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.oobj-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();
.....
#endifreturn 0;
}
static lv_disp_t * hal_init(void  )
{
#if 0disp_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);
#endiflv_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;

Melis4.0[D1s]:6.mango-MQ-R基于Melis移植lvgl
有了这个地址,我们就可以编写自己的显示回调函数:
Melis4.0[D1s]:6.mango-MQ-R基于Melis移植lvgl

#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 1disp_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);
#endiflv_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 配置:
Melis4.0[D1s]:6.mango-MQ-R基于Melis移植lvgl
这里是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,	//	一个时钟节拍调用一次回调函数,具体是5msRT_TIMER_FLAG_PERIODIC);/* 启动定时器1 */if (timer1 != RT_NULL)rt_timer_start(timer1);disp_layer_cfg_def();......
#endiflv_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.fexERROR: 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行:
Melis4.0[D1s]:6.mango-MQ-R基于Melis移植lvgl

;---------------------------------------------------------------------------------------------------------
; 说明: 脚本中的字符串区分大小写,用户可以修改"="后面的数值,但是不要修改前面的字符串
;---------------------------------------------------------------------------------------------------------;--------------------------------------------------------------------------------------------------
;                                   固件下载参数配置
;--------------------------------------------------------------------------------------------------
;****************************************************
;    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         = 2048size         = 4096downloadfile = "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         = ROOTFSsize         = 10240;size         = 20336downloadfile = "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.shmelis_pkg_nor.fex ,这两个文件的修改比较简单。
源码链接:https://gitee.com/huangweide001/linux-d1-h-test/tree/master/disp2
源码包含了可以直接烧录的img文件 melis_d1s-mq_uart0_8Mnor_lvgl.img