From 80686e6bc4cb17e9d856647084725203fa63ebe6 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Mon, 19 Aug 2024 16:47:42 +0800
Subject: [PATCH] Add LCD API examples
---
hal/lcd/lvgl/lvgl_demo.c | 91 ++++
hal/lcd/lvgl/libs_lvgl/patches/lv_drivers-8.0.1-imx6ull.patch | 103 ++++
hal/lcd/drm/libs/build.sh | 44 ++
hal/lcd/lvgl/libs_lvgl/build.sh | 72 +++
hal/lcd/lvgl/makefile | 46 ++
hal/lcd/fb/fbtest.c | 396 ++++++++++++++++++
hal/lcd/fb/makefile | 43 +
hal/lcd/drm/libs/libdrm/build.sh | 98 ++++
hal/lcd/lvgl/libs_lvgl/patches/gen_patch.sh | 55 ++
hal/lcd/lvgl/libs_lvgl/patches/lvgl-8.0.2-imx6ull.patch | 92 ++++
hal/lcd/lvgl/libs_lvgl/patches/lv_demos-8.0.1-imx6ull.patch | 49 ++
hal/lcd/drm/drm_test.c | 154 +++++++
hal/lcd/drm/makefile | 50 ++
13 files changed, 1,293 insertions(+), 0 deletions(-)
diff --git a/hal/lcd/drm/drm_test.c b/hal/lcd/drm/drm_test.c
new file mode 100644
index 0000000..e3cf6ca
--- /dev/null
+++ b/hal/lcd/drm/drm_test.c
@@ -0,0 +1,154 @@
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <time.h>
+#include <unistd.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+struct buffer_object {
+
+ uint32_t width;
+ uint32_t height;
+ uint32_t pitch;
+ uint32_t handle;
+ uint32_t size;
+ uint32_t *vaddr;
+ uint32_t fb_id;
+};
+
+struct buffer_object buf[3];
+
+static int modeset_create_fb(int fd, struct buffer_object *bo, uint32_t color)
+{
+
+ struct drm_mode_create_dumb create = {
+ };
+ struct drm_mode_map_dumb map = {
+ };
+ uint32_t i;
+
+ create.width = bo->width;
+ create.height = bo->height;
+ create.bpp = 32;
+ drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
+
+ bo->pitch = create.pitch;
+ bo->size = create.size;
+ bo->handle = create.handle;
+ drmModeAddFB(fd, bo->width, bo->height, 24, 32, bo->pitch,
+ bo->handle, &bo->fb_id);
+
+ map.handle = create.handle;
+ drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
+
+ bo->vaddr = mmap(0, create.size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, map.offset);
+
+ for (i = 0; i < (bo->size / 4); i++)
+ bo->vaddr[i] = color;
+
+ return 0;
+}
+
+static void modeset_destroy_fb(int fd, struct buffer_object *bo)
+{
+
+ struct drm_mode_destroy_dumb destroy = {
+ };
+
+ drmModeRmFB(fd, bo->fb_id);
+
+ munmap(bo->vaddr, bo->size);
+
+ destroy.handle = bo->handle;
+ drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy);
+}
+
+int main(int argc, char **argv)
+{
+ char *dri_card="/dev/dri/card0";
+ int fd;
+ uint32_t conn_id;
+ uint32_t crtc_id;
+ drmModeConnector *conn;
+ drmModeRes *res;
+
+ if( argc != 2 )
+ {
+ printf("Usage: %s /dev/dri/card0\n", argv[0]);
+ return 1;
+ }
+ else
+ {
+ dri_card = argv[1];
+ }
+
+ fd = open(dri_card, O_RDWR | O_CLOEXEC);
+ if( fd < 0)
+ {
+ printf("Open '%s' failure: %s\n", dri_card, strerror(errno));
+ return 0;
+ }
+
+ res = drmModeGetResources(fd);
+ if( !res )
+ {
+ printf("drmModeGetResources() failure\n");
+ return 0;
+ }
+
+ crtc_id = res->crtcs[0];
+ conn_id = res->connectors[0];
+
+ conn = drmModeGetConnector(fd, conn_id);
+ if( !conn )
+ {
+ printf("drmModeGetConnector() failure\n");
+ return 0;
+ }
+
+ buf[0].width = conn->modes[0].hdisplay;
+ buf[0].height = conn->modes[0].vdisplay;
+ buf[1].width = conn->modes[0].hdisplay;
+ buf[1].height = conn->modes[0].vdisplay;
+ buf[2].width = conn->modes[0].hdisplay;
+ buf[2].height = conn->modes[0].vdisplay;
+
+ printf("DRM create framebuffer now.\n");
+ modeset_create_fb(fd, &buf[0], 0xff0000);
+ modeset_create_fb(fd, &buf[1], 0x00ff00);
+ modeset_create_fb(fd, &buf[2], 0x0000ff);
+
+ printf("Show red screen on LCD.\n");
+ drmModeSetCrtc(fd, crtc_id, buf[0].fb_id, 0, 0, &conn_id, 1, &conn->modes[0]);
+ getchar();
+
+ printf("Show green screen on LCD.\n");
+ drmModeSetCrtc(fd, crtc_id, buf[1].fb_id, 0, 0, &conn_id, 1, &conn->modes[0]);
+ getchar();
+
+ printf("Show blue screen on LCD.\n");
+ drmModeSetCrtc(fd, crtc_id, buf[2].fb_id, 0, 0, &conn_id, 1, &conn->modes[0]);
+ getchar();
+
+ printf("DRM destroy framebuffer now.\n");
+ modeset_destroy_fb(fd, &buf[0]);
+ modeset_destroy_fb(fd, &buf[1]);
+ modeset_destroy_fb(fd, &buf[2]);
+
+ drmModeFreeConnector(conn);
+ return 0;
+ drmModeFreeResources(res);
+
+ close(fd);
+
+ return 0;
+}
+
diff --git a/hal/lcd/drm/libs/build.sh b/hal/lcd/drm/libs/build.sh
new file mode 100755
index 0000000..bdc2729
--- /dev/null
+++ b/hal/lcd/drm/libs/build.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+function do_compile
+{
+ for dir in `ls`
+ do
+ if [ -f $dir/build*.sh ] ; then
+ cd $dir
+ ./build*.sh
+ cd -
+ fi
+ done
+}
+
+function do_distclean
+{
+ for dir in `ls`
+ do
+ if [ -f $dir/build*.sh ] ; then
+ rm -rf ${dir}/${dir}*
+ fi
+ done
+}
+
+if [ $# == 1 ] ; then
+ if [ $1 == "clean" ] ; then
+ rm -rf install
+ exit;
+ elif [ $1 == "distclean" ] ; then
+ rm -rf install
+ do_distclean
+ exit;
+ fi
+
+ # export cross compiler
+ if echo $1 | grep "\-linux\-" > /dev/null 2>&1 ; then
+ export CROSS_COMPILE=$1
+ echo -e "\033[40;33m --W-- export cross compiler $CROSS_COMPILE \033[0m\n"
+ fi
+fi
+
+
+do_compile
+
diff --git a/hal/lcd/drm/libs/libdrm/build.sh b/hal/lcd/drm/libs/libdrm/build.sh
new file mode 100755
index 0000000..2574193
--- /dev/null
+++ b/hal/lcd/drm/libs/libdrm/build.sh
@@ -0,0 +1,98 @@
+#!/bin/bash
+
+#+--------------------------------------------------------------------------------------------
+#|Description: This shell script used download and cross compile open source libs
+#| Author: GuoWenxue <guowenxue@gmail.com>
+#| ChangeLog:
+#| 1, Initialize 1.0.0 on 2011.04.12
+#+--------------------------------------------------------------------------------------------
+
+SCRIPT_PATH=`dirname ${BASH_SOURCE[0]}`
+PREFIX_PATH=`realpath ${SCRIPT_PATH}/`/../install
+
+CONF_FILE=cross_file.txt
+
+# display in yellow
+function pr_warn() {
+ echo -e "\033[40;33m --W-- $1 \033[0m\n"
+}
+
+function generate_config()
+{
+cat > $CONF_FILE <<EOF
+
+[binaries]
+c = '${CROSS_COMPILE}gcc'
+cpp = '${CROSS_COMPILE}g++'
+ar = '${CROSS_COMPILE}ar'
+strip = '${CROSS_COMPILE}strip'
+
+[host_machine]
+system = 'linux'
+cpu_family = 'arm'
+cpu = 'armv7'
+endian = 'little'
+
+[build_machine]
+system = 'linux'
+cpu_family = 'x86_64'
+cpu = 'x86_64'
+endian = 'little'
+
+EOF
+}
+
+function compile_libdrm()
+{
+ SRC_NAME=libdrm-2.4.110
+
+ echo $PREFIX_PATH
+
+ if [ -f ${PREFIX_PATH}/bin/modetest ] ; then
+ pr_warn "$SRC_NAME already compile and installed"
+ return 0;
+ fi
+
+ pr_warn "Start compile $SRC_NAME "
+
+ if [ ! -d $SRC_NAME ] ; then
+ if [ ! -f ${SRC_NAME}.tar.xz ] ; then
+ wget https://dri.freedesktop.org/libdrm/${SRC_NAME}.tar.xz
+ fi
+
+ tar -xJf ${SRC_NAME}.tar.xz
+ fi
+
+ cd ${SRC_NAME}
+
+ generate_config
+
+ BUILD_PATH=tmp_build
+ rm -rf $BUILD_PATH && mkdir -p $BUILD_PATH && cd $BUILD_PATH
+
+ meson --prefix=$PREFIX_PATH \
+ --cross-file=../$CONF_FILE \
+ -D amdgpu=false \
+ -D cairo-tests=false \
+ -D etnaviv=false \
+ -D exynos=false \
+ -D freedreno=false \
+ -D freedreno-kgsl=false \
+ -D install-test-programs=true \
+ -D intel=false \
+ -D libkms=false \
+ -D man-pages=false \
+ -D nouveau=false \
+ -D omap=false \
+ -D radeon=false \
+ -D tegra=false \
+ -D udev=false \
+ -D valgrind=false \
+ -D vc4=false \
+ -D vmwgfx=false
+
+ ninja && ninja install
+}
+
+compile_libdrm
+
diff --git a/hal/lcd/drm/makefile b/hal/lcd/drm/makefile
new file mode 100644
index 0000000..76f206c
--- /dev/null
+++ b/hal/lcd/drm/makefile
@@ -0,0 +1,50 @@
+#*********************************************************************************
+# Copyright: (C) 2022 Avnet. All rights reserved.
+# Author: Guo Wenxue<wenxue.guo@avnet.com>
+#
+# Filename: Makefile
+# Description: This Makefile used to compile all the C source code file in
+# current folder to a excutable binary file.
+#
+#********************************************************************************/
+
+PRJ_PATH=$(shell pwd)
+APP_NAME = drm_test
+
+CROSS_COMPILE=arm-linux-gnueabihf-
+
+# C source files in top-level directory
+SRCFILES = $(wildcard *.c)
+
+# common CFLAGS for our source code
+CFLAGS = -Wall -Wshadow -Wundef -Wmaybe-uninitialized
+
+# CFLAGS and LDFLAGS for opensource library in libs
+CFLAGS+=-I ${PRJ_PATH}
+CFLAGS+=-I ${PRJ_PATH}/libs/install/include/
+CFLAGS+=-I ${PRJ_PATH}/libs/install/include/libdrm
+LDFLAGS+=-L ${PRJ_PATH}/libs/install/lib
+LDFLAGS+=-L ${PRJ_PATH}/libs/install/lib
+
+LIBS+=-ldrm
+
+.PHONY:libs
+all: libs binary
+
+libs:
+ cd libs && ./build.sh ${CROSS_COMPILE}
+
+modules:
+ @set -e; for d in ${DIRS}; do $(MAKE) CROSS_COMPILE=${CROSS_COMPILE} CFLAGS="${CFLAGS}" -C $${d}; done
+
+binary: ${SRCFILES}
+ $(CROSS_COMPILE)gcc $(CFLAGS) -o ${APP_NAME} $^ ${LDFLAGS} ${LIBS}
+ @echo " Compile over"
+
+#set -e; for d in ${DIRS}; do $(MAKE) clean -C $${d}; done
+clean:
+ @rm -f *.o $(APP_NAME)
+
+distclean: clean
+ @rm -rf cscope* tags
+ @cd libs && ./build.sh distclean
diff --git a/hal/lcd/fb/fbtest.c b/hal/lcd/fb/fbtest.c
new file mode 100644
index 0000000..43f8693
--- /dev/null
+++ b/hal/lcd/fb/fbtest.c
@@ -0,0 +1,396 @@
+/********************************************************************************
+ * Copyright: (C) 2023 LingYun IoT System Studio
+ * All rights reserved.
+ *
+ * Filename: fbtest.c
+ * Description: This program used to:
+ * 1, Show framebuffer device information
+ * 2, Show RGB color on LCD full screen
+ * 3, Show BMP file on LCD;
+ *
+ * Version: 1.0.0(08/19/23)
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ * ChangeLog: 1, Release initial version on "08/19/23 12:56:31"
+ *
+ ********************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <linux/fb.h>
+#include <sys/mman.h>
+
+#define PROG_VERSION "1.0.0"
+
+enum
+{
+ CMD_SHOW_INFO, /* show LCD info */
+ CMD_SHOW_RGB, /* show RGB color */
+ CMD_SHOW_BMP, /* show BMP file */
+};
+
+typedef struct fb_ctx_s
+{
+ int fd; /* framebuffer file descriptor */
+ char dev[64]; /* framebuffer device name */
+ long fb_size; /* framebuffer size */
+ int pix_size; /* lcd screen pix size */
+ struct fb_var_screeninfo vinfo; /* framebuffer var information */
+ char *fbp; /* framebuffer mmap() address */
+} fb_ctx_t;
+
+
+int fb_init(fb_ctx_t *fb_ctx);
+int fb_term(fb_ctx_t *fb_ctx);
+int show_rgb(fb_ctx_t *fb_ctx, int times);
+int show_bmp(fb_ctx_t *fb_ctx, char *bmp_file);
+
+static void program_usage(char *progname)
+{
+ printf("Usage: %s [OPTION]...\n", progname);
+ printf(" %s is a program to show RGB color or BMP file on LCD screen\n", progname);
+
+ printf("\nMandatory arguments to long options are mandatory for short options too:\n");
+ printf(" -d[device ] Specify framebuffer device, such as: /dev/fb0\n");
+ printf(" -c[color ] Display RGB corlor on LCD screen for some times, such as: -c 3\n");
+ printf(" -b[bmp ] Display BMP file, such as: -b bg.bmp\n");
+ printf(" -h[help ] Display this help information\n");
+ printf(" -v[version ] Display the program version\n");
+
+ printf("\n%s version %s\n", progname, PROG_VERSION);
+ return;
+}
+
+int main (int argc, char **argv)
+{
+ fb_ctx_t fb_ctx;
+ char *progname=NULL;
+ char *bmp_file=NULL;
+ char *fb_dev="/dev/fb0";
+ int cmd = CMD_SHOW_INFO;
+ int opt, times;
+
+ struct option long_options[] = {
+ {"device", required_argument, NULL, 'd'},
+ {"color", required_argument, NULL, 'c'},
+ {"bmp", required_argument, NULL, 'b'},
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+ {NULL, 0, NULL, 0}
+ };
+
+ progname = (char *)basename(argv[0]);
+
+ /* Parser the command line parameters */
+ while ((opt = getopt_long(argc, argv, "d:c:b:vh", long_options, NULL)) != -1)
+ {
+ switch (opt)
+ {
+ case 'd': /* Set framebuffer device */
+ fb_dev = optarg;
+ break;
+
+ case 'b': /* Set BMP file */
+ bmp_file = optarg;
+ cmd = CMD_SHOW_BMP;
+ break;
+
+ case 'c': /* Show RGB color */
+ times = atoi(optarg);
+ cmd = CMD_SHOW_RGB;
+ break;
+
+ case 'v': /* Get software version */
+ printf("%s version %s\n", progname, PROG_VERSION);
+ return 0;
+
+ case 'h': /* Get help information */
+ program_usage(progname);
+ return 0;
+
+ default:
+ break;
+ }
+
+ }
+
+ memset(&fb_ctx, 0, sizeof(fb_ctx));
+ strncpy(fb_ctx.dev, fb_dev, sizeof(fb_ctx.dev));
+
+ if( fb_init(&fb_ctx) < 0 )
+ {
+ printf("ERROR: Initial framebuffer device '%s' failure.\n", fb_ctx.dev);
+ return 1;
+ }
+
+ switch( cmd )
+ {
+ case CMD_SHOW_RGB:
+ show_rgb(&fb_ctx, times);
+ break;
+
+ case CMD_SHOW_BMP:
+ show_bmp(&fb_ctx, bmp_file);
+ break;
+
+ default:
+ break;
+ }
+
+ fb_term(&fb_ctx);
+
+ return 0;
+}
+
+
+int fb_get_var_screeninfo(int fd, struct fb_var_screeninfo *vinfo)
+{
+ if( fd<0 || !vinfo )
+ {
+ printf("ERROR: Invalid input arguments\n");
+ return -1;
+ }
+
+ if(ioctl(fd, FBIOGET_VSCREENINFO, vinfo))
+ {
+ printf("ERROR: ioctl() get variable info failure: %s\n", strerror(errno));
+ return -2;
+ }
+
+ printf("LCD information : %dx%d, bpp:%d rgba:%d/%d,%d/%d,%d/%d,%d/%d\n", vinfo->xres, vinfo->yres, vinfo->bits_per_pixel,
+ vinfo->red.length, vinfo->red.offset, vinfo->green.length, vinfo->green.offset,
+ vinfo->blue.length,vinfo->blue.offset, vinfo->transp.length, vinfo->transp.offset);
+
+ return 0;
+}
+
+int fb_init(fb_ctx_t *fb_ctx)
+{
+ struct fb_var_screeninfo *vinfo;
+
+ if( !fb_ctx || !strlen(fb_ctx->dev) )
+ {
+ printf("ERROR: Invalid input arguments\n");
+ return -1;
+ }
+
+ if( (fb_ctx->fd=open(fb_ctx->dev, O_RDWR)) < 0 )
+ {
+ printf("ERROR: Open framebuffer device '%s' failure: %s\n", fb_ctx->dev, strerror(errno));
+ return -2;
+ }
+
+ fb_get_var_screeninfo(fb_ctx->fd, &fb_ctx->vinfo);
+
+ vinfo = &fb_ctx->vinfo;
+ fb_ctx->fb_size = vinfo->xres * vinfo->yres * vinfo->bits_per_pixel / 8;
+ fb_ctx->pix_size = vinfo->xres * vinfo->yres;
+
+ fb_ctx->fbp =(char *)mmap(0, fb_ctx->fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, fb_ctx->fd ,0);
+ if ( !fb_ctx->fbp )
+ {
+ printf ("ERROR: Framebuffer mmap() failure: %s\n", strerror(errno));
+ return -2;
+ }
+
+ vinfo->xoffset = 0;
+ vinfo->yoffset = 0;
+
+ return 0;
+}
+
+int fb_term(fb_ctx_t *fb_ctx)
+{
+ if( !fb_ctx )
+ {
+ printf("ERROR: Invalid input arguments\n");
+ return -1;
+ }
+
+ munmap(fb_ctx->fbp, fb_ctx->fb_size);
+ close (fb_ctx->fd);
+
+ return 0;
+}
+
+int show_rgb_screen(fb_ctx_t *fb_ctx)
+{
+ struct fb_var_screeninfo *vinfo;
+ char *fb_addr;
+ int interval = 1;
+ int i, color;
+ int bpp_bytes;
+
+ if( !fb_ctx )
+ {
+ printf("ERROR: Invalid input arguments\n");
+ return -1;
+ }
+
+ vinfo = &fb_ctx->vinfo;
+ bpp_bytes = vinfo->bits_per_pixel / 8;
+
+ printf("show full screen on red\n");
+ color = (1<<vinfo->red.length-1) << vinfo->red.offset;
+ fb_addr = fb_ctx->fbp;
+ for(i=0; i<fb_ctx->pix_size; i++)
+ {
+ memcpy(fb_addr, &color, bpp_bytes);
+ fb_addr += bpp_bytes;
+ }
+ sleep(interval);
+
+ printf("show full screen on green\n");
+ color = (1<<vinfo->green.length-1) << vinfo->green.offset;
+ fb_addr = fb_ctx->fbp;
+ for(i=0; i<fb_ctx->pix_size; i++)
+ {
+ memcpy(fb_addr, &color, bpp_bytes);
+ fb_addr += bpp_bytes;
+ }
+ sleep(interval);
+
+ printf("show full screen on blue\n");
+ color = (1<<vinfo->blue.length-1) << vinfo->blue.offset;
+ fb_addr = fb_ctx->fbp;
+ for(i=0; i<fb_ctx->pix_size; i++)
+ {
+ memcpy(fb_addr, &color, bpp_bytes);
+ fb_addr += bpp_bytes;
+ }
+ sleep(interval);
+
+ return 0;
+}
+
+int show_rgb(fb_ctx_t *fb_ctx, int times)
+{
+ int i;
+
+ if( !fb_ctx )
+ {
+ printf("ERROR: Invalid input arguments\n");
+ return -1;
+ }
+
+ for(i=0; i<times; i++)
+ {
+ show_rgb_screen(fb_ctx);
+ }
+
+ return 0;
+}
+
+
+/* BMP format: https://blog.csdn.net/weixin_39756273/article/details/110585675 */
+typedef struct bmp_file_head_s
+{
+ uint8_t bfType[2]; /* BMP file type: "BM" */
+ int32_t bfSize; /* BMP file size */
+ int32_t bfReserved; /* reserved */
+ int32_t bfoffBits; /* image data offset */
+}__attribute__((packed)) bmp_file_head_t;
+
+
+typedef struct bmp_bitmap_info_s
+{
+ int32_t biSize; /* this struture size */
+ int32_t biWidth; /* image width in pix */
+ int32_t biHeight; /* image height in pix */
+ uint16_t biPlanes; /* display planes, always be 1 */
+ uint16_t biBitCount; /* bpp: 1,4,8,16,24,32 */
+ int32_t biCompress; /* compress type */
+ int32_t biSizeImage; /* image size in byte */
+ int32_t biXPelsPerMeter; /* x-res in pix/m */
+ int32_t biYPelsPerMeter; /* y-res in pix/m */
+ int32_t biClrUsed;
+ int32_t biClrImportant;
+}__attribute__((packed)) bmp_bitmap_info_t;
+
+/*
+ * BMP image file format:
+ * +----------------+------------------+--------------------+---------------+
+ * | File Head(14B) | Bitmap Info(40B) | color palette(OPT) | bitmap data |
+ * +----------------+------------------+--------------------+---------------+
+ */
+int show_bmp(fb_ctx_t *fb_ctx, char *bmp_file)
+{
+ struct fb_var_screeninfo *vinfo;
+ char *fb_addr;
+ bmp_file_head_t *file_head;
+ bmp_bitmap_info_t *bitmap_info;
+ struct stat statbuf;
+ char *f_addr;
+ char *d_addr;
+ char *p_addr;
+ int fd;
+ int bpp_bytes;
+ int i, j;
+ int width, height;
+
+ if( !fb_ctx || !bmp_file )
+ {
+ printf("ERROR: Invalid input arguments\n");
+ return -1;
+ }
+
+ if( (fd=open(bmp_file, O_RDONLY)) < 0 )
+ {
+ printf("ERROR: Open file '%s' failure: %s\n", bmp_file, strerror(errno));
+ return -2;
+ }
+
+ fstat(fd, &statbuf);
+ f_addr =(char *)mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd ,0);
+ if ( !f_addr )
+ {
+ printf ("ERROR: BMP file mmap() failure: %s\n", strerror(errno));
+ return -2;
+ }
+
+ /* BMP file header */
+ file_head = (bmp_file_head_t *)f_addr;
+ if( memcmp(file_head->bfType, "BM", 2) != 0)
+ {
+ printf("ERROR: It's not a BMP file\n");
+ return -3;
+ }
+
+ /* BMP bitmap information header */
+ bitmap_info = (bmp_bitmap_info_t *)(f_addr+sizeof(bmp_file_head_t));
+
+ /* BMP bitmap data */
+ d_addr = f_addr + file_head->bfoffBits;
+
+ vinfo = &fb_ctx->vinfo;
+ fb_addr = fb_ctx->fbp;
+ bpp_bytes = vinfo->bits_per_pixel / 8;
+
+ width = bitmap_info->biWidth>vinfo->xres ? vinfo->xres : bitmap_info->biWidth;
+ height = bitmap_info->biHeight>vinfo->yres ? vinfo->yres : bitmap_info->biHeight;
+
+ printf("BMP file '%s': %dx%d and display %dx%d\n", bmp_file, bitmap_info->biWidth, bitmap_info->biHeight, width, height);
+
+ /* if biHeight is positive, the bitmap is a bottom-up DIB */
+ for(i=0; i<height; i++)
+ {
+ p_addr=d_addr+(height-1-i)*bitmap_info->biWidth*bpp_bytes;
+ memcpy(fb_addr, p_addr, bpp_bytes*width);
+ fb_addr += bpp_bytes * vinfo->xres;
+ }
+
+ munmap(f_addr, statbuf.st_size);
+ close (fd);
+
+ return 0;
+}
+
diff --git a/hal/lcd/fb/makefile b/hal/lcd/fb/makefile
new file mode 100644
index 0000000..0b48c53
--- /dev/null
+++ b/hal/lcd/fb/makefile
@@ -0,0 +1,43 @@
+#********************************************************************************
+# Copyright: (C) 2023 LingYun IoT System Studio
+# All rights reserved.
+#
+# Filename: Makefile
+# Description: This file used to compile all the C file to respective binary,
+# and it will auto detect cross compile or local compile.
+#
+# Version: 1.0.0(11/08/23)
+# Author: Guo Wenxue <guowenxue@gmail.com>
+# ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
+#
+#*******************************************************************************
+
+PWD=$(shell pwd)
+INSTPATH=/tftp
+
+CROSS_COMPILE=arm-linux-gnueabihf-
+CC=${CROSS_COMPILE}gcc
+
+SRCS = $(wildcard ${VPATH}/*.c)
+OBJS = $(patsubst %.c,%.o,$(SRCS))
+
+SRCFILES = $(wildcard *.c)
+BINARIES=$(SRCFILES:%.c=%)
+
+all: binaries install
+
+binaries: ${BINARIES}
+
+%: %.c
+ $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
+
+install:
+ cp $(BINARIES) ${INSTPATH}
+
+clean:
+ @rm -f *.o *.lo $(BINARIES)
+
+distclean: clean
+ @rm -f tags cscope*
+
+.PHONY: clean entry
diff --git a/hal/lcd/lvgl/libs_lvgl/build.sh b/hal/lcd/lvgl/libs_lvgl/build.sh
new file mode 100755
index 0000000..f3fc658
--- /dev/null
+++ b/hal/lcd/lvgl/libs_lvgl/build.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+
+PRJ_PATH=`pwd`
+BOARD=imx6ull
+
+LYFTP_SRC=http://master.weike-iot.com:2211/src/
+
+LIB_LVGL=lvgl-8.0.2
+LIB_LVGL_DRV=lv_drivers-8.0.1
+LIB_LVGL_DEMO=lv_demos-8.0.1
+
+LIBS_DIR="lvgl lv_drivers lv_demos"
+
+CROSS_COMPILE=arm-linux-gnueabihf-
+if [ $# == 1 ] ; then
+ CROSS_COMPILE=$1
+fi
+
+set -e
+
+function prepare_lib()
+{
+ PACK_SUFIX=tar.gz
+ PACK_NAME=$1
+ DIR_NAME=$2
+
+ if [ ! -d ${DIR_NAME} ] ; then
+ if [ ! -s ${PACK_NAME}.${PACK_SUFIX} ] ; then
+ wget ${LYFTP_SRC}/${PACK_NAME}.${PACK_SUFIX}
+ fi
+
+ tar -xzf ${PACK_NAME}.${PACK_SUFIX}
+ patch -p0 < patches/${PACK_NAME}-${BOARD}.patch
+ mv ${PACK_NAME} ${DIR_NAME}
+
+ cd ${DIR_NAME}
+ sed -i -e "s|.*CMAKE_C_COMPILER.*|set(CMAKE_C_COMPILER \"${CROSS_COMPILE}gcc\")|g" CMakeLists.txt
+ temp_file=`ls *_template.h`
+ conf_file=`echo ${temp_file/_template/}`
+ cp ${temp_file} ../${conf_file}
+ cd ${PRJ_PATH}
+ fi
+}
+
+if [[ $# == 1 && $1 == clean ]] ; then
+ rm -rf lv*
+ rm -rf libs
+ exit;
+fi
+
+prepare_lib ${LIB_LVGL} lvgl
+prepare_lib ${LIB_LVGL_DRV} lv_drivers
+prepare_lib ${LIB_LVGL_DEMO} lv_demos
+
+
+mkdir -p ${PRJ_PATH}/libs
+
+for lib in ${LIBS_DIR}
+do
+ if [ -f ${PRJ_PATH}/libs/lib${lib}.a ] ; then
+ continue;
+ fi
+
+ mkdir -p ${lib}/build
+ cd ${lib}/build/
+ rm -rf * && cmake .. && make
+
+ cp lib*.a ${PRJ_PATH}/libs/lib${lib}.a
+ cd ${PRJ_PATH}
+done
+
+
diff --git a/hal/lcd/lvgl/libs_lvgl/patches/gen_patch.sh b/hal/lcd/lvgl/libs_lvgl/patches/gen_patch.sh
new file mode 100755
index 0000000..acf88f1
--- /dev/null
+++ b/hal/lcd/lvgl/libs_lvgl/patches/gen_patch.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Description: This shell script used to generate patch file
+# Author: guowenxue <guowenxue@gmail.com>
+# Version: 1.0.0
+
+PROJ_PATH=`pwd`
+
+PATCH_PATH=${PROJ_PATH}/patches
+
+BOARD=imx6ull
+PATCH_SUFFIX=${BOARD}.patch
+
+set -e
+
+
+if [ $# != 1 ] ; then
+ echo "Usage: $0 [src_path]"
+ printf "\nExample: \n"
+ echo "$0 lvgl-8.0.2"
+
+ exit ;
+fi
+
+
+SRC=`basename $1`
+
+if [ ! -d ${SRC} ] ; then
+ printf "\nERROR: ${SRC} source code not exist, exit now\n\n"
+ exit
+fi
+
+if [ ! -f ${SRC}.tar.gz ] ; then
+ printf "\nERROR: ${SRC}.tar.gz packet not exist, exit now\n\n"
+ exit
+fi
+
+rm -rf ${SRC}/build
+
+# rename new source code
+mv ${SRC} ${SRC}-${BOARD}
+
+# decompress orignal soruce code packet
+tar -xzf ${SRC}.tar.gz
+
+set +e
+
+# generate patch file
+diff -Nuar ${SRC} ${SRC}-${BOARD} > ${SRC}-${PATCH_SUFFIX}
+
+# remove orignal soruce code
+rm -rf ${SRC}
+
+# recover new source code
+mv ${SRC}-${BOARD} ${SRC}
+
diff --git a/hal/lcd/lvgl/libs_lvgl/patches/lv_demos-8.0.1-imx6ull.patch b/hal/lcd/lvgl/libs_lvgl/patches/lv_demos-8.0.1-imx6ull.patch
new file mode 100644
index 0000000..b07ea04
--- /dev/null
+++ b/hal/lcd/lvgl/libs_lvgl/patches/lv_demos-8.0.1-imx6ull.patch
@@ -0,0 +1,49 @@
+diff -Nuar lv_demos-8.0.1/CMakeLists.txt lv_demos-8.0.1-imx6ull/CMakeLists.txt
+--- lv_demos-8.0.1/CMakeLists.txt 2021-06-14 20:00:00.000000000 +0800
++++ lv_demos-8.0.1-imx6ull/CMakeLists.txt 2021-09-27 21:26:45.823935469 +0800
+@@ -1,2 +1,5 @@
++set(CMAKE_C_COMPILER "/opt/buildroot/cortex-a7/bin/arm-linux-gcc")
++include_directories(..)
++
+ file(GLOB_RECURSE SOURCES src/*.c)
+ add_library(lv_examples STATIC ${SOURCES})
+diff -Nuar lv_demos-8.0.1/lv_demo_conf_template.h lv_demos-8.0.1-imx6ull/lv_demo_conf_template.h
+--- lv_demos-8.0.1/lv_demo_conf_template.h 2021-06-14 20:00:00.000000000 +0800
++++ lv_demos-8.0.1-imx6ull/lv_demo_conf_template.h 2021-09-27 20:57:35.667901897 +0800
+@@ -7,7 +7,7 @@
+ * COPY THIS FILE AS lv_demo_conf.h
+ */
+
+-#if 0 /*Set it to "1" to enable the content*/
++#if 1 /*Set it to "1" to enable the content*/
+
+ #ifndef LV_EX_CONF_H
+ #define LV_EX_CONF_H
+@@ -25,22 +25,22 @@
+ *********************/
+
+ /*Show some widget*/
+-#define LV_USE_DEMO_WIDGETS 0
++#define LV_USE_DEMO_WIDGETS 1
+ #if LV_USE_DEMO_WIDGETS
+ #define LV_DEMO_WIDGETS_SLIDESHOW 0
+ #endif
+
+ /*Printer demo, optimized for 800x480*/
+-#define LV_USE_DEMO_PRINTER 0
++#define LV_USE_DEMO_PRINTER 1
+
+ /*Demonstrate the usage of encoder and keyboard*/
+-#define LV_USE_DEMO_KEYPAD_AND_ENCODER 0
++#define LV_USE_DEMO_KEYPAD_AND_ENCODER 1
+
+ /*Benchmark your system*/
+-#define LV_USE_DEMO_BENCHMARK 0
++#define LV_USE_DEMO_BENCHMARK 1
+
+ /*Stress test for LVGL*/
+-#define LV_USE_DEMO_STRESS 0
++#define LV_USE_DEMO_STRESS 1
+
+ /*Music player demo*/
+ #define LV_USE_DEMO_MUSIC 1
diff --git a/hal/lcd/lvgl/libs_lvgl/patches/lv_drivers-8.0.1-imx6ull.patch b/hal/lcd/lvgl/libs_lvgl/patches/lv_drivers-8.0.1-imx6ull.patch
new file mode 100644
index 0000000..fddbfea
--- /dev/null
+++ b/hal/lcd/lvgl/libs_lvgl/patches/lv_drivers-8.0.1-imx6ull.patch
@@ -0,0 +1,103 @@
+diff -Nuar lv_drivers-8.0.1/CMakeLists.txt lv_drivers-8.0.1-imx6ull/CMakeLists.txt
+--- lv_drivers-8.0.1/CMakeLists.txt 2021-06-14 19:54:20.000000000 +0800
++++ lv_drivers-8.0.1-imx6ull/CMakeLists.txt 2021-09-27 22:20:38.179997474 +0800
+@@ -1,2 +1,5 @@
++set(CMAKE_C_COMPILER "/opt/buildroot/cortex-a7/bin/arm-linux-gcc")
++include_directories(..)
++
+ file(GLOB_RECURSE SOURCES ./*.c)
+ add_library(lv_drivers STATIC ${SOURCES})
+diff -Nuar lv_drivers-8.0.1/indev/evdev.c lv_drivers-8.0.1-imx6ull/indev/evdev.c
+--- lv_drivers-8.0.1/indev/evdev.c 2021-06-14 19:54:20.000000000 +0800
++++ lv_drivers-8.0.1-imx6ull/indev/evdev.c 2021-09-27 22:25:04.172002576 +0800
+@@ -115,7 +115,7 @@
+ * @param data store the evdev data here
+ * @return false: because the points are not buffered, so no more data to be read
+ */
+-bool evdev_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
++void evdev_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
+ {
+ struct input_event in;
+
+@@ -196,7 +196,7 @@
+ }
+ evdev_key_val = data->key;
+ evdev_button = data->state;
+- return false;
++ return;
+ }
+ }
+ }
+@@ -205,10 +205,10 @@
+ /* No data retrieved */
+ data->key = evdev_key_val;
+ data->state = evdev_button;
+- return false;
++ return;
+ }
+ if(drv->type != LV_INDEV_TYPE_POINTER)
+- return false;
++ return;
+ /*Store the collected data*/
+
+ #if EVDEV_CALIBRATE
+@@ -225,12 +225,12 @@
+ data->point.x = 0;
+ if(data->point.y < 0)
+ data->point.y = 0;
+- if(data->point.x >= drv->disp->driver.hor_res)
+- data->point.x = drv->disp->driver.hor_res - 1;
+- if(data->point.y >= drv->disp->driver.ver_res)
+- data->point.y = drv->disp->driver.ver_res - 1;
++ if(data->point.x >= drv->disp->driver->hor_res)
++ data->point.x = drv->disp->driver->hor_res - 1;
++ if(data->point.y >= drv->disp->driver->ver_res)
++ data->point.y = drv->disp->driver->ver_res - 1;
+
+- return false;
++ return;
+ }
+
+ /**********************
+diff -Nuar lv_drivers-8.0.1/indev/evdev.h lv_drivers-8.0.1-imx6ull/indev/evdev.h
+--- lv_drivers-8.0.1/indev/evdev.h 2021-06-14 19:54:20.000000000 +0800
++++ lv_drivers-8.0.1-imx6ull/indev/evdev.h 2021-09-27 22:25:33.424003137 +0800
+@@ -57,7 +57,7 @@
+ * @param data store the evdev data here
+ * @return false: because the points are not buffered, so no more data to be read
+ */
+-bool evdev_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
++void evdev_read(lv_indev_drv_t * drv, lv_indev_data_t * data);
+
+
+ /**********************
+diff -Nuar lv_drivers-8.0.1/lv_drv_conf_template.h lv_drivers-8.0.1-imx6ull/lv_drv_conf_template.h
+--- lv_drivers-8.0.1/lv_drv_conf_template.h 2021-06-14 19:54:20.000000000 +0800
++++ lv_drivers-8.0.1-imx6ull/lv_drv_conf_template.h 2021-09-27 22:20:38.183997474 +0800
+@@ -7,7 +7,7 @@
+ * COPY THIS FILE AS lv_drv_conf.h
+ */
+
+-#if 0 /*Set it to "1" to enable the content*/
++#if 1 /*Set it to "1" to enable the content*/
+
+ #ifndef LV_DRV_CONF_H
+ #define LV_DRV_CONF_H
+@@ -272,7 +272,7 @@
+ * Linux frame buffer device (/dev/fbx)
+ *-----------------------------------------*/
+ #ifndef USE_FBDEV
+-# define USE_FBDEV 0
++# define USE_FBDEV 1
+ #endif
+
+ #if USE_FBDEV
+@@ -386,7 +386,7 @@
+ * Mouse or touchpad as evdev interface (for Linux based systems)
+ *------------------------------------------------*/
+ #ifndef USE_EVDEV
+-# define USE_EVDEV 0
++# define USE_EVDEV 1
+ #endif
+
+ #ifndef USE_BSD_EVDEV
diff --git a/hal/lcd/lvgl/libs_lvgl/patches/lvgl-8.0.2-imx6ull.patch b/hal/lcd/lvgl/libs_lvgl/patches/lvgl-8.0.2-imx6ull.patch
new file mode 100644
index 0000000..5ae5a78
--- /dev/null
+++ b/hal/lcd/lvgl/libs_lvgl/patches/lvgl-8.0.2-imx6ull.patch
@@ -0,0 +1,92 @@
+diff -Nuar lvgl-8.0.2/CMakeLists.txt lvgl-8.0.2-imx6ull/CMakeLists.txt
+--- lvgl-8.0.2/CMakeLists.txt 2021-07-16 23:40:51.000000000 +0800
++++ lvgl-8.0.2-imx6ull/CMakeLists.txt 2021-09-27 22:30:20.360008641 +0800
+@@ -1,3 +1,7 @@
++
++set(CMAKE_C_COMPILER "/opt/buildroot/cortex-a7/bin/arm-linux-gcc")
++include_directories(..)
++
+ if(ESP_PLATFORM)
+
+ file(GLOB_RECURSE SOURCES src/*.c)
+diff -Nuar lvgl-8.0.2/lv_conf_template.h lvgl-8.0.2-imx6ull/lv_conf_template.h
+--- lvgl-8.0.2/lv_conf_template.h 2021-07-16 23:40:51.000000000 +0800
++++ lvgl-8.0.2-imx6ull/lv_conf_template.h 2021-09-27 22:33:47.448012614 +0800
+@@ -7,7 +7,7 @@
+ * COPY THIS FILE AS `lv_conf.h` NEXT TO the `lvgl` FOLDER
+ */
+
+-#if 0 /*Set it to "1" to enable content*/
++#if 1 /*Set it to "1" to enable content*/
+
+ #ifndef LV_CONF_H
+ #define LV_CONF_H
+@@ -21,7 +21,7 @@
+ *====================*/
+
+ /*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
+-#define LV_COLOR_DEPTH 32
++#define LV_COLOR_DEPTH 16
+
+ /*Swap the 2 bytes of RGB565 color. Useful if the display has a 8 bit interface (e.g. SPI)*/
+ #define LV_COLOR_16_SWAP 0
+@@ -42,7 +42,7 @@
+ #define LV_MEM_CUSTOM 0
+ #if LV_MEM_CUSTOM == 0
+ /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
+-# define LV_MEM_SIZE (32U * 1024U) /*[bytes]*/
++# define LV_MEM_SIZE (128U * 1024U) /*[bytes]*/
+
+ /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
+ # define LV_MEM_ADR 0 /*0: unused*/
+@@ -68,9 +68,10 @@
+
+ /*Use a custom tick source that tells the elapsed time in milliseconds.
+ *It removes the need to manually update the tick with `lv_tick_inc()`)*/
+-#define LV_TICK_CUSTOM 0
++#define LV_TICK_CUSTOM 1
+ #if LV_TICK_CUSTOM
+-#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/
++extern uint32_t millis(void);
++#define LV_TICK_CUSTOM_INCLUDE <stdint.h> /*Header for the system time function*/
+ #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/
+ #endif /*LV_TICK_CUSTOM*/
+
+@@ -137,7 +138,7 @@
+ *-----------*/
+
+ /*Enable the log module*/
+-#define LV_USE_LOG 0
++#define LV_USE_LOG 1
+ #if LV_USE_LOG
+
+ /*How important log should be added:
+@@ -151,7 +152,7 @@
+
+ /*1: Print the log with 'printf';
+ *0: User need to register a callback with `lv_log_register_print_cb()`*/
+-# define LV_LOG_PRINTF 0
++# define LV_LOG_PRINTF 1
+
+ /*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/
+ # define LV_LOG_TRACE_MEM 1
+@@ -262,13 +263,13 @@
+
+ /*Montserrat fonts with ASCII range and some symbols using bpp = 4
+ *https://fonts.google.com/specimen/Montserrat*/
+-#define LV_FONT_MONTSERRAT_8 0
+-#define LV_FONT_MONTSERRAT_10 0
+-#define LV_FONT_MONTSERRAT_12 0
++#define LV_FONT_MONTSERRAT_8 1
++#define LV_FONT_MONTSERRAT_10 1
++#define LV_FONT_MONTSERRAT_12 1
+ #define LV_FONT_MONTSERRAT_14 1
+-#define LV_FONT_MONTSERRAT_16 0
+-#define LV_FONT_MONTSERRAT_18 0
+-#define LV_FONT_MONTSERRAT_20 0
++#define LV_FONT_MONTSERRAT_16 1
++#define LV_FONT_MONTSERRAT_18 1
++#define LV_FONT_MONTSERRAT_20 1
+ #define LV_FONT_MONTSERRAT_22 0
+ #define LV_FONT_MONTSERRAT_24 0
+ #define LV_FONT_MONTSERRAT_26 0
diff --git a/hal/lcd/lvgl/lvgl_demo.c b/hal/lcd/lvgl/lvgl_demo.c
new file mode 100644
index 0000000..f7eeb5c
--- /dev/null
+++ b/hal/lcd/lvgl/lvgl_demo.c
@@ -0,0 +1,91 @@
+/*********************************************************************************
+ * Copyright: (C) 2021 LingYun IoT System Studio
+ * All rights reserved.
+ *
+ * Filename: lvgl_demo.c
+ * Description: This file is LVGL demo program.
+ *
+ * Version: 1.0.0(2021年09月27日)
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ * ChangeLog: 1, Release initial version on "2021年09月27日 22时16分52秒"
+ *
+ ********************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "lvgl/lvgl.h"
+#include "lv_drivers/display/fbdev.h"
+#include "lv_drivers/indev/evdev.h"
+#include "lv_demos/lv_demo.h"
+
+#define DISP_BUF_SIZE (128 * 1024)
+
+
+int main(void)
+{
+ lv_disp_drv_t disp_drv;
+ lv_indev_drv_t indev_drv;
+ static lv_color_t buf[DISP_BUF_SIZE]; /* buffer for LVGL to draw the screen's content */
+ static lv_disp_draw_buf_t disp_buf; /* Initialize a descriptor for the buffer */
+
+ /* LVGL context init */
+ lv_init();
+
+ /* Linux frame buffer device init */
+ fbdev_init();
+
+ /* linux touchscreen device init */
+ lv_indev_drv_init(&indev_drv);
+ indev_drv.type =LV_INDEV_TYPE_POINTER;
+ indev_drv.read_cb =evdev_read;
+ lv_indev_drv_register(&indev_drv);
+
+ /* Initialize and register a display driver */
+ lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);
+ lv_disp_drv_init(&disp_drv);
+ disp_drv.draw_buf = &disp_buf;
+ disp_drv.flush_cb = fbdev_flush;
+ disp_drv.hor_res = 800;
+ disp_drv.ver_res = 480;
+ lv_disp_drv_register(&disp_drv);
+
+ /* Create a Demo */
+ //lv_demo_widgets();
+ lv_demo_music();
+ //lv_demo_keypad_encoder();
+ //lv_demo_stress();
+
+ /* Handle LitlevGL tasks (tickless mode) */
+ while(1) {
+ lv_task_handler();
+ usleep(5000);
+ }
+
+ return 0;
+}
+
+/* Set in lv_conf.h as LV_TICK_CUSTOM_SYS_TIME_EXPR */
+uint32_t millis(void)
+{
+ static uint64_t start_ms = 0;
+ struct timeval tv_start;
+ struct timeval tv_now;
+ uint64_t now_ms;
+ uint32_t time_ms;
+
+ if(start_ms == 0)
+ {
+ gettimeofday(&tv_start, NULL);
+ start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
+ }
+
+ gettimeofday(&tv_now, NULL);
+ now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;
+
+ time_ms = now_ms - start_ms;
+ return time_ms;
+}
diff --git a/hal/lcd/lvgl/makefile b/hal/lcd/lvgl/makefile
new file mode 100644
index 0000000..fc31e3b
--- /dev/null
+++ b/hal/lcd/lvgl/makefile
@@ -0,0 +1,46 @@
+
+CROSS_COMPILE=arm-linux-gnueabihf-
+CC=${CROSS_COMPILE}gcc
+
+CFLAGS = -Wall -Wshadow -Wundef -Wmaybe-uninitialized
+CFLAGS += -O3 -g3 -I./ -I ./libs_lvgl/
+
+LDFLAGS+=-L ./libs_lvgl/libs/ -llv_demos -llv_drivers -llvgl
+
+BIN = lvgl_demo
+
+MAINSRC = lvgl_demo.c
+
+VPATH =
+OBJEXT ?= .o
+
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+MAINOBJ = $(MAINSRC:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS) $(MAINSRC)
+OBJS = $(AOBJS) $(COBJS)
+
+## MAINOBJ -> OBJFILES
+
+all: libs clean default
+ cp ${BIN} /tftp
+
+libs:
+ cd libs_lvgl && ./build.sh ${CROSS_COMPILE}
+
+%.o: %.c
+ @$(CC) $(CFLAGS) -c $< -o $@
+ @echo "CC $<"
+
+default: $(AOBJS) $(COBJS) $(MAINOBJ)
+ $(CC) -o $(BIN) $(MAINOBJ) $(AOBJS) $(COBJS) $(LDFLAGS)
+
+clean:
+ rm -f $(BIN) $(AOBJS) $(COBJS) $(MAINOBJ)
+
+distclean: clean
+ rm -rf cscope* tags
+ cd libs_lvgl && ./build.sh clean
+
--
Gitblit v1.9.1