问题1:函数的参数在传输过程中会出问题吗?为什么总是出现Segmentation fault?
答:段错误,一般是出现野指针或对空指针的调用而出现的?。
所谓的段错误就是指访问的内存超过了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表,
后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中就保存着程序运
行的代码段以及数据段的起始地址以及相应的断限和页面交换还有程序运行级别和内存粒度等信息,一旦一个程序发生了越界访问,CPU就会产生相应的异常保护,
于是segmentation fault就出现了。
即“当程序试图访问不被允许访问的内存区域(比如,尝试写一块属于操作系统的内存),或以错误的类型访问内存区域(比如,尝试写一块只读内存)。这个描述
是准确的。为了加深理解,我们再更加详细的概括一下SIGSEGV。段错误应该就是访问了不可访问的内存,这个内存要么是不存在的,要么是受系统保护的。
Ø SIGSEGV是在访问内存时发生的错误,它属于内存管理的范畴
Ø SIGSEGV是一个用户态的概念,是操作系统在用户态程序错误访问内存时所做出的处理。
Ø 当用户态程序访问(访问表示读、写或执行)不允许访问的内存时,产生SIGSEGV。
Ø 当用户态程序以错误的方式访问允许访问的内存时,产生SIGSEGV。
用户态程序地址空间,特指程序可以访问的地址空间范围。如果广义的说,一个进程的地址空间应该包括内核空间部分,只是它不能访问而已。
————————————————
版权声明:本文为****博主「喜欢恋着风」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.****.net/u010150046/article/details/77775114
问题2:明明在i2c.c中已经定义了mt7620_i2c_xfer()函数,且EXPORT_SYMBOL(mt7620_i2c_xfer)修饰,但是在执行ili2117.ko模块时仍发生错误:
ili2117: Unknown symbol mt7620_i2c_xfer (err 0)
insmod: cannot insert \'ili2117.ko\': Success
答:原因找到了,加载ili2117.ko模块之前卸载了板子的所有驱动(包括i2c所在的ramips_mt7620模块),因此必然出现“Unknown symbol mt7620_i2c_xfer”
错误。
问题3:目前的内核是否使用了Linux内核自带的I2C/input子系统、设备树?如何和奕力TP原厂的ILI2117_TP驱动对接起来?
答:都没有,不过目前公司的系统里面,自定义了i2c驱动,且直接编译进内核了,不过这个i2c功能比较简单,只有i2c_read/i2c_write(),没有比较丰富的
i2c操作函数(尤其i2c子系统常用的内核i2c-core.c中的一些函数,例如:i2c_transfer())。ILI2117_TP驱动的最底层是内核i2c_transfer()函数,而我们的
i2c驱动最底层是i2c_read/i2c_write(),通过查验i2c_transfer()函数可知其到底是调用某CPU的master_i2c_xfer()函数。因此,在i2c.c文件中定义
mt7620_i2c_xfer()函数并实现其内部读写函数:
if (msgs[i].flags & I2C_M_RD) /* 2.读数据 */
{
ret = do_master_read(&msgs[i]);
}
else /* 3.写数据 */
{
ret = do_master_write(&msgs[i]);
}
的定义与实现。
备注:关于内核的I2C/input子系统、设备树可以通过make menuconfig配置选项进系统。
问题4:为什么mt7620_i2c_xfer()函数名字改成i2c_transfer()时,且内部实现一致时,编译时总是发生一些未知/莫名的错误?
答:不要定义和内核函数同名的函数,否则由于头文件包含的原因,极易因调用混乱而产生错误。
问题5:ILI2117_TP持续修改测试方法
答:前言:由于TP和keys_leds的GPIO冲突,执行fv_drv.sh脚本,卸载所有驱动,然后重新加载fvdd/ramips_mt7620,在公司的i2c平台上实现i2c操作,
然后再加载ili2117.ko驱动并调试。
①每次修改前,先把之前的代码复制一份(名字不用改动),然后再修改;
②用D:\shared_dir\driver_ts_20191230\fip11c\build目录下的keys_leds.ko复制到D:\shared_dir\driver_tp_20200116\fip15\build目录下;
③保持fv_drv.sh不变,不要删除该文件(xx_OK.sh是目前可以满足要求的脚本);
④下载fv_drv.sh到/tmp目录,chmod 777 fv_drv.sh;
⑤加载模块并测试:
cat /proc/kmsg & //若在telnet,打开后台打印;
voip.sh stop
rmmod alc5621d
rmmod ramips_mt7620
rmmod fvdd
rmmod keys_leds
rmmod nand_lcd_notdma_fip11c
cd /tmp
tftp -g -l ili2117.ko 192.168.1.88
或者
cd /tmp
tftp -g -l fv_drv.sh 192.168.1.88
chmod 777 fv_drv.sh
tftp -g -l ili2117.ko 192.168.1.88
#insmod ili2117.ko
问题6:加载ili2117.ko之后,执行期间发生错误:
<4>*** ilitek_get_customer_firmware_version ***
<1>CPU 0 Unable to handle kernel paging request at virtual address 00000000, epc == 80013240, ra == 80013018
原因何在?
答:互斥锁的原因,暂时关闭即可。
//mutex_lock(&ilitek_data->ilitek_mutex);
ret = ilitek_i2c_write_and_read(data, 1, 5, data, 4);
p_customer_fw_ver = kzalloc(sizeof(u8) * 11, GFP_KERNEL);
//mutex_unlock(&ilitek_data->ilitek_mutex);
问题7:TP可视区左右的虚拟键区,如何读取坐标?
答:①使用单独线控制TP虚拟键,即除TP六线外,单独有一根线(我们的TP没有)控制虚拟键区,如此即可使用《I2C_ProgramingGuide(ILI211XA,MSG58XX)_V1.03.pdf》页末中关于I2C传输的43字节的byte[41],作为虚拟键坐标信息进行上报;
②只有TP标准六线(如下图2),如此,虚拟键区将作为普通触摸区,其坐标纳入TP坐标系(坐标由byte[1~39]保留并上报),TP上报的坐标将以左虚拟键区左上角(像素?)为原点,右虚拟键区右下角最后一个(像素?)为末点。
图1:
图2: