TP 固件升级,手势识别,开短路测试 流程分析 |
您所在的位置:网站首页 › 固件升级测试 › TP 固件升级,手势识别,开短路测试 流程分析 |
一. TP固件升级
TP 固件升级方式是采用自动升级方式,自动升级分为两种:
1.request_firmware() 用户空间获取获取固件 2.搜寻BIN 文件方式,包括/data/_goodix_update_.bin 或者/sdcard/_goodix_update_.bin。 TP固件升级流程: 1. 驱动初始化会调用kthread_run()在内核创建并启动一个线程, 并执行gt1x_auto_update_proc()方法,这里data==NULL static int gt1x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id){ GTP_INFO("GTP Driver Version: %s,slave addr:%02xh",GTP_DRIVER_VERSION, client->addr); #ifdef CONFIG_GTP_AUTO_UPDATE do { struct task_struct *thread = NULL; thread = kthread_run(gt1x_auto_update_proc, (void *)NULL, "gt1x_auto_update"); if(IS_ERR(thread)) GTP_ERROR("Failed to create auto-update thread: %d.", ret); } while(0); #endif }2. 执行gt1x_auto_update_proc() 方法时,由于data==null 执行 完 gt1x_update_firmware(NULL); 就会返回0;停止执行下去 int gt1x_auto_update_proc(void *data) { int ret; char *filename; u8 config[GTP_CONFIG_ORG_LENGTH + GTP_CONFIG_EXT_LENGTH] = { 0 }; if(data == NULL) { GTP_INFO("Start auto update thread from request..."); gt1x_update_firmware(NULL); return 0; } //下面是不会执行 GTP_INFO("Start auto update thread from file..."); ret = gt1x_search_update_files(); if(ret & (FOUND_FW_PATH_1 | FOUND_FW_PATH_2)) { if(ret & FOUND_FW_PATH_1) { filename = UPDATE_FILE_PATH_1; } gt1x_update_firmware(filename);3.//执行gt1x_update_firmware(filename) 时,会执行下面方法 gt1x_enter_update_mode(); 进入固件升级模式 gt1x_update_prepare(filename);固件升级准备 gt1x_check_firmware(); 检查固件 gt1x_update_judge(); 下载决定 int gt1x_update_firmware(void *filename) { update_info.status = UPDATE_STATUS_RUNNING; update_info.progress = 0; gt1x_enter_update_mode(); ret = gt1x_update_prepare(filename); ret = gt1x_check_firmware(); ............ }调用request_firmware(&update_info.fw,GT1X_FW_NAME, 1x_i2c_client->dev) 从用户空间获取获取固件 int gt1x_update_prepare(char *filename) { int ret = 0; int retry = 5; if(filename == NULL) { update_info.fw_name = NULL; update_info.fw = NULL; ret = request_firmware(&update_info.fw, GT1X_FW_NAME, 1x_i2c_client->dev); if(ret data; update_info.fw_length = update_info.fw->size; } else { GTP_INFO("Firmware: %s", filename); update_info.old_fs = get_fs(); set_fs(KERNEL_DS); //将其能访问的空间限制扩大到KERNEL_DS,这样就能在内核中顺利使用内核调用了 update_info.fw_name = filename; update_info.update_type = UPDATE_TYPE_FILE;二.手势识别流程分析 原理: 在Gesture模式下,IC检测到手指在屏幕滑动足够的长度,双击动作,和自定义字符,中断产生后会上报相应事件。 下面是手势唤醒一些定义和方法 #ifdef CONFIG_GTP_GESTURE_WAKEUP extern DOZE_T gesture_doze_status; //手势睡眠状态 extern int gesture_enabled; extern void gt1x_gesture_debug(int on) ; //手势处理方法 extern s32 gesture_event_handler(struct input_dev *dev); //手势睡眠方法 extern s32 gesture_enter_doze(void); extern void gesture_clear_wakeup_data(void); #endif #define KEY_GES_REGULAR KEY_F2 // regular gesture-key #define KEY_GES_CUSTOM KEY_F3 //customize gesture-key 二.下面是手势唤醒流程://1.中断申请成功后会执行中断函数gt1x_ts_irq_handler() 线程中断上下文中调用的函数 gt1x_ts_work_thread() 注意: 在 Linux 中,中断具有最高的优先级。不论在任何时刻,只要产生中断事件,内核将立即执行相应的中断处理程序,等到所有挂起的中断和软中断处理完毕后才能执行正常的任务,因此有可能造成实时任务得不到及时的处理。中断线程化之后,中断将作为内核线程运行而且被赋予不同的实时优先级,实时任务可以有比中断线程更高的优先级。这样,具有最高优先级的实时任务就能得到优先处理,即使在严重负载下仍有实时性保证。但是,并不是所有的中断都可以被线程化,比如时钟中断,主要用来维护系统时间以及定时器等,其中定时器是操作系统的脉搏,一旦被线程化,就有可能被挂起,这样后果将不堪设想,所以不应当被线程化。 static s32 gt1x_request_irq(void) { s32 ret = -1; const u8 irq_table[] = GTP_IRQ_TAB; GTP_DEBUG("INT trigger type:%x", gt1x_int_type); ret = devm_request_threaded_irq(1x_i2c_client->dev, gt1x_i2c_client->irq, gt1x_ts_irq_handler, gt1x_ts_work_thread, irq_table[gt1x_int_type], gt1x_i2c_client->name, gt1x_i2c_client); if(ret) { GTP_ERROR("Request IRQ failed!ERRNO:%d.", ret); return -1; } else { gt1x_irq_disable(); return 0; } }//2.执行gt1x_ts_work_thread()后 会执行手势执行函数 gesture_event_handler(input_dev); static irqreturn_t gt1x_ts_work_thread(int irq, void *data) { u8 point_data[11] = { 0 }; u8 end_cmd = 0; u8 finger = 0; u8 fod_flag = 0; //add by liuyang3.wt s32 ret = 0; if(update_info.status) { GTP_DEBUG("Ignore interrupts during fw update."); return IRQ_HANDLED; } #ifdef CONFIG_GTP_GESTURE_WAKEUP ret = gesture_event_handler(input_dev); if(ret >= 0) goto exit_work_func; #endif }//3.gesture_event_handler(input_dev)函数 :获取手势数据,类型,和上报事件 s32 gesture_event_handler(struct input_dev * dev) { u8 doze_buf[4] = { 0 }, ges_type; static int err_flag1 = 0, err_flag2 = 0; int len, extra_len, need_chk; unsigned int key_code = 0; s32 ret = 0; if(DOZE_ENABLED != gesture_doze_status) { return -1; } .......... 三.开短路测试流程3.1开短路测试方式: 确认在器件测试时所有的信号引脚都与测试系统相应的通道在电性能上完成了连接,并且没有信号引脚与其他信号引脚、 电源或地发生短路。 3.2开短路测试好处
1.快速发现芯片的各个引脚间的是否有短路 2.检测出DUT是否存在电性物理缺陷,如引脚短路、bond wire缺失、引脚的静电损坏、以及制造缺陷 3.还能发现测试时接触是否良好,探针卡或测试座是否有问题. 3.3 开短路测试流程 //1. gt1x_ts_probe() =>驱动初始化后会执行 gtp_test_sysfs_init(); static int gt1x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { //Add for openshort test; gtp_test_sysfs_init(); mz_appid_init(); mz_gesture_init(); return 0; }//==>2.gtp_test_sysfs_init() 主要操作: kobject_create_and_add 动态创建一个kobject结构并注册到sysfs 例如: 目录项(/sys/kernel/gt1x_test):通过函数 kobject_create_and_add("gt1x_test", NULL)可以在/sys/kernel下建立一个helloworld目录项。 sysfs_create_file 属性文件(dev_attr_openshort.attr)通过函数sysfs_create_file(gt1x_debug_kobj, &dev_attr_openshort.attr)建立。 这个也同时建立了文件与操作之间的联系和对应。 s32 gtp_test_sysfs_init(void) { gt1x_debug_kobj = kobject_create_and_add("gt1x_test", NULL); if(gt1x_debug_kobj == NULL) { GTP_ERROR("%s: subsystem_register failed\n", __func__); return -ENOMEM; } ret = sysfs_create_file(gt1x_debug_kobj, &dev_attr_openshort.attr); if(ret) { GTP_ERROR("%s: sysfs_create_openshort_file failed\n", __func__); return ret;} } DEBUG("GT1X debug sysfs create successwtfadd\n"); GTP_INFO("GT1X debug sysfs create success!\n"); .....//3. DEVICE_ATTR()函数 触发条件 使用DEVICE_ATTR,可以实现驱动在sys目录自动创建文件,我们只需要实现show和store函数即可.然后在应用层就能通过cat和echo命令来对sys创建出来的文件进行读写驱动设备,实现交互. 注意: 在使用cat命令时,将会调用函数gtp_sysfs_openshort_show(); 使用echo命令时,将会调用gtp_sysfs_openshort_store函数. static DEVICE_ATTR(openshort, 0664, gtp_sysfs_openshort_show, gtp_sysfs_openshort_store); //4.在使用cat命令时,将会调用函数gtp_sysfs_openshort_show(); => 会执行init_chip_type() 和 open_short_test(result)操作 static ssize_t gtp_sysfs_openshort_show(struct device *dev, struct device_attribute *attr, char *buff) { unsigned char *result; ssize_t i, len = 0, ret; init_chip_type(); // malloc(300) 动态分配一个300个大小的内存, result = (unsigned char *)malloc(300); //+Bug436464,liuyang3.wt,ADD,20190402,Coverity Test CID70911 if(!result) return -ENOMEM; //-Bug436464,liuyang3.wt,ADD,20190402,Coverity Test CID70911 //开短路测试方法 ret = open_short_test(result); if(ret 5) { WARNING("read rawdata timeout."); break; } be_normal(); continue; } ret = _check_rawdata_proc(test_types, rawdata, sys.sensor_num * sys.driver_num, save_path); if(ret < 0) { WARNING("raw data test proc error."); break; } else if(ret == 1) { DEBUG("rawdata check finish."); break; } times++; } TEST_COMPLETE: ret = test_error_code; #if GTP_SAVE_TEST_DATA // if ((check_types & _TEST_RESULT_SAVE) != 0) { _save_test_result_data(save_path, test_types, short_result); } #endif
7.在使用echo命令时,将会调用gtp_sysfs_openshort_store函数. static ssize_t gtp_sysfs_openshort_store(struct device *dev, struct device_attribute *attr, const char *buff, size_t count) { DEBUG("openshort_store"); buf = (unsigned char *)malloc(100); if(buf == NULL) { return -1; } // a+ 以附加方式打开可读写的文件 /sdcard/test.csv fp = fopen("/sdcard/test.csv", "a+"); if(fp == NULL) { DEBUG("open /sdcard/test.csv fail"); free(buf); return -1; } bytes += sprintf(&buf[bytes], "%d,", i); } DEBUG("%s", buf); fwrite(buf, bytes, 1, fp);
本人有写不对地方,欢迎大家指出, https://mp.csdn.net/postedit
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |