1. 概述本篇主要是記錄將LVGL移植到百問網(wǎng)STM32MP157開發(fā)板上,并且僅是跑一下LVGL的一些例程。 2. 軟件平臺(tái) 本次使用的是Ubuntu18.04,是由百問網(wǎng)提供的,并且是按照他們的手冊(cè)搭建好了交叉編譯環(huán)境,花了一點(diǎn)時(shí)間將Linux內(nèi)核編譯好之后才進(jìn)行的LVGL移植,本次移植必須搭建好嵌入式Linux的交叉編譯環(huán)境且內(nèi)核也必須編譯好,否則無法完成移植。 3. 移植所需要的資源 本次實(shí)驗(yàn)是從LVGL的官方倉(cāng)庫(kù),移植了三個(gè)倉(cāng)庫(kù): 名稱 | 倉(cāng)庫(kù)地址 | 描述 | lvgl | https://github.com/lvgl/lvgl.git | 包含了LVGL圖形界面控件的源碼以及少量例程 | lv_drivers | https://github.com/lvgl/lv_drivers.git | 包含了驅(qū)動(dòng)LVGL圖形界面的驅(qū)動(dòng)接口源代碼 | lv_demos | https://github.com/lvgl/lv_demos.git | LVGL的例程 | lv_port_linux_frame_buffer | https://github.com/lvgl/lv_port_linux_frame_buffer.git | 適配有frame buffer的linux系統(tǒng)的接口 |
4. 移植步驟4.1 移植文件首先在根目錄創(chuàng)建一個(gè)文件夾用以存放官方的源碼: book@100ask:~$ mkdir lvgl book@100ask:~$ cd lvgl
然后使用git命令,將前面提到的倉(cāng)庫(kù)克隆到本地: book@100ask:~/lvgl$ git clone https://github.com/lvgl/lvgl.git book@100ask:~/lvgl$ git clone https://github.com/lvgl/lv_drivers.git book@100ask:~/lvgl$ git clone https://github.com/lvgl/lv_demos.git book@100ask:~/lvgl$ git clone https://github.com/lvgl/lv_port_linux_frame_buffer.git
因?yàn)閭}(cāng)庫(kù)是在github上的,克隆可能會(huì)失敗,多嘗試幾次。如果幾個(gè)倉(cāng)庫(kù)都克隆成功了,那么在lvgl下用ls命令檢查就能看到如下結(jié)果: book@100ask:~/lvgl$ ls lv_demos lv_drivers lvgl lv_port_linux_frame_buffer
然后再去根目錄下創(chuàng)建一個(gè)工作空間,在工作空間內(nèi)創(chuàng)建一個(gè)lvgl的工程,我將其取名叫做lvgl_demo: book@100ask:~/lvgl$ cd book@100ask:~$ mkdir workspace book@100ask:~$ cd workspace book@100ask:~/workspace$ mkdir lvgl_demo book@100ask:~/workspace$ cd lvgl_demo
將根目錄下的lvgl文件夾中的lvgl、lv_drivers和lv_port_linux_frame_buffer中的main.c與Makefile復(fù)制到lvgl_demo中: book@100ask:~/workspace/lvgl_demo$ cp -r ~/lvgl/lvgl ./ book@100ask:~/workspace/lvgl_demo$ cp -r ~/lvgl/lv_drivers ./ book@100ask:~/workspace/lvgl_demo$ cp ~/lvgl/lv_port_linux_frame_buffer/main.c ./ book@100ask:~/workspace/lvgl_demo$ cp ~/lvgl/lv_port_linux_frame_buffer/Makefile ./ book@100ask:~/workspace/lvgl_demo$ ls -l total 16 drwxrwxr-x 11 book book 4096 Jun 21 03:07 lv_drivers drwxrwxr-x 11 book book 4096 Jun 21 03:07 lvgl -rw-rw-r-- 1 book book 2350 Jun 21 03:07 main.c -rw-rw-r-- 1 book book 1812 Jun 21 03:07 Makefile
將lvgl中的lv_conf_template.h復(fù)制出來并且改名位lv_conf.h: book@100ask:~/workspace/lvgl_demo$ cp lvgl/lv_conf_template.h lv_conf.h
將lv_drivers中的lv_drv_conf_template.h復(fù)制出來并且改名為lv_drv_conf.h: book@100ask:~/workspace/lvgl_demo$ cp lv_drivers/lv_drv_conf_template.h lv_drv_conf.
這樣,我們的lvgl_demo的工程目錄有如下的文件: book@100ask:~/workspace/lvgl_demo$ ls -l total 60 -rw-rw-r-- 1 book book 24733 Jun 21 03:08 lv_conf.h drwxrwxr-x 11 book book 4096 Jun 21 03:07 lv_drivers -rw-rw-r-- 1 book book 14940 Jun 21 03:10 lv_drv_conf.h drwxrwxr-x 11 book book 4096 Jun 21 03:07 lvgl -rw-rw-r-- 1 book book 2350 Jun 21 03:07 main.c -rw-rw-r-- 1 book book 1812 Jun 21 03:07 Makefile
4.2 修改配置文件 修改這個(gè)文件的目的主要是為了使用linux下的frame buffer輸出顯示以及觸控輸入,需要將第11行的#if 0改成#if 1: book@100ask:~/workspace/lvgl_demo$ vim lv_drv_conf.h
如果在vim中顯示文本的行數(shù),只需要按下鍵盤上的ESC鍵,然后輸入:set nu 就能顯示行數(shù)了,先講第11行的改成#if 1 ,要編輯需要進(jìn)入編輯模式,如果當(dāng)前不是編輯模式,就按鍵盤上的i 鍵進(jìn)入編輯模式:
10 /* clang-format off */ 11 #if 1 /*Set it to "1" to enable the content*/
然后318~324行,將USE_FBDEV 的值改為1,使能frame buffer設(shè)備: 315 /*----------------------------------------- 316 * Linux frame buffer device (/dev/fbx) 317 *-----------------------------------------*/ 318 #ifndef USE_FBDEV 319 # define USE_FBDEV 1 320 #endif 321 322 #if USE_FBDEV 323 # define FBDEV_PATH "/dev/fb0" 324 #endif
接著是441~461行,將USE_EVDEV 使能,并且觸控輸入設(shè)備的名稱要根據(jù)自己的板子實(shí)際情況更改: 438 /*------------------------------------------------- 439 * Mouse or touchpad as evdev interface (for Linux based systems) 440 *------------------------------------------------*/ 441 #ifndef USE_EVDEV 442 # define USE_EVDEV 1 443 #endif 444 445 #ifndef USE_BSD_EVDEV 446 # define USE_BSD_EVDEV 0 447 #endif 448 449 #if USE_EVDEV || USE_BSD_EVDEV 450 # define EVDEV_NAME "/dev/input/event0" /*You can use the "evtest" Linux tool to get the list of devices and test them*/ 451 # define EVDEV_SWAP_AXES 0 /*Swap the x and y axes of the touchscreen*/ 452 453 # define EVDEV_CALIBRATE 0 /*Scale and offset the touchscreen coordinates by using maximum and minimum values for each axis*/ 454 455 # if EVDEV_CALIBRATE 456 # define EVDEV_HOR_MIN 0 /*to invert axis swap EVDEV_XXX_MIN by EVDEV_XXX_MAX*/ 457 # define EVDEV_HOR_MAX 4096 /*"evtest" Linux tool can help to get the correct calibraion values>*/ 458 # define EVDEV_VER_MIN 0 459 # define EVDEV_VER_MAX 4096 460 # endif /*EVDEV_CALIBRATE*/ 461 #endif /*USE_EVDEV*/
其它的地方暫時(shí)不用修改,然后按ESC退出編輯模式,輸入:wq 保存退出。 和lv_drv_conf.h 一樣需要將一開始的#if 0 改成#if 1 : 14 /* clang-format off */ 15 #if 1 /*Set it to "1" to enable content*/
接著是49~67行修改顯存大小,可以使能LV_MEM_CUSTOM 自己分配也可以自動(dòng)分配,我選擇的是自己分配顯存: 48 /*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/ 49 #define LV_MEM_CUSTOM 1 50 #if LV_MEM_CUSTOM == 0 51 /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/ 52 #define LV_MEM_SIZE (10 * 1024U * 1024U) /*[bytes]*/ 53 54 /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/ 55 #define LV_MEM_ADR 0 /*0: unused*/ 56 /*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/ 57 #if LV_MEM_ADR == 0 58 #undef LV_MEM_POOL_INCLUDE 59 #undef LV_MEM_POOL_ALLOC 60 #endif 61 62 #else /*LV_MEM_CUSTOM*/ 63 #define LV_MEM_CUSTOM_INCLUDE <stdlib.h> /*Header for the dynamic memory function*/ 64 #define LV_MEM_CUSTOM_ALLOC malloc 65 #define LV_MEM_CUSTOM_FREE free 66 #define LV_MEM_CUSTOM_REALLOC realloc 67 #endif /*LV_MEM_CUSTOM*/
隨后是刷新時(shí)間,鑒于處理器的運(yùn)算能力可以自己調(diào)整,像我這原本是30ms,都被我調(diào)整成了10ms: 80 /*Default display refresh period. LVG will redraw changed areas with this period time*/ 81 #define LV_DISP_DEF_REFR_PERIOD 10 /*[ms]*/ 82 83 /*Input device read period in milliseconds*/ 84 #define LV_INDEV_DEF_READ_PERIOD 10 /*[ms]*/
最后是比較關(guān)鍵的一個(gè)設(shè)置,TICK的配置,我們選擇自己定義一個(gè)Tick定時(shí)器配置函數(shù),在自己的應(yīng)用程序中實(shí)現(xiàn): /* 原本的 */ 86 /*Use a custom tick source that tells the elapsed time in milliseconds. 87 *It removes the need to manually update the tick with `lv_tick_inc()`)*/ 88 #define LV_TICK_CUSTOM 0 89 #if LV_TICK_CUSTOM 90 #define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ 91 #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ 92 #endif /*LV_TICK_CUSTOM*/ /* 改為 */ 86 /*Use a custom tick source that tells the elapsed time in milliseconds. 87 *It removes the need to manually update the tick with `lv_tick_inc()`)*/ 88 #define LV_TICK_CUSTOM 1 89 #if LV_TICK_CUSTOM 90 #define LV_TICK_CUSTOM_INCLUDE <stdint.h> /*Header for the system time function*/ 91 #define LV_TICK_CUSTOM_SYS_TIME_EXPR (custom_tick_get()) /*Expression evaluating to current system time in ms*/ 92 #endif /*LV_TICK_CUSTOM*/
我們現(xiàn)在是移植lvgl官方的模板,所以直接跑一下他們的例程,去706行將widget例程使能: 705 /*Show some widget. It might be required to increase `LV_MEM_SIZE` */ 706 #define LV_USE_DEMO_WIDGETS 1 707 #if LV_USE_DEMO_WIDGETS 708 #define LV_DEMO_WIDGETS_SLIDESHOW 0 709 #endif
然后保存退出。 4.3 修改main.c 我們沒有將lvgl的demos移植到工程文件中,所以需要將第2行的demos頭文件注釋掉: 2 // #include "lvgl/demos/lv_demos.h"
我們還需要根據(jù)自己使用的屏幕修改分辨率: 32 disp_drv.hor_res = 1024; // 原來是800 33 disp_drv.ver_res = 600; // 原來是480
另外我們也沒有移植原本的鼠標(biāo)樣式,所以也需要注釋掉: 46 /*Set a cursor for the mouse*/ 47 // LV_IMG_DECLARE(mouse_cursor_icon); 48 // lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); /*Create an image object for the cursor */ 49 // lv_img_set_src(cursor_obj, &mouse_cursor_icon); /*Set the image source*/ 50 // lv_indev_set_cursor(mouse_indev, cursor_obj); /*Connect the image object to the driver*/
然后保存退出。 4.4 修改Makefile 在Makefile中需要指定編譯器,如果不知道自己的交叉編譯是什么,可以在命令行輸入echo $CROSS_COMPILE 查看: book@100ask:~/workspace/lvgl_demo$ echo $CROSS_COMPILE arm-buildroot-linux-gnueabihf-
可以看到我當(dāng)前環(huán)境使用的是arm-buildroot-linux-gnueabihf-gcc ,如果你沒有得到這個(gè)結(jié)果,說明你的交叉編譯環(huán)境沒有設(shè)置好,需要去看百問網(wǎng)的手冊(cè)學(xué)習(xí)如何構(gòu)建好交叉編譯環(huán)境。 我們將Makefile中的CC ?= gcc 修改成我們自己的編譯鏈: 4 #CC ?= gcc 5 CC = arm-buildroot-linux-gnueabihf-gcc
因?yàn)槲覀儧]有移植鼠標(biāo)樣式,所以需要將鼠標(biāo)樣式的連接源文件注釋掉: 19 #CSRCS +=$(LVGL_DIR)/mouse_cursor_icon.c
然后保存退出。 4.5 編譯和運(yùn)行 在命令行輸入make 編譯工程,如果有報(bào)錯(cuò)信息,仔細(xì)看提示,不明白的可以百度或者留言交流。 編譯完成后,會(huì)在工程目錄生成一個(gè)可執(zhí)行文件demo ,我們需要將這個(gè)文件copy到開發(fā)板上,我使用的是網(wǎng)絡(luò)掛載方式(不明白的可以去看百問網(wǎng)的完全開發(fā)手冊(cè)V4.0版本)。在開發(fā)板上將開發(fā)板的mnt 目錄掛載到虛擬機(jī)的nfs_rootfs 目錄: [root@100ask:~]# mount -t nfs -o nolock,vers=3 192.168.3.14:/home/book/nfs_rootfs /mnt
然后去虛擬機(jī)那邊將demo 復(fù)制到虛擬機(jī)的nfs_rootfs 目錄: book@100ask:~/workspace/lvgl_demo$ cp demo ~/nfs_rootfs/
這樣在開發(fā)板的mnt 目錄也會(huì)有這個(gè)文件了: [root@100ask:~]# ls /mnt demo lib stm32mp157c-100ask-512d-v1.dtb uImage
我們將mnt 目錄下的demo 文件復(fù)制到本地: [root@100ask:~]# cp /mnt/demo ./ [root@100ask:~]# ls demo
然后執(zhí)行這個(gè)文件: 就可以看到在開發(fā)板上的屏幕顯示了LVGL的widget例程: 


至此LVGL在嵌入式開發(fā)板(百問網(wǎng)STM32MP157)上的簡(jiǎn)單移植應(yīng)用就完成了。
|