gsensorアーキテクチャと原理分析

12380 ワード

本文は主にandroid 2について説明する.3プラットフォームG-sensor関連ソフト・ハードウェアのアーキテクチャと実現原理は、Applications、Framework、HAL、Driver、Hardwareの5つの階層でそれぞれ紹介されています.
1.システムアーキテクチャ(Architecture)
1.1 Androidアーキテクチャ図
1.2 Sensorサブシステムアーキテクチャ図
 · Application Framework
Sensorアプリケーションは、Sensorアプリケーションフレームワークを介してsensorデータを取得し、アプリケーションフレームワーク層のSensor ManagerはJNIを介してC++層と通信する.
 · Sensor Libraries
Sensor中間層は、主にSensor Manager、Sensor service、およびSensorハードウェア抽象層から構成される.
 · Input Subsystem
汎用Linux入力フレームワークは、キーボード、マウス、タッチスクリーンなどの入力デバイスに特化して設計され、標準的なイベントセットを定義しています.Sensor入力サブシステムは、/sys/class/inputノードを介してユーザ空間と対話する汎用Linux入力フレームワークを採用している.
 · Event Dev
Evedevは、/dev/input/eventX入力デバイスイベントにアクセスするための一般的な方法を提供する.
 · AccelerometerDriver
この駆動はSIRQおよびI 2 Cバスを介してMMA 7660モジュールと通信する.SIRQは、センサイベント割り込みを生成するために使用される.
 
2アプリケーション(Applications)
2.1応用開発五段階曲
(1)センサマネージャオブジェクトを取得する.
mSensorManager =(SensorManager) getSystemService(SENSOR_SERVICE);
(2)センサオブジェクトを取得する.
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
(3)イベントリスナーを定義する.
mEventListener =new SensorEventListener() {
          
           @Override
           publicvoid onSensorChanged(SensorEvent event) {
              float[] values = event.values;
              mTextView.setText("Accelerometer:" + values[0] +", "
                     + values[1] +", " + values[2]);
           }
 
           @Override
           publicvoidonAccuracyChanged(Sensor sensor,int accuracy) {
           }
       };

(4)イベントリスナーを登録する.
protectedvoid onResume() {
       super.onResume();
      
       mSensorManager.registerListener(mEventListener, mSensor,
              SensorManager.SENSOR_DELAY_NORMAL);
    }

(5)イベントリスナーをアンインストールする.
protectedvoid onPause() {
       super.onPause();
      
       mSensorManager.unregisterListener(mEventListener);
    }

3フレームワーク(Framework)
3.1作業モデル
3.1.1 SensorManagerの作成
nativeClassInit():Nativeクラス情報を初期化します.
sensors_module_Init():Native SensorManagerインスタンスを作成し、SensorServiceからSensorデバイスのリストを読み込みます.
sensors_module_get_next_sensor():SensorServiceから次のSensorデバイスを読み込みます.
3.1.2 SensorThreadデータ受信処理
sensors_create_Queue():SensorServiceと共有するメッセージキューを作成します.
sensors_data_Poll():SensorServiceから送信されたメッセージをメッセージキューから読み出す.
3.1.3 SensorServiceの動作原理
SensorDevice::poll():HALインタフェースを呼び出してデータを読み込む;
SensorEventConnection::sendEvents():メッセージキューにメッセージを書き込み、SensorThreadはその後メッセージを読み込みます.
3.1.4 SensorDeviceのHALへのアクセス
4ハードウェア抽象層(HAL)
linuxオペレーティングシステムでは、アプリケーションとハードウェアの相互作用はデバイス駆動によって実現され、Androidシステムはアプリケーション開発者の開発難易度を低減し、ハードウェアの違いを遮断するために、ハードウェア抽象層を定義し、開発者に各種デバイスに関する情報を取得するインタフェースを提供する.
4.1 Sensors HALキーフロー
4.1.1 Sensorデバイスを開く
SensorBase::openInput():inputサブシステムのsensorメッセージファイルハンドルを開く;
ioctl(EVIOCGABS(...)) : ABS_を取得X/ABS_Y/ABS_Zの加速度
4.1.2ラウンドシーサー事件
InputEventCircularReader::fill():read()を呼び出してinputサブシステムからイベントを読み込み、リングバッファに入れます.
InputEventCircularReader::readEvent()ループバッファからイベントを読み込む;
InputEventCircularReader::next():リングバッファの現在のポインタを移動します.
5.2 Sensors HALキーデータ構造
5.2.1 sensors_module_t
struct sensors_module_t {
    struct hw_module_t common;

    /**
     * Enumerate all available sensors. The list is returned in "list".
     * @return number of sensors in the list
     */
    int (*get_sensors_list)(struct sensors_module_t* module,
            struct sensor_t const** list);
};

hw_get_module()は、HALモジュールをロードし、HALエントリデータ構造(hw_module_t)を返します.HAL_MODULE_INFO_SYMのデフォルトは「HAL」で、hw_get_moduleでdlsymで取得します.
const struct sensors_module_t HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .version_major = 1,
        .version_minor = 0,
        .id = SENSORS_HARDWARE_MODULE_ID,
        .name = "MMA7660 Sensors Module",
        .author = "The Android Open Source Project",
        .methods = &sensors_module_methods,
    },
    .get_sensors_list = sensors__get_sensors_list
};

5.2.2 hw_module_methods_t
 
static struct hw_module_methods_t sensors_module_methods = {
    .open = open_sensors
};

5.2.3 sensors_poll_context_t
struct sensors_poll_context_t {
    struct sensors_poll_device_t device; // must be first
    sensors_poll_context_t();
    ~sensors_poll_context_t();
    int activate(int handle, int enabled);
    int setDelay(int handle, int64_t ns);
    int pollEvents(sensors_event_t* data, int count);
    int handleToDriver(int handle);
};

5.2.4 sensors_poll_device_t
struct sensors_poll_device_t {
struct hw_device_t common;

    int (*activate)(struct sensors_poll_device_t *dev,
            int handle, int enabled);

    int (*setDelay)(struct sensors_poll_device_t *dev,
            int handle, int64_t ns);

    int (*poll)(struct sensors_poll_device_t *dev,
            sensors_event_t* data, int count);
};

5.2.5 sensor_t
センサの基本パラメータを定義します.
static const struct sensor_t sSensorList[] = {
        { "MMA7660 3-axis Accelerometer",
                "Freescale Semiconductor",
                1, SENSORS_HANDLE_BASE+ID_A,
                SENSOR_TYPE_ACCELEROMETER, 3.0f*9.81f, (3.0f*9.81f)/64.0f, 0.35f, 0, { } },
};
struct sensor_t {
    const char*     name;
    const char*     vendor; 
    int             version;
    int             handle;
    int             type;
    float           maxRange;
    float           resolution;
    float           power;
    int32_t         minDelay;
    void*           reserved[8];
};

6ドライバ
6.1 mma 7660駆動フレーム
mma 7660とホストとの通信はI 2 Cインタフェースを介しているため、mma 7660ドライバはLinuxシステムのI 2 Cサブシステムフレームワークを採用して実現され、主に3つの部分から構成されている.
 
(1)
I 2 Cコア
I 2 Cコアは、I 2 Cバス駆動とデバイス駆動の登録・ログアウト方法、I 2 C通信方法(すなわち「algorithm」)上層の、特定のアダプタに関係のないコード、およびプローブ装置、デバイスアドレスを検出する上層コードなどを提供する.この部分はプラットフォームとは関係ありません.
このセクションはLinuxカーネルのI 2 Cドライバで実現され、mma 7660ドライバは、提供された機能インタフェースを使用してデバイスドライバを登録するように駆動する.
(2)
I 2 Cバス駆動
I 2 Cバス駆動は、I 2 Cハードウェアアーキテクチャにおけるアダプタ端子の実現である.I 2 Cバス駆動は主にI 2 Cアダプタデータ構造i 2 c_を含むadapter、I 2 Cアダプタのalgorithmデータ構造i 2 c_AlgorithmとI 2 Cアダプタを制御して通信信号を生成する関数.I 2 Cバスを介して駆動されるコードは、I 2 Cアダプタがマスタ方式で開始ビット、停止ビット、読み書き周期、およびデバイス方式から読み書き、ACKなどを生成するように制御することができる.異なるCPUプラットフォームは異なるI 2 Cバス駆動に対応している.
このセクションはLinuxカーネルのI 2 Cドライバで実現され、mma 7660ドライバは提供されたadapterを直接取得し、I 2 Cコアのインタフェースを呼び出して登録する.
(3)
I 2 Cデバイス駆動
I 2 Cデバイス駆動は、I 2 Cハードウェアアーキテクチャにおけるデバイス側の実現である.装置は一般的にCPUによって制御されるI 2 Cアダプタに接続され、I 2 Cアダプタを介してCPUとデータを交換する.I 2 Cデバイス駆動は主にデータ構造i 2 c_を含むdriverとi 2 c_Client,mma 7660ドライバは、メンバー関数を実装する必要がある.
Linuxカーネルソースのdriversディレクトリの下にあるi 2 c_dev.cファイルは、I 2 Cアダプタデバイスファイルの機能を実現し、アプリケーションは「i 2 c-%d」ファイル名を使用してファイル操作インタフェースopen()、write()、read()、ioctl()、close()などを使用してこのデバイスにアクセスします.アプリケーション層は、これらのインタフェースを用いて、アダプタに接続されたI 2 Cデバイスの記憶空間またはレジスタにアクセスし、I 2 Cデバイスの動作を制御することができる.
6.2 mma 7660操作フロー
6.2.1初期化
6.2.2探知設備
6.2.3デバイスの削除
6.2.4データ収集
6.2.5睡眠と覚醒
Suspend処理:mma 7660モジュールを閉じる;
Resume処理:mma 7660モジュールを使用する;
 
static int mma7660_suspend(struct i2c_client *client, pm_message_t mesg)
{
    int result;
result = i2c_smbus_write_byte_data(client, MMA7660_MODE, 
                               MK_MMA7660_MODE(0, 0, 0, 0, 0, 0, 0));
    assert(result==0);
    return result;
}

static int mma7660_resume(struct i2c_client *client)
{
    int result;
result = i2c_smbus_write_byte_data(client, MMA7660_MODE, 
                                MK_MMA7660_MODE(0, 1, 0, 0, 0, 0, 1));
    assert(result==0);
    return result;
}

static struct i2c_driver mma7660_driver = {
    .driver = {
        .name = MMA7660_DRV_NAME,
        .owner = THIS_MODULE,
    },
    .class = I2C_CLASS_HWMON,
    .suspend = mma7660_suspend,
    .resume = mma7660_resume,
    .probe = mma7660_probe,
    .detect = mma7660_detect,
//	.address_data = &addr_data,
    .remove = __devexit_p(mma7660_remove),
    .id_table = mma7660_id,
};

6.3コマンドラインのデバッグ
6.3.1 sysfsデバッグインタフェース(1)
sysfs attribute関連データ構造を定義します.
 
static SENSOR_DEVICE_ATTR(all_axis_force, S_IRUGO, show_xyz_force, NULL, 0);
static SENSOR_DEVICE_ATTR(x_axis_force, S_IRUGO, show_axis_force, NULL, 0);
static SENSOR_DEVICE_ATTR(y_axis_force, S_IRUGO, show_axis_force, NULL, 1);
static SENSOR_DEVICE_ATTR(z_axis_force, S_IRUGO, show_axis_force, NULL, 2);
static SENSOR_DEVICE_ATTR(orientation, S_IRUGO, show_orientation, NULL, 0);

static struct attribute* mma7660_attrs[] =
{
    &sensor_dev_attr_all_axis_force.dev_attr.attr,
    &sensor_dev_attr_x_axis_force.dev_attr.attr,
    &sensor_dev_attr_y_axis_force.dev_attr.attr,
    &sensor_dev_attr_z_axis_force.dev_attr.attr,
    &sensor_dev_attr_orientation.dev_attr.attr,
    NULL
};

static const struct attribute_group mma7660_group =
{
    .attrs = mma7660_attrs,
};

(2)
probe関数にsysfsファイルシステムを作成します.
 
    result = sysfs_create_group(&client->dev.kobj, &mma7660_group);
    if (result != 0) {
        ERR("sysfs_create_group err
"); goto exit_sysfs_creat_failed; }

(3)
sysfs属性に関連する読み書き関数を実現する.
ssize_t	show_orientation(struct device *dev, struct device_attribute *attr, char *buf)
{
    int result;
u8 tilt, new_orientation;

    mma7660_read_tilt(&tilt);
    DBG("tilt [0x%x]
", tilt); new_orientation = tilt & 0x1f; if (orientation!=new_orientation) orientation = new_orientation; switch ((orientation>>2)&0x07) { case 1: result = sprintf(buf, "Left
"); break; case 2: result = sprintf(buf, "Right
"); break; case 5: result = sprintf(buf, "Downward
"); break; case 6: result = sprintf(buf, "Upward
"); break; default: switch(orientation & 0x03) { case 1: result = sprintf(buf, "Front
"); break; case 2: result = sprintf(buf, "Back
"); break; default: result = sprintf(buf, "Unknown
"); } } return result; }
ssize_t show_xyz_force(struct device *dev, struct device_attribute *attr, char *buf)
{
    int i;
    s8 xyz[3];

    for (i=0; i<3; i++)
        mma7660_read_xyz(i, &xyz[i]);

    return sprintf(buf, "(%d,%d,%d)
", xyz[0], xyz[1], xyz[2]); } ssize_t show_axis_force(struct device *dev, struct device_attribute *attr, char *buf) { s8 force; int n = to_sensor_dev_attr(attr)->index; mma7660_read_xyz(n, &force); return sprintf(buf, "%d
", force); }

 
6.3.2 Gsensorデバッグ例
/sys/devices/platform/gl5201-i2c.1/i2c-1/1-004c # ls
uevent
name
modalias
subsystem
power
driver
all_axis_force
x_axis_force
y_axis_force
z_axis_force
orientation
input
/sys/devices/platform/gl5201-i2c.1/i2c-1/1-004c # cat all_axis_force 
(-1,0,22)

7 Hardware
7.1 mma 7660モジュール
7.2重要特性
  • Sampling Resolution: 6bit
  • Digital Output (I2C)
  • 3mm x 3mm x 0.9mm DFN Package
  • Low Power Current Consumption: 

  •    
    Off Mode: 0.4 μA,
       
    Standby Mode: 2 μA, 
       
    Active Mode: 47 μA at 1 ODR
  • Configurable Samples per Second from 1 to 120 samples
  • Low Voltage Operation:

  •    
    Analog Voltage: 2.4 V - 3.6 V
       
    Digital Voltage: 1.71 V - 3.6 V
  • Auto-Wake/Sleep Feature for Low Power Consumption
  • Tilt Orientation Detection for Portrait/Landscape Capability
  • Gesture Detection Including Shake Detection and Tap Detection

  • 7.2.1機能モジュール図
    7.2.2ハードウェア接続図
    7.2.3運動検出原理
    mma 7660は容量式3軸g−sensorであり、その技術原理はwaferの表面に櫛状構造を作り、動作が発生すると検出容量差によって変形量を判断し、加速度の値を逆押し出しすることである.
    単純な物理モデルは次の図です.
    7.2.4 I 2 C読み書きタイミング
    7.2.5作動状態機械
    7.2.6レジスタ定義
    7.2.7イベント検出
  • 方向及び揺動検出
  • パッティングまたはチルト検出
  •