君正X1600E-HALLY6开发板LVGL踩坑与开发记录

发布时间:2026/11/1 1:29:03
君正X1600E-HALLY6开发板LVGL踩坑与开发记录

参考文档:X1600 LVGL_Demo | Ingenic Docs

1.编译lvgl遇到问题,libonvif/onvif_api.h不存在

building third_party/lvgl
-------------------------
--- generate lvgl file list
.lvgl_cflags.mk .lvgl_files.mk
--- build lvgl lib
In file included from ingenic/lvgl_ingenic_support.h:10:0,
from ingenic/view/ilv_text_doing.c:8:
ingenic/ui_onvif_manager.h:10:32: fatal error: libonvif/onvif_api.h: No such file or directory
compilation terminated.

...

In file included from ingenic/lvgl_ingenic_support.h:10:0,
from lvgl/src/draw/lv_img_cache.c:15:
ingenic/ui_onvif_manager.h:10:32: fatal error: libonvif/onvif_api.h: No such file or directory
compilation terminated.

解决思路:先查sdk中有没有这个文件,文件存在说明编译没选上

ubuntu@ubuntu:~/x1600$find ./ -name onvif_api.h
./third_party/onvif/libonvif/onvif_api.h


2.编译lvgl遇到问题, error: '-mmsa'

building third_party/lvgl
-------------------------
--- generate lvgl file list
.lvgl_cflags.mk .lvgl_files.mk
--- build lvgl lib
cc1: error: '-mmsa' must be used with '-mfp64' and '-mhard-float'
...

lvgl/demos/music/lv_demo_music_main.c:1:0: error: '-mmsa' must be used with '-mfp64' and '-mhard-float'
/**
^
make[2]: *** [tools/build_elf.mk:154: .objs/lvgl/demos/music/lv_demo_music_main.c.o] Error 1
make[2]: *** [tools/build_elf.mk:154: .objs/lvgl/demos/music/lv_demo_music.c.o] Error 1
make[2]: *** [tools/build_elf.mk:154: .objs/lvgl/demos/music/assets/img_lv_demo_music_logo.c.o] Error 1
make[1]: *** [Makefile:49: all] Error 2
make: *** [Makefile:94: all] Error 2

解决办法:取消 msa 优化

3.编译成功后buildroot目录会生成liblvgl.a文件,但是没有生成头文件,要自己去源码引用

SYSROOT := /home/ubuntu/x1600/buildroot/buildroot/output/host/mipsel-buildroot-linux-gnu/sysroot
SRC_DIR := ../src
INC_DIRS := ../include $(SYSROOT)/usr/include /home/ubuntu/x1600/third_party/lvgl /home/ubuntu/x1600/third_party/lvgl/ingenic /home/ubuntu/x1600/third_party/lvgl/lvgl/src/hal/
LIB_DIRS := ../lib $(SYSROOT)/usr/lib
LIBS := hardware2 lvgl pthread utils2

4.lvgl 8显示中文开发步骤

1.下载字体库 100font.com - 免费商用字体大全 - 免费字体下载网站

2.官方在线转换字体 Font Converter — LVGL

3.编译遇到问题,是因为官网字体转换的版本太高了

I/home/ubuntu/x1600/buildroot/buildroot/output/host/mipsel-buildroot-linux-gnu/sysroot/usr/lib -c ../src/font_24.c -o build/font_24.o
../src/font_24.c:34115:5: error: unknown field 'static_bitmap' specified in initializer
.static_bitmap = 0,
^

解决办法:注释掉.static_bitmap = 0,

4.1另一种方式显示中文,资源不受限的情况下,使用ttf文件效果更好
#include "lvgl.h" lv_ft_info_t ft_info; ft_info.name = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"; ft_info.weight = 24; ft_info.style = FT_FONT_STYLE_NORMAL; if (lv_ft_font_init(&ft_info) == LV_FS_RES_OK) { lv_obj_set_style_text_font(label, ft_info.font, 0); }
5.lvlg中文键盘,8.3版本默认支持,详细使用案例参考官方文档:Pinyin IME — LVGL documentation

lv_config.h文件中打开宏定义,执行

make clean_app_module_driver

make app_module_driver

编译即可用

#define LV_USE_IME_PINYIN 1
#if LV_USE_IME_PINYIN
/*1: Use default thesaurus*/
/*If you do not use the default thesaurus, be sure to use `lv_ime_pinyin` after setting the thesauruss*/
#define LV_IME_PINYIN_USE_DEFAULT_DICT 1
/*Set the maximum number of candidate panels that can be displayed*/
/*This needs to be adjusted according to the size of the screen*/
#define LV_IME_PINYIN_CAND_TEXT_NUM 6

/*Use 9 key input(k9)*/
#define LV_IME_PINYIN_USE_K9_MODE 1
#if LV_IME_PINYIN_USE_K9_MODE == 1
#define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3
#endif // LV_IME_PINYIN_USE_K9_MODE
#endif

如果提示:

/home/ubuntu/x1600/my_app/src/../src/lv_ui.c:74: undefined reference to `lv_ime_pinyin_create'
build/lv_ui.o: In function `lv_example_ime_pinyin_1':
/home/ubuntu/x1600/my_app/src/../src/lv_ui.c:231: undefined reference to `lv_ime_pinyin_create'
/home/ubuntu/x1600/my_app/src/../src/lv_ui.c:243: undefined reference to `lv_ime_pinyin_set_keyboard'
/home/ubuntu/x1600/my_app/src/../src/lv_ui.c:249: undefined reference to `lv_ime_pinyin_get_cand_panel'
collect2: error: ld returned 1 exit status
make: *** [Makefile:60: bin/myapp] Error 1

需要选一个demo编译

6.如果使用GUI-Guider图形化软件快速开发,使用中文键盘可能遇到的问题,中文候选框无法显示,原因是候选框依赖于父对象的实际布局。
解决办法:先加载当前界面lv_scr_load(ui->screen_test); 再去绑定拼音键盘到当前界面。
实际修改过后的参考代码:
/* * Copyright 2026 NXP * NXP Proprietary. This software is owned or controlled by NXP and may only be used strictly in * accordance with the applicable license terms. By expressly accepting such terms or by downloading, installing, * activating and/or otherwise using the software, you are agreeing that you have read, and that you agree to * comply with and are bound by, such license terms. If you do not agree to be bound by the applicable license * terms, then you may not retain, install, activate or otherwise use the software. */ #include "lvgl.h" #include <stdio.h> #include "gui_guider.h" #include "events_init.h" #include "widgets_init.h" #include "custom.h" #if 1 static lv_obj_t * g_cand_panel = NULL; static lv_obj_t * g_kb = NULL; static lv_obj_t * g_ta = NULL; // 文本框引用 // 关闭键盘的辅助函数 static void close_keyboard(void) { if(g_kb && !lv_obj_has_flag(g_kb, LV_OBJ_FLAG_HIDDEN)) { lv_obj_add_flag(g_kb, LV_OBJ_FLAG_HIDDEN); if(g_cand_panel) lv_obj_add_flag(g_cand_panel, LV_OBJ_FLAG_HIDDEN); if(g_ta) { lv_obj_clear_state(g_ta, LV_STATE_FOCUSED); lv_indev_reset(NULL, g_ta); } } } // 打开键盘的辅助函数 static void open_keyboard(lv_obj_t * ta) { if(g_kb && lv_obj_has_flag(g_kb, LV_OBJ_FLAG_HIDDEN)) { lv_keyboard_set_textarea(g_kb, ta); lv_obj_clear_flag(g_kb, LV_OBJ_FLAG_HIDDEN); // 关键:移到最前面 lv_obj_move_foreground(g_kb); if(g_cand_panel) { lv_obj_clear_flag(g_cand_panel, LV_OBJ_FLAG_HIDDEN); lv_obj_move_foreground(g_cand_panel); } } } static void ta_event_cb1(lv_event_t * e) { lv_event_code_t code = lv_event_get_code(e); lv_obj_t * ta = lv_event_get_target(e); if(code == LV_EVENT_CLICKED) { open_keyboard(ta); } else if(code == LV_EVENT_CANCEL) { close_keyboard(); // 点击OK关闭 } } // 辅助函数:检查child是否是parent的子对象 static bool obj_is_child_of(lv_obj_t * child, lv_obj_t * parent) { if(!child || !parent) return false; lv_obj_t * p = lv_obj_get_parent(child); while(p) { if(p == parent) return true; p = lv_obj_get_parent(p); } return false; } // 屏幕点击事件:点击空白处关闭键盘 static void screen_event_cb(lv_event_t * e) { lv_obj_t * screen = lv_event_get_target(e); lv_indev_t * indev = lv_event_get_indev(e); lv_point_t vect; lv_indev_get_vect(indev, &vect); // 获取点击位置的对象 lv_obj_t * hit = lv_indev_get_obj_act(); // 如果点击的不是键盘、候选面板、文本框,则关闭键盘 if(hit != g_ta && hit != g_kb && hit != g_cand_panel && !obj_is_child_of(hit, g_kb) && !obj_is_child_of(hit, g_cand_panel)) { close_keyboard(); } } // 纯拼音键盘,无模式切换,无大写 static const char * pinyin_kb_map[] = { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "\n", "a", "s", "d", "f", "g", "h", "j", "k", "l", "\n", "z", "x", "c", "v", "b", "n", "m", LV_SYMBOL_BACKSPACE, "\n", ",", " ", ".", LV_SYMBOL_OK, "" }; static const lv_btnmatrix_ctrl_t pinyin_kb_ctrl[] = { // 第1行:10个 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 第2行:10个(9个按键+\n) 4, 4, 4, 4, 4, 4, 4, 4, 4, // 第3行:9个(8个按键+\n) 4, 4, 4, 4, 4, 4, 4, 6, // 第4行:6个(5个按键+结束符"") 4, 6, 4 ,6, 0 }; void setup_scr_screen_z_test(lv_ui *ui) { ui->screen_test = lv_obj_create(NULL); lv_obj_set_size(ui->screen_test, 480, 480); lv_obj_set_style_bg_color(ui->screen_test, lv_color_hex(0x183966), 0); lv_scr_load(ui->screen_test); // 为屏幕添加点击事件(点击空白处关闭键盘) lv_obj_add_event_cb(ui->screen_test, screen_event_cb, LV_EVENT_CLICKED, NULL); // 创建拼音输入法 lv_obj_t * pinyin_ime = lv_ime_pinyin_create(ui->screen_test); lv_obj_set_style_text_font(pinyin_ime, &lv_font_simsun_16_cjk, 0); lv_ime_pinyin_set_mode(pinyin_ime, LV_IME_PINYIN_MODE_K26); // 创建文本输入区域 lv_obj_t * ta1 = lv_textarea_create(ui->screen_test); g_ta = ta1; lv_textarea_set_one_line(ta1, true); lv_textarea_set_placeholder_text(ta1, "..."); lv_obj_set_style_text_font(ta1, &lv_font_simsun_16_cjk, 0); lv_obj_set_size(ta1, 440, 50); lv_obj_align(ta1, LV_ALIGN_TOP_MID, 0, 20); lv_obj_set_style_border_width(ta1, 2, 0); lv_obj_set_style_border_color(ta1, lv_color_hex(0x00aaff), 0); // 创建键盘 lv_obj_t * kb = lv_keyboard_create(ui->screen_test); g_kb = kb; lv_obj_set_size(kb, 460, 220); lv_obj_align(kb, LV_ALIGN_BOTTOM_MID, 0, -10); // // 在 setup 中使用自定义映射 lv_keyboard_set_map(kb, LV_KEYBOARD_MODE_TEXT_LOWER, pinyin_kb_map, pinyin_kb_ctrl); lv_ime_pinyin_set_keyboard(pinyin_ime, kb); lv_keyboard_set_textarea(kb, ta1); // 文本框事件 lv_obj_add_event_cb(ta1, ta_event_cb1, LV_EVENT_CLICKED, NULL); lv_obj_add_event_cb(ta1, ta_event_cb1, LV_EVENT_CANCEL, NULL); // 候选面板 lv_obj_t * cand_panel = lv_ime_pinyin_get_cand_panel(pinyin_ime); g_cand_panel = cand_panel; lv_obj_set_size(cand_panel, 460, 50); lv_obj_align_to(cand_panel, kb, LV_ALIGN_OUT_TOP_MID, 0, -10); lv_obj_set_style_bg_color(cand_panel, lv_color_hex(0xf5f5f5), 0); lv_obj_set_style_bg_opa(cand_panel, LV_OPA_COVER, 0); lv_obj_set_style_text_font(cand_panel, &lv_font_simsun_16_cjk, 0); lv_obj_set_style_text_font(cand_panel, &lv_font_simsun_16_cjk, LV_PART_ITEMS); // 初始隐藏 lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN); lv_obj_add_flag(cand_panel, LV_OBJ_FLAG_HIDDEN); } #endif
7.lvgl监听屏幕触摸事件,刷新亮屏时间,实现点击亮屏

cd /home/ubuntu/x1600/third_party/lvgl

code ./

找到下面这个函数,添加一个全局变量

应用层声明后直接使用

8.X轴或Y轴坐标重复,导致应用层显示同一个坐标点,因lvgl移植适配问题引起。

现象:第三个坐标数据,驱动层坐标数据为【337,203】,应用层lvgl坐标为【117,203】,evtest测试发现x轴上报的337,y轴坐标因重复未上报。

驱动log:
[ 629.422889] [ST]sitronix_ts_pen_down touch[0] DOWN x=337 y=198
[ 629.448708] [ST]sitronix_ts_pen_up ----------------------------
[ 629.734854] [ST]sitronix_ts_pen_down touch[0] DOWN x=117 y=203
[ 629.870053] [ST]sitronix_ts_pen_up ----------------------------
[ 630.173066] [ST]sitronix_ts_pen_down touch[0] DOWN x=337 y=203
[ 630.274557] [ST]sitronix_ts_pen_up ----------------------------


lvgl源码log:
x:337 y:198 state:1
x:337 y:198 state:0
x:117 y:203 state:1
x:117 y:203 state:0
x:117 y:203 state:1
x:117 y:203 state:0

evtest log:
Event: time 1793436957.891393, -------------- SYN_REPORT ------------
Event: time 1793436958.177591, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 218
Event: time 1793436958.177591, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 337
Event: time 1793436958.177591, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 198
Event: time 1793436958.177591, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 1
Event: time 1793436958.177591, type 3 (EV_ABS), code 58 (ABS_MT_PRESSURE), value 255
Event: time 1793436958.177591, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1793436958.177591, -------------- SYN_REPORT ------------
Event: time 1793436958.262194, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value -1
Event: time 1793436958.262194, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 0
Event: time 1793436958.262194, type 3 (EV_ABS), code 58 (ABS_MT_PRESSURE), value 0
Event: time 1793436958.262194, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 0
Event: time 1793436958.262194, -------------- SYN_REPORT ------------
Event: time 1793436958.548331, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 219
Event: time 1793436958.548331, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 117
Event: time 1793436958.548331, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 203
Event: time 1793436958.548331, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 1
Event: time 1793436958.548331, type 3 (EV_ABS), code 58 (ABS_MT_PRESSURE), value 255
Event: time 1793436958.548331, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1793436958.548331, -------------- SYN_REPORT ------------
Event: time 1793436958.683538, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value -1
Event: time 1793436958.683538, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 0
Event: time 1793436958.683538, type 3 (EV_ABS), code 58 (ABS_MT_PRESSURE), value 0
Event: time 1793436958.683538, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 0
Event: time 1793436958.683538, -------------- SYN_REPORT ------------
Event: time 1793436958.986537, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 220
Event: time 1793436958.986537, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 337
Event: time 1793436958.986537, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 1
Event: time 1793436958.986537, type 3 (EV_ABS), code 58 (ABS_MT_PRESSURE), value 255
Event: time 1793436958.986537, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
Event: time 1793436958.986537, -------------- SYN_REPORT ------------
Event: time 1793436959.088045, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value -1
Event: time 1793436959.088045, type 3 (EV_ABS), code 48 (ABS_MT_TOUCH_MAJOR), value 0
Event: time 1793436959.088045, type 3 (EV_ABS), code 58 (ABS_MT_PRESSURE), value 0
Event: time 1793436959.088045, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 0
Event: time 1793436959.088045, -------------- SYN_REPORT ------------

修复方法:

static int read_input_event(struct tp_input_reader *reader) { struct input_event event; int ret; int report = 0; int x = -1, y = -1; int next = 0; int fds_cnt = reader->fds_cnt; struct pollfd pollfd[fds_cnt]; for (int i = 0; i < fds_cnt; i++) { pollfd[i].fd = reader->fds[i]; pollfd[i].events = POLLIN; pollfd[i].revents = 0; } ret = poll(pollfd, fds_cnt, 0); if (ret <= 0) return 0; int r_fd = 0; for (int i = 0; i < fds_cnt; i++) { if (pollfd[i].revents == POLLIN) { r_fd = pollfd[i].fd; break; } } if (!r_fd) return 0; next = 1; //原实现代码 // while (!report) { // read(r_fd, &event, sizeof(struct input_event)); // switch (event.type) { // case EV_KEY: // if (event.code == BTN_TOUCH) { // if (event.value == 0) // reader->is_press = 0; // else // reader->is_press = 1; // } // break; // case EV_ABS: // if (event.code == ABS_MT_POSITION_X || event.code == ABS_X) // x = event.value; // if (event.code == ABS_MT_POSITION_Y || event.code == ABS_Y) // y = event.value; // break; // case EV_SYN: // report = 1; // if (x >= 0 && y >= 0) { // reader->x = x; // reader->y = y; // } // break; // default: // break; // } // } //优化后代码 while (!report) { read(r_fd, &event, sizeof(struct input_event)); switch (event.type) { case EV_KEY: if (event.code == BTN_TOUCH) { if (event.value == 0) reader->is_press = 0; else reader->is_press = 1; } break; case EV_ABS: if (event.code == ABS_MT_POSITION_X || event.code == ABS_X) reader->x = event.value; if (event.code == ABS_MT_POSITION_Y || event.code == ABS_Y) reader->y = event.value; break; case EV_SYN: report = 1; break; default: break; } } return next; }