分享

Android sensors移植文档

 dwlinux_gs 2014-07-18

1  硬件工作原理

1.1 G-sensor主要管脚定义

上图是LIS3DHTR在TD_100中的原理图

       电压:VDD:sensor的供电电源。

      VDD_IO:sensor的IO电源。

       中断:ACCEL_INT1

      ACCEL_INT2:sensor的中断pin脚

       I2C:I2C_SCL

     I2C_SDA:sensor和处理器通过I2C总线用I2C协议通信。

硬件上的正确连接才能确保sensor的正常工作。

具体详细的定义见原理图和datasheet。

1.2 Gsensor的工作原理

  

芯片会把感知的重力加速度分解在XYZ三个方向,经过模数转换通过I2C总线和处理器通信。

1.3 datasheet中Gsensor的重要寄存器

   主要的是一些配置寄存器,需要通过他们来实现sensor在不同模式下的转换和一些功能设置。Gsensor的寄存器不是太多,可以参考datasheet。

2  软件目录结构

2.1 java层

Java层sensor的状态控制有SesnorService来负责, 它的java代码和JNI代码分别位于

       frameworks/base/services/java/com/android/server/SensorService.java

       frameworks/base/services/jni/com_android_server_SensorService.cpp

 

在java层Sensor的数据控制有SensorManager来负责,它的java代码和JNI代码分别位于:

       frameworks/base/core/java/android/hardware/SensorManager.java

       frameworks/base/core/jni/android_hardware_SensorManager.cpp

 

2.2 hardware层

   Android对于Sensor的API定义在hardware/libhardware/include/hardware/sensor.h中,要求在sensor.so提供8个API函数(在第四部分会详细说明)

2.3 HAL层

          Vendor/marvell/dkb/libsensor目录下有lib_sensor.c和Android.mk

          vendor/marvell/generic/sensors-hal目录下有marvell sensors HAL层的实现

   这一层的实现代码最后会在编译的过程中生成一个sensor.default.so.放在system/lib/hw下。

2.4 内核驱动层

   Kernel/kernel/driver/hwmon目录下有sensors(例如:重力加速度计,陀螺仪,磁力计,光与距离传感器等)的驱动文件。

3  移植新模块

3.1  HAL层

在sensor的HAL代码已经实现的情况下,只要在sensor的信息列表的结构体中添加新的sensor信息就可以,以marvell的代码为例,只需要在结构体

sensor_info_t sensors[] = {

   {

       .name = "accelerometer",        

       .vendor = "ST",              

       .version = 1,                

       .type = SENSOR_TYPE_ACCELEROMETER,

       .max_range = 2.0f * GRAVITY_EARTH,        

       .resolution = GRAVITY_EARTH/2048,     

       .power = 0,                      

       .minDelay = 20,

       .convert = &(convert_accelerometor), 

   },

};

中添加新的sensor信息就可以。

3.2 内核层

   在kernel/kernel/driver/hwmon的目录下添加sensor的驱动文件(lis3dh_acc.c),如果有.h文件放在相应的目录下,使驱动中包含的头文件可以在编译时被找到,以lis3dh为例。

       在kernel/kernel/driver/hwmon下添加驱动文件lis3dh_acc.c,在kernel/include/linux/I2C下添加lis3dh.h。

       在kernel/kernel/driver/hwmon下的Kconfig和Makefile修改如下:

             config SENSORS_LIS3DH

         tristate "STMicroelectronics LIS3DH Accelerometer Sensor"

         depends on I2C

 

              config SENSORS_LIS3DH_POSITION

         int "LIS3DH_ACCELELEROMETER Mounting Position on Board"

         depends on SENSORS_LIS3DH

         default "0"

         help

           Chip mounting position (pin 1).

             0: top. upper-left

             1: top. upper-right

             2: top. lower-right

             3: top. lower-left

             4: bottom. upper-left

             5: bottom. upper-right

             6: bottom. lower-right

             7: bottom. lower-left

             obj-$(CONFIG_SENSORS_LIS3DH)    += lis3dh_acc.o

       在版文件中添加并把编译开关打开

             在板文件中要传的平台数据

#ifdef CONFIG_SENSORS_LIS3DH

static struct lis3dh_acc_platform_data lis3dh_pdata = {

  .poll_interval = 10,

  .min_interval  = 10,

    .axis_map_x    = 0,

    .axis_map_y    = 1,

    .axis_map_z    = 2,

 

  .negate_x      = 1,

  .negate_y      = 0,

  .negate_z      = 1,

  .gpio_int1     = 51,

  .gpio_int2     = 52,

};

         #endif

             在板文件中添加lis3dh的驱动

static struct i2c_board_info ttc_dkb_i2c_info[] = {

  {

      .type      = "88PM860x",

      .addr      = 0x34,

      .platform_data    = &ttc_dkb_pm8607_info,

      .irq       = IRQ_PXA910_PMIC_INT,

  },

    #if defined(CONFIG_SENSORS_LIS3DH)

  {

      .type      = "lis3dh_acc",

      .addr      0x18,

      .platform_data    = &lis3dh_pdata,

  },

#endif

};

             在kernel/kernel/arch/arm/configs/pxa910_config文件中添加

      CONFIG_SENSORS_LIS3DH=y

      CONFIG_SENSOR_LIS3DH_POSITION=0

4  模块核心代码分析

4.1 Android上层应用APK到G-sensor driver的大致流程:

4.1.1  java层

       Java层sensor的状态控制有SesnorService来负责, 它的java代码和JNI代码分别位于 :

frameworks/base/services/java/com/android/server/SensorService.java

frameworks/base/services/jni/com_android_server_SensorService.cpp

 

       在java层Sensor的数据控制有SensorManager来负责,它的java代码和JNI代码分别位于:

frameworks/base/core/java/android/hardware/SensorManager.java

frameworks/base/core/jni/android_hardware_SensorManager.cpp

 

       Android  framework中与sensor通信的是sensorService.java和sensorManager.java

             sensorService.java的具体通信是通过JNI调用sensorService.cpp中的方法实现的。

             sensorManager.java的具体通信是通过JNI调用sensorManager.cpp中的方法实现的.

 

       sensorService.cpp 和 sensorMansger.cpp通过hardware.c与sensor.default.so通信。其中sensorService.cpp实现对sensor的状态控制,sensorManager.cpp实现对sensor的数据控制。sensor.default.so通过Ioctl控制sensor driver的状态,通过打开sensor driver对应的设备文件读取G-sensor采集的数据。

 

       Android SDK提供了4个类用于sensor通信,分别为sensor, sensorEvent, sensorEventListener,sensorManager。其中sensorEventListener用来在sensorManager中注册需要监听的sensor类型。

 

       sensorManager.java提供register(),unregister()接口供sensorEventListener使用。sensorManager.java不断轮询从sensor.default.so中取数据,取到数据后送给负责监听此类型sensor的sesnorEventListener.java,,sesnorEventListener.java通过在sensorManager.java中注册可以监听特定类型的sensor传来的数据。

 

       系统启动时执行systemProcess,会启动sensorService.java, 在sensorService.java的构造函数中调用JNI方法_sensor_control_init()。senosrService.cpp中相应的方法android_int()会被执行。该函数会调用hardware.c中的方法hw_get_module()此函数又通过load()函数在system/lib/hw下查找sensor.default.so。查找时会根据hardware.c中定义好的sensor.*.so的扩展名的顺序查找,找到第一匹配的时候即停止,并将该sensor.default.so中定义好的一个全局变量HAL_MODULE_INFO_SYM带回。该变量包含的一个重要信息是它的一个成员结构变量中包含的一个函数指针open,该指针所指函数会对一个device结构变量赋值,从而带出sensorService.cpp和sensorManager.cpp与sensor通信所需要的全部信息。Device结构变量有两种变体分别供sensorService.cpp和sensorManager.cpp使用。其中主要是一些函数指针指向与sensor通信的函数。sensorService.cpp和sensorManager.cpp在得到HAL_MODULE_INFO_SYM结构后都会调用sensor.h的inline函数open()通过HAL_MODULE_INFO_SYM的open函数指针将所需的device信息取回。

 

   系统在启动activityManager.java时,它会启动sensorManager.java,它也会调用hardware.c中的方法hw_get_module()带回HAL_MODULE_INFO_SYM。

 

4.1.2  硬件抽象层

Android对于Sensor的API定义在hardware/libhardware/include/hardware/sensor.h中,要求在sensor.so提供以下8个API函数

控制方面:

Int(*open_data_source)(struct sensor_control_device_t *dev);

Int(*activate)(struct sensor_control_device_t *dev, int handle, int enable);

Int(*set_delay)(struct sensor_control_device_t *dev, int32_t ms);

Int(*wake)(struct sensor_control_device_t *dev);

数据方面:

Int(*data_open)(struct sensor_data_device_t *dev, int fd);

Int(*data_close)(struct sensor_data_device_t *dev);

Int(*poll)(struct sensor_data_device_t *dev, sensor_data_t *data);

模块方面

Int(*get_sensor_list)(struct sensors_module_t *module,  struct sensor_t const**list);

4.2  G-sensor driver工作的大致流程:

    系统开机后。先加载i2c总线驱动,然后加载设备驱动。

在设备驱动中的init函数中通过i2c_add_driver(&lis3dh_i2c_driver)注册i2c_driver;此函数将driver注册到i2c_bus_type的总线上,此总线的匹配规则是利用i2c_client的名称和i2c_driver中id_table中的名称做匹配。其中i2c_client是注册版载信息是系统自动创建的,注册板载信息的过程就是在kernel/kernel/arch./arm/mach-mmp/tty_dkb.c文件中的结构变量中添加G-sensor的设备信息(前面已讲过)。当匹配成功时, I2c_driver中的probe()函数开始执行。

Probe()函数主要完成以下功能:

        创建G-sensor的工作队列

        注册input_devices设备

        读取chip ID

        设置寄存器,使能G-sensor

        设置并启动中断

当G-sensor上报数据的时候会触发中断,然后在中断处理函数中提交一个报值的任务到队列中并禁止中断。在工作队列中读数G-sensor的数据并上报到input子系统中,最后使能中断。

 

5  调试

5.1  软硬件调试

   驱动的调试一般要从硬件和软件两方面来调试,确定问题是处在软件还是硬件方面,不过sensor的硬件方面的连接不如一些设备(比如摄像头)那么复杂。

硬件方面:

       测量电压,还有一些频脚的高低电平(这些要根据datasheet判断是否正确)

软件方面:

       可以根据串口打印出的LOG判断驱动是否加载成功,在那些地方有错。

5.2  调试过程中的具体问题

       Gsesnor的i2c地址不对,如果i2c的地址不正确在系统起来时内核会有log出来,可以参考datasheet中的I2C的写地址,可以问厂商是否需要移位。

       创建设备属性问题

在驱动中需要创建设备文件系统的节点,驱动中创建的节点要和HAL层要打开的设备节点路径匹配,才能够实现两层之间的调用。

       没有数据读出问题。

在驱动中有数据上报,而在HAL层却没有数据读出,对驱动中数据处理的方式不对,这个参考datasheet,在驱动或HAL层做相应处理就可以在HAL层读到数据。

       数据的正负不正确的问题

有时gsensor会出现转屏不正常,这可能是sensor上报的数据的有问题,在sensor的datasheet中有说明,sensor在板子上的放置方式会影响到sensor三轴数据的正负,驱动中要根据sensor在板子上的放置方式和上层的数据要求确定数据的方向。

       hal层的问题

在HAL层要添加sensor的设备信息,如果需要要在HAL层实现数据转换。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多