跟蹤G-Sensor有時不起作用的問題
最近在生產反饋中,有提到批量機器中有大約2%的機器遇到不轉屏的問題。筆者通過反覆跟蹤,重現了這個問題,通過分析lsmod,看到驅動又已經加載,但是就是不起作用,再通過getevent看信息,發現沒有數據報上來,這說明有問題,G-sensor沒有報數據肯定就不轉屏了,那怎麼解決呢?
仔細分析了G-sensor的驅動,流程上也沒看出什麼問題來,當然如果流程有問題就不可能是小概率出問題了, 那應該是大面積有問題了。層層分析,還是覺得在detect處理上有疑點,全志平臺提供的驅動,讀一遍chip ID後,就判斷是不是BMA250,或者BMA250E,如果都不是就返回了,上層也就認爲沒有找到G-sensor,就不會去讀數據。通過加了一些打印後,通過大量的測試跟蹤,發現G-sensor沒有的時候,在detect的時候都沒有讀成功,於是筆者又從硬件原理圖上分析了一下,原來在同一組IIC上,不止它一個,而它就是相對比較晚加載的一個,因此在加載它驅動的時候,前一個驅動使用iic可能有忙的問題,這樣就可能造成超時,最終讀不出chip ID。那麼,我們可以在讀chip ID的時候,可以嘗試多讀幾次,一次不行,休息一會再去讀,這樣就盡了最多限度的努力去讀chip ID了,當然極端一點的還可以在讀不出chip ID的時候,也強制認爲讀到了,這樣有一個不好地方就是,不能做多種G-sensor的兼容,如果你只有一種G-sensor,這樣做也沒什麼。筆者通過這樣一修改後,通過專項測試,以及近段時間的批量生產,沒有復現了這個問題。
因此,在靠讀外設的chip ID來判斷是否存在這個硬件的時候,我們可以嘗試多讀幾次,這樣軟件的兼容性會好一點,有一個不好的地方就是,系統的啓動時間會稍微增加一點。下面就是對G-sensor detect改造的代碼:
- int gsensor_detect(struct i2c_client *client, struct i2c_board_info *info)
- {
- struct i2c_adapter *adapter = client->adapter;
- int ret;
- int retrytimes = 5;
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return -ENODEV;
- if(twi_id == adapter->nr){
- for(i2c_num = 0; i2c_num < (sizeof(i2c_address)/sizeof(i2c_address[0]));i2c_num++)
- { client->addr = i2c_address[i2c_num];
- pr_info("%s:addr= 0x%x,i2c_num:%d\n",__func__,client->addr,i2c_num);
- do {
- ret = i2c_smbus_read_byte_data(client,BMA250_CHIP_ID_REG);
- if (ret < 0) {
- printk("FAIL read value is 0x%x, retrytimes =%d\n", ret, retrytimes);
- retrytimes--;
- msleep(5);/*5ms*/
- }
- } while((retrytimes > 0) && (ret < 0));
- pr_info("Read ID value is :0x%x\n",ret);
- if ((ret &0x00FF) == BMA250_CHIP_ID){
- pr_info("Bosch Sensortec Device detected!\n" );
- strlcpy(info->type, SENSOR_NAME, I2C_NAME_SIZE);
- return 0;
- }else if((ret &0x00FF) == BMA150_CHIP_ID){
- pr_info("Bosch Sensortec Device detected!\n" \
- "BMA150 registered I2C driver!\n");
- strlcpy(info->type, SENSOR_NAME, I2C_NAME_SIZE);
- return 0;
- } else if((ret &0x00FF) == BMA250E_CHIP_ID) {
- strlcpy(info->type, SENSOR_NAME, I2C_NAME_SIZE);
- return 0;
- } else {
- /*worearound we just one gsensor*/
- pr_info("set force!!!\n");
- strlcpy(info->type, SENSOR_NAME, I2C_NAME_SIZE);
- return 0;
- }
- }
- pr_info("%s:Bosch Sensortec Device not found, \
- maybe the other gsensor equipment! \n",__func__);
- return -ENODEV;
- }else{
- return -ENODEV;
- }
- }