adb 恢复后启动无法使用问题分析

来源:互联网 发布:c语言小写变大写 编辑:程序博客网 时间:2024/04/26 14:51

V1.0

有关adb相关内容知识在本wiki内部不做说明了,具体内容可以参考 click here

根据任务一步步推进,对其按时间和要点进行划分如下:

重新启动adb程序方式

根据之前在A10以及freescale上的经验,系统恢复后adb无法使用,但是重新启动adb服务就可以使adb可以使用

因此在任务之初尝试使用这个方式解决问题

涉及到的技术

adb服务控制

adb服务在设备端名称为adbd ,adb的启动定义在init.rc文件中,具体内容如下:

service adbd /sbin/adbd

  class core  socket adbd stream 660 system system  disabled  seclabel u:r:adbd:s0

为了完成adb重启操作,可以采用的方式有两种:

1.在init.rc中添加restar的属性对应的指令序列

on property:service.adb.root=1

write /sys/class/android_usb/android0/enable 0restart adbdwrite /sys/class/android_usb/android0/enable 1

在需要使用的时候使用下面命令就可以 setprop service.adb.root 1

2.也可以使用setprop指令直接操作adb服务,具体指令如下

关闭adb服务使用 setprop ctl.stop adbd

打开adb服务使用 setprop ctl.start adbd

添加服务程序

休眠恢复之后由于adb和串口都无法使用,需要系统内部自动的去重新启动adb,为此需要添加一个服务程序,该程序能够在系统

恢复后重新启动adb。这里采用的基本思路是在init.rc中添加一个开机启动服务,该服务sleep一段时间之后执行重启adb操 作。

在该服务sleep的过程中执行休眠操作,这样,在系统恢复后该程序继续执行便会重新启动adb。

在init.rc中添加服务的方式如下:

service XXXXX /system/bin/YYYYYYY

  class main  oneshot

XXXXX 为想要的服务名称 YYYYYYY为可执行程序或者脚本的名称

实验结果

通过在系统恢复后重新启动adb的方式,无法使adb正常使用

adb程序相关调试分析

重新启动adb的方式无法使adb在恢复后的系统中正常使用,因此调试adb程序设备端和PC端,

查看是否是adb程序的通信问题。

涉及到的技术

PC端adb

PC端adb即运行在PC机上的adb程序,对程序流程进行分析,发现adb程序运行的log输出到/tmp/下

logfile的名称为adb.log ,因此在PC端启动adb之后,可以通过跟踪adb.log 文件的方式跟踪adb程序

的运行状况 :

tail -f /tmp/adb.log

设备端adb

设备端adb即运行于开发板上的adb程序,对程序流程进行分析,发现adb程序会在设备分区data上创建adb文件夹

并在该文件夹内创建名称跟时间相关的adb-log

存在问题:实际运行中,没有发现该log存在,adb程序没有能够成功创建出文件夹以及log文件

实验结果

对比系统正常启动情况下和休眠恢复后PC端adb程序响应状况

发现pc端adb程序在休眠恢复状况下无法识别到设备端任何信息

通过lsusb 指令也无法发现任何usb设备信息,初步估计是设备端出了问题

gadget driver 相关内容分析

涉及到的技术

gadget相关概念介绍

Linux-USB Gadget 驱动框架(以下简称 Gadget )实现了 USB 协议定义的设备端的软件功能。相对于 Linux USB 主机端( Host ) 驱动而言,

Gadget 驱动出现较晚,它出现在 2.4.23 以后

Gadget 框架提出了一套标准 API, 在底层, USB 设备控制器 (USB Device Controller, UDC) 驱动则实现这一套API, 不同的 UDC (通常是 SOC 的一部分) 需要不同的驱动,

甚至基于同样的 UDC 的不同板子也需要进行代码修改。这一层我们可以称之为平台相关层。

在本小节重点介绍 gadget drvier ,下一小节会介绍UDC driver。

1.源码位置:

driver/usb/gadget/android.c

2.gadget driver实现说明:

struct usb_gadget_driver {

char *function;

enum usb_device_speed speed;

int (*bind)(struct usb_gadget *);

void (*unbind)(struct usb_gadget *);

int (*setup)(struct usb_gadget *,

const struct usb_ctrlrequest *);

void (*disconnect)(struct usb_gadget *);

void (*suspend)(struct usb_gadget *);

void (*resume)(struct usb_gadget *);

struct device_driver driver;

};

这个结构表示我们的gadget驱动,其中的函数需要在gadget driver中实现,是编码的重点之一。具体实现可参考源码文件,下面简单介绍一下各个函数的功能:

Bind中主要执行gadget driver的初始化,它会被usb_gadget_register_driver函数调用,而usb_gadget_register_driver 一般在模块初始化时调用。usb_gadget_register_driver执行完之

后,device可以被主机探测到。

Unbind与bind相反,被usb_gadget_unregister_driver调用。

Setup处理主机发过来的request,例如读decriptors,配置configuration等。因此,setup函数中一 般包含switch,case语句。

Disconnect在设备与主机断开时被调用。

3.adb相关说明

针对adb设备的功能实现在android.c 中没有看到,android.c中用

#include “f_adb.c” 将adb相关功能接口引入。具体功能实现可以参考f_adb.c

将gadget编译为 module

module位置如下:

编译方式为:

实验结果

1.将gadget编译为module方式,并在系统启动后通过服务加载该module(模块名称为g_android.ko),系统可 正常工作。

2.将gadget编译为module方式,系统正常启动后通过后台服务程序执行休眠操作,休眠恢复后后台服务执行加载 g_android.ko 模块,

adb仍然无法正常使用,在g_android 中添加的log没有打印输出。

UDC 控制器相关内容分析

涉及到的技术

UDC 相关概念说明

1.源文件位置:

driver/usb/gadget/msb250x_udc.c

2.实现说明:

UDC driver 被实现为一个platform driver,结构如下

static struct platform_driver msb250x_udc_driver = {

  .probe    = msb250x_udc_probe,  .remove = msb250x_udc_remove,  .suspend = msb250x_udc_suspend,  .resume = msb250x_udc_resume,  .driver =  {      .name = "msb250x_udc",      .owner = THIS_MODULE,  }

};

通过该driver同底层硬件通信

将UDC 编译为module

UDC module位置为:

UDC module的编译方式为:

实验结果

1.将mstar UDC driver 编译为module (通过make menuconfig 修改) 产生如下五个ko文件: ms_otg.ko ms_dma.ko ms_usbmain.ko msb250x_udc.ko msb250x_udc_proc.ko 修改full_mstarcedric3.mk,将ko文件打包放入镜像中,参照modules.order 中模 块顺序,在android系统启动脚本init.rc中添加 insmod XXXX,ko语句

结果: 正常启动情况下 adb无法使用

2.编译module以及生成镜像方式不变,改变android启动脚本修改方式,在init.rc 中添加启动脚本的服务:总共添加两个服务 ,一个为休眠一段时间插入module脚本,

另一个为执行休眠脚本

结果: 休眠恢复后 adb也无法使用

3.按照设想,使用上述方式一的方式,adb应该能正常使用,初步估计可能是 module加载顺序问题 :现在总要加载的module(跟这部分相关的)共有七个

还有g_android ,以及ehci_hcd ,尝试调整加载顺序,adb仍然无法正常使用

linux中断处理相关内容分析

通过对比系统正常启动以及休眠恢复之后系统运行状况,发现在休眠恢复情况下,driver注册的中断函数在休眠恢复后的系统中不会被运 行。

通过脚本查看休眠恢复后查看中断注册情况 ,中断已经注册,插入设备,没有调用中断函数。因此对linux中断子系统的执行过程进行分析,

整理清楚从硬件中断到系统中断被执行这个过程

涉及到的技术

硬件中断到程序中断流程说明

说明: 1.asm_do_irq 即为汇编代码调用的函数口,硬件设备出发电信号之后会在汇编代码中简易处理之后调用该函数接口

2.ms_irq_handle_cascade_host0_irq 该函数口为mstar实现,通过该函数mstar将硬件中断号为31的硬件中断

根据寄存器中的值转换为中断函数对应的中断(如 2117,2123等等)

3.handle_level_irq 该函数口是电平中断的通用实现,在当前硬件情况下,系统内的中断处理被指定到该处执行

中断在程序内的实现

1.数据结构表示

struct irq_desc {

      struct irq_data         irq_data;      struct timer_rand_state *timer_rand_state;      unsigned int __percpu   *kstat_irqs;      irq_flow_handler_t      handle_irq;     /*中断函数接口*/      irq_preflow_handler_t   preflow_handler;      struct irqaction        *action;        /* 中断 action list */      unsigned int            status_use_accessors;      unsigned int            core_internal_state__do_not_mess_with_it;      unsigned int            depth;          /* nested irq disables */      unsigned int            wake_depth;     /* nested wake enables */      unsigned int            irq_count;      /* For detecting broken IRQs */      unsigned long           last_unhandled; /* Aging timer for unhandled count */      unsigned int            irqs_unhandled;      raw_spinlock_t          lock;      struct cpumask          *percpu_enabled;      const struct cpumask    *affinity_hint;      struct irq_affinity_notify *affinity_notify;      cpumask_var_t           pending_mask;      unsigned long           threads_oneshot;      atomic_t                threads_active;      wait_queue_head_t       wait_for_threads;      struct proc_dir_entry   *dir;      struct module           *owner;      const char              *name;  /*中断名称*/

} cacheline_internodealigned_in_smp;

上述结构即为中断在程序中的实现结构,在程序中我门可以通过 irq_to_desc 函数将irq号转化为该结构,方便调用中断的处理函数或者属性等等

添加调试口控制log说明

由于系统内中断会频繁被执行,因此在系统的处理中断的函数中添加的log信息会导致系统无法正常使用

为使系统在正常情况下没有log,在休眠恢复后可以打印log,可以参照toi实现的系统操纵接口来控制log的输出状况

添加说明: 1.toi 中同下面的结构定义文件操作结构:

struct toi_module_ops toi_fileops = {

      .type                                   = BIO_ALLOCATOR_MODULE,      .name                                   = "file storage",      .directory                              = "file",      .module                                 = THIS_MODULE,      .print_debug_info                       = toi_file_print_debug_stats,      .cleanup                                = toi_file_cleanup,      .bio_allocator_ops                      = &toi_bio_fileops,
      .sysfs_data             = sysfs_params,      .num_sysfs_entries      = sizeof(sysfs_params) /              sizeof(struct toi_sysfs_data),

}

为添加操作接口,需要修改其中的sysfs_params对象。 2.对sysfs_params修改示例如下,

static struct toi_sysfs_data sysfs_params[] = {

      SYSFS_STRING("target", SYSFS_RW, toi_file_target, 256,              SYSFS_NEEDS_SM_FOR_WRITE, test_toi_file_target),      SYSFS_INT("enabled", SYSFS_RW, &toi_fileops.enabled, 0, 1, 0, NULL),      SYSFS_INT("XXXX", SYSFS_RW, &YYYY, 0, 1, 0, NULL),      SYSFS_INT("priority", SYSFS_RW, &file_target_priority, -4095,                      4096, 0, NULL),

};

XXXX 为最终会看到的文件节点名称 ,YYYY 为变量名称(该变量为全局变量)

YYYY的值这里指定为0/1.

3.在中断处理函数中通过变量YYYY控制log的输出,示例如下

handle_IRQ() {

 if(YYYY)    printk("##");

}

实验结果

1.休眠恢复后,无法看到adb gadget 设备驱动中log信息,层层向上追踪,发现在ms_irq_handle_cascade_host0_irq中就

没有31号中断被转换为设备需要的2117信号。对硬件接口层调试,由于log信息太多问题导致无法确定硬件中断是否发送。

2.对比分析sd卡中断信号传递过程 ,将sd卡driver的suspend以及resume设置为空,对中断处理部分无影响


原创粉丝点击