正点原子imx6ull移植lvgl v8.3及触摸屏调试

使用正点原子imx6ull移植lvgl 8.3及触摸屏调试过程。

硬件

  • 开发板:ALPHA I.MX6ULL
  • 屏幕:ALIENTEK 7' RGB TFTLCD 1024*600

软件

已烧录带framebuffer的zImage(cat /dev/fb0可以打开)

如果带触摸,需要确认已存在触摸节点(ls /dev/input/event*),使用hexdump /dev/input/event*可以检测到触摸

lvgl源码下载、修改、编译

lvgllv_drivers文件夹复制到lv_port_frame_buffer 文件夹下,文件目录如下:

shell 复制代码
lv_port_linux_frame_buffer$ tree -L 1
├── LICENSE
├── lv_conf.h
├── lv_drivers
├── lv_drv_conf.h
├── lvgl
├── main.c
├── Makefile
├── mouse_cursor_icon.c
└── README.md

修改Makefile

修改工具链:CC = arm-linux-gnueabihf-gcc

由于驱动教程安装的工具链版本较低,所以后续编译会报错,这里直接为了解决编译错误,直接修改Makefile的CFLAGS

  • 添加-std=gnu99
  • 删除编译选项-Wshift-negative-value

修改lv_drv_conf.h

1. USE_FBDEV
2. USE_EVDEV

修改lv_conf.h

1. LV_MEM_CUSTOM
2. 可选

修改main.c

编译

shell 复制代码
lvgl_imx/lv_port_linux_frame_buffer$ make -j16

编译完后生成可执行文件demo,拷贝至开发板后使用./demo运行即可。

运行效果

至此,基本移植工作已完成,但是此时触摸完全没反应,接下来开始了调触摸的部分。

触摸调试

这里是使用的Linux内核自带的驱动,edt-ft5x06.c也是使用的正点原子修改过的,理论上不需要再次修改。

使用hexdump /dev/input/event1命令可以确认触摸硬件及驱动都是正常工作的。

evdev_read

main.c已经注册了输入的回调函数,调试的第一步选择在evdev_read函数里添加打印,输出当前坐标位置,检测是否检测到触摸。

c 复制代码
void evdev_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
	  ...
	  
	data->state = evdev_button;
	printf("state = %d\n", evdev_button);
	
	if(data->point.x < 0)
	  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;
	  
	printf("point.x = %d, point.y = %d\n", data->point.x, data->point.y);
	
	return ;
}

从打印信息里观察到:

shell 复制代码
state = 0
point.x = 930, point.y = 61
state = 0
point.x = 930, point.y = 61
state = 0
point.x = 930, point.y = 61
...
state = 0
point.x = 593, point.y = 28
state = 0
point.x = 593, point.y = 28
state = 0
point.x = 593, point.y = 28

按下的状态一直为0,但是实际坐标是实时更新的,所以还是这个data->state的问题。

修改驱动文件MAX_SUPPORT_POINTS

看到其他博客中有提到这款屏幕只支持单点触摸,可以把此宏修改为1,然后重新编译内核,可以解决此问题,然而这里修改后并未解决。

c 复制代码
#define MAX_SUPPORT_POINTS		1			/* 5点触摸 	*/

此时有些无语了,搞了大半天了。。。

继续跟踪evdev_read

data->state一直为0,说明问题还是出在evdev_read前面的代码里,未满足条件,所以未进行赋值,data->state一直未得到更新。
in.typeinput 子系统 的事件大类,定义在 <linux/input-event-codes.h>

常见 6 种(全部枚举不足 10 种):

数值 含义 典型事件码
EV_SYN 0x00 同步事件------用来打包一组数据,本身无意义 SYN_REPORT
EV_KEY 0x01 按键/开关------键盘、鼠标键、触摸按下/释放 BTN_TOUCH, KEY_ENTER
EV_REL 0x02 相对坐标------鼠标、轨迹球 REL_X, REL_Y, REL_WHEEL
EV_ABS 0x03 绝对坐标------触摸屏、游戏摇杆 ABS_X, ABS_Y, ABS_MT_POSITION_X
EV_MSC 0x04 杂项------无标准含义,驱动私有 MSC_SCAN, MSC_SERIAL
EV_SW 0x05 开关------物理滑盖、耳机插入 SW_LID, SW_HEADPHONE_INSERT

所以这里只需要关注EV_ABS下的代码:

c 复制代码
void evdev_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
    struct input_event in;
    
    while(read(evdev_fd, &in, sizeof(struct input_event)) > 0) {
        printf("read evdev_fd, in.type = %d, in.code = %d\n", in.type, in.code);
        if(in.type == EV_REL) {
			...
        } else if(in.type == EV_ABS) {
            if(in.code == ABS_X)
				#if EVDEV_SWAP_AXES
					evdev_root_y = in.value;
				#else
					evdev_root_x = in.value;
				#endif
            else if(in.code == ABS_Y)
				#if EVDEV_SWAP_AXES
					evdev_root_x = in.value;
				#else
					evdev_root_y = in.value;
				#endif
            else if(in.code == ABS_MT_POSITION_X)
                                #if EVDEV_SWAP_AXES
                                        evdev_root_y = in.value;
                                #else
                                        evdev_root_x = in.value;
                                #endif
            else if(in.code == ABS_MT_POSITION_Y)
                                #if EVDEV_SWAP_AXES
                                        evdev_root_x = in.value;
                                #else
                                        evdev_root_y = in.value;
                                #endif
            else if(in.code == ABS_MT_TRACKING_ID) {
                                if(in.value == -1)
                                    evdev_button = LV_INDEV_STATE_REL;
                                else if(in.value == 0)
                                    evdev_button = LV_INDEV_STATE_PR;
            }
        } else if(in.type == EV_KEY) {
           ...
        }
    }
    ...
}

上述代码里只有in.code==ABS_MT_TRACKING_ID时才会更新evdev_button ,后续再赋值给data->state

继续添加打印信息:

c 复制代码
in.code = ABS_MT_TRACKING_ID
in.value = 132
in.code = ABS_MT_POSITION_X
in.value = 606
in.code = ABS_MT_POSITION_Y
in.value = 21
in.code = ABS_X
in.value = 606
in.code = ABS_Y
in.value = 21
state = 1
point.x = 606, point.y = 21
state = 1
point.x = 606, point.y = 21
state = 1
point.x = 606, point.y = 21
in.code = ABS_MT_TRACKING_ID
in.value = -1

从打印信息中基本可以确认问题所在了。可以看到,in.value的值并不是只有-10两种情况,当触摸释放时in.value=-1,但是当按下时会有具体的数值,但不是0 ,所以一直不会把按下的状态置起。

修改代码,再次测试:

c 复制代码
 if(in.value == -1)
     evdev_button = LV_INDEV_STATE_REL;
 else /*if(in.value == 0)*/
     evdev_button = LV_INDEV_STATE_PR;

果然,一切正常了,可以愉快的触摸了。


由于使用的是现成的驱动程序,所以并未从驱动角度深入调试分析,按理说修改驱动应该才是正确方法,但是既然传入的in.value可以是更大范围的数值,那修改lvgl的代码应该也是合理的,如果大家有更好的修改方法也可评论区交流。

相关推荐
WG_1713 分钟前
Linux:环境变量
linux·运维·服务器
努力的小帅14 分钟前
Linux_基础IO(Linux入门到精通)
linux·动态库·静态库·计算机组成原理·io操作
txzz888818 分钟前
CentOS-Stream-10 系统安装之Firewalld防火墙配置
linux·运维·网络·计算机网络·centos·firewall-cmd·linux防火墙
Konwledging25 分钟前
VMA-virtual memory areas
linux
无事好时节27 分钟前
【Linux 进程详解】从 PCB 到 fork
linux
kaoa00031 分钟前
Linux入门攻坚——57、HAProxy
linux·运维·服务器
噜啦噜啦嘞好1 小时前
Linux——网络概念
linux·网络
博语小屋1 小时前
简单线程池实现(单例模式)
linux·开发语言·c++·单例模式
import_random1 小时前
[环境变量]export命令的作用是什么
linux
何妨呀~1 小时前
Linux在VMware上添加磁盘与扩展分区
linux·运维·服务器