IMX6ULL开发板移植LVGL v9
基于韦东山的IMX6ULL Pro开发板,使用framebuffer
准备材料
IMX6ULL Pro开发板 7寸触摸屏
Cmake V3.12.4以上的版本
arm gcc交叉编译环境 arm-buildroot-linux-gnueabihf-gcc (Ubuntu18.04)
lvgl v9源码
移植
克隆lv_port_linux仓库并安装lvgl子模块
# 克隆lv_port_linux仓库并安装lvgl子模块
git clone https://github.com/lvgl/lv_port_linux.git
cd lv_port_linux_frame_buffer/
git submodule update --init --recursive
修改l
v_port_linux_frame_buffer
根目录的CMakeLists.txt文件
cmake_minimum_required(VERSION 3.10)
# 设置交叉编译
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
# 设置编译器的路径,必须是绝对路径
set(CMAKE_C_COMPILER /home/lucas/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/arm-buildroot-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER /home/lucas/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/arm-buildroot-linux-gnueabihf-g++)
project(lvgl)
set(CMAKE_C_STANDARD 99)#C99 # lvgl officially support C99 and above
set(CMAKE_CXX_STANDARD 17)#C17
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
add_subdirectory(lvgl)
target_include_directories(lvgl PUBLIC ${PROJECT_SOURCE_DIR})
add_executable(main main.c mouse_cursor_icon.c)
#include(${CMAKE_CURRENT_LIST_DIR}/lvgl/tests/FindLibDRM.cmake)
#include_directories(${Libdrm_INCLUDE_DIRS})
#find_package(SDL2)
#find_package(SDL2_image)
#include_directories(${SDL2_INCLUDE_DIRS} ${SDL2_IMAGE_INCLUDE_DIRS})
target_link_libraries(main lvgl lvgl::examples lvgl::demos lvgl::thorvg ${SDL2_LIBRARIES} ${SDL2_IMAGE_LIBRARIES} ${Libdrm_LIBRARIES} m pthread)
add_custom_target (run COMMAND ${EXECUTABLE_OUTPUT_PATH}/main DEPENDS main)
修改
lv_conf.h
// 屏幕色深
#define LV_COLOR_DEPTH 32
// 14毫秒刷新一次
#define LV_DEF_REFR_PERIOD 14
// 建议关闭
#define LV_USE_ASSERT_STYLE 0
#define LV_USE_ASSERT_MEM_INTEGRITY 0
#define LV_USE_ASSERT_OBJ 0
// 对象样式缓存默认0,设置20
#define LV_OBJ_STYLE_CACHE 20
// 显示帧率和cpu使用情况
#define LV_USE_PERF_MONITOR 1
#define LV_USE_MEM_MONITOR 1
// 开启framebuffer,确保这一项是开启的,如果要使用DRM驱动,配置LV_USE_LINUX_DRM 1
#define LV_USE_LINUX_FBDEV 1
// 开启输入设备驱动
#define LV_USE_EVDEV 1
修改
mian.c
#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"
#include "lvgl/examples/lv_examples.h"
#include <src/core/lv_obj_pos.h>
#include <src/lv_api_map_v8.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
static const char * getenv_default(const char * name, const char * dflt)
{
return getenv(name) ?: dflt;
}
#if LV_USE_LINUX_FBDEV
static void lv_linux_disp_init(void)
{
// framebuffer默认为/dev/fb0
const char * device = getenv_default("LV_LINUX_FBDEV_DEVICE", "/dev/fb0");
lv_display_t * disp = lv_linux_fbdev_create();
lv_linux_fbdev_set_file(disp, device);
}
#elif LV_USE_LINUX_DRM
static void lv_linux_disp_init(void)
{
const char * device = getenv_default("LV_LINUX_DRM_CARD", "/dev/dri/card0");
lv_display_t * disp = lv_linux_drm_create();
lv_linux_drm_set_file(disp, device, -1);
}
#elif LV_USE_SDL
static void lv_linux_disp_init(void)
{
const int width = atoi(getenv("LV_SDL_VIDEO_WIDTH") ?: "800");
const int height = atoi(getenv("LV_SDL_VIDEO_HEIGHT") ?: "480");
lv_sdl_window_create(width, height);
}
#else
#error Unsupported configuration
#endif
static int led_fd;
typedef struct
{
bool status;
// 可以添加更多自定义变量
} custom_data_t;
static void event_handler(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * obj = lv_event_get_target(e);
char led_status;
if(code == LV_EVENT_CLICKED) {
LV_LOG_USER("Clicked");
custom_data_t * retrieved_data = (custom_data_t *)lv_obj_get_user_data(obj);
led_fd = open("/dev/bsp_led", O_RDWR);
if(led_fd == -1) {
LV_LOG_USER("can not open led_drv");
}
if(retrieved_data->status) {
led_status = 0;
} else {
led_status = 1;
}
write(led_fd, &led_status, 1);
retrieved_data->status = led_status;
lv_obj_set_user_data(obj, retrieved_data);
close(led_fd);
printf("LV_EVENT_CLICKED");
}
}
void user_demo()
{
lv_obj_t * led_btn = lv_button_create(lv_screen_active());
lv_obj_set_size(led_btn, 60, 48);
lv_obj_center(led_btn);
lv_obj_add_event_cb(led_btn, event_handler, LV_EVENT_ALL, NULL);
custom_data_t * data = malloc(sizeof(custom_data_t));
data->status = false;
lv_obj_set_user_data(led_btn, data);
lv_obj_t * label = lv_label_create(led_btn);
lv_label_set_text(label, "LED");
lv_obj_center(label);
}
int main(void)
{
lv_init();
/*Linux display device init*/
lv_linux_disp_init();
// 触摸 可以使用hexdump /dev/input/eventx命令检查触摸是那个设备文件
lv_indev_t * indev = lv_evdev_create(LV_INDEV_TYPE_POINTER, "/dev/input/event1");
/*Create a Demo*/
lv_demo_music();
/*Handle LVGL tasks*/
while(1) {
lv_timer_handler();
usleep(5000);
}
return 0;
}
编译
mkdir build
cd build
cmake ..
make -j
可执行文件为bin
目录下的main
拷贝到开发板并运行
挂载网络文件系统
mount -t nfs -o nolock,vers=3 192.168.5.11:/home/lucas/nfs_rootfs /mnt
运行
./main
开机自动运行lvgl
编写启动脚本
#!/bin/sh
#
# Start lvgl....
#
start() {
printf "Starting lvgl: "
echo -n -e '\e[?17;14;224c'
echo 0 > /sys/class/graphics/fbcon/cursor_blink
echo -e "\033[9;0]" > /dev/tty0
start-stop-daemon -S -q -m -b -p /var/run/lvgl.pid \
-x /usr/lvgl/main
[ $? = 0 ] && echo "OK" || echo "FAIL"
}
stop() {
printf "Stopping lvgl: "
start-stop-daemon -K -q -p /var/run/lvgl.pid \
-x /usr/lvgl/main
[ $? = 0 ] && echo "OK" || echo "FAIL"
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart|reload)
stop
start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
评论区