正点原子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的代码应该也是合理的,如果大家有更好的修改方法也可评论区交流。

相关推荐
馨谙1 小时前
使用 systemd 单元管理容器环境完全指南
linux
石像鬼₧魂石1 小时前
有哪些常见的字典可以用于Hydra的密码破解?
linux·学习·ssh
RXXW_Dor1 小时前
西门子EtherNet/IP 适配器 通过 EtherNet/IP 将第三方控制系统连接到 SIMATIC S7 控制器
linux·网络·tcp/ip
Mr.H01271 小时前
(上册)TCP 服务器核心流程实操指南
linux·服务器·网络·tcp/ip
DeeplyMind2 小时前
Guest → QEMU → Virglrenderer 调用逻辑分析
linux·驱动开发·虚拟化·virtio-gpu·virglrenderer
chenzhou__2 小时前
LinuxC语言并发程序笔记(第二十天)
linux·c语言·笔记·学习
会飞的土拨鼠呀2 小时前
运维工程师需要具备哪些技能
linux·运维·ubuntu
虎头金猫4 小时前
随时随地处理图片文档!Reubah 加cpolar的实用体验
linux·运维·人工智能·python·docker·开源·visual studio
NiKo_W4 小时前
Linux 数据链路层
linux·服务器·网络·内网穿透·nat·数据链路层