Gsensor的整個系統架構

 

 Email:[email protected]

Blog:http://blog.csdn.net/yinwei520

Author: Yww

Time:2011-8-22

一、首先建立這樣一個全局的觀念:

    Android中sensor在Android系統架構中的位置及其工作。方框圖如下:

從以上方框圖中,可以看出Android中sensor在系統分爲四層:驅動層(Sensor Driver)、硬件抽象層(Native)、中間層(Framework)、應用層(Java)。硬件抽象層與中間層可以合併一起作爲Framework層。

針對我們xx這裏一個具體的Gsensor,下面將以具體的源碼形式來講解以上的這個系統框圖。

 

二、驅動層(Sensor Driver Layer)

芯片ADXL345爲GSensor,至於硬件的具體工作原理,須分析ADXL345的DataSheet。驅動源碼位於:xx\custom\common\kernel\accelerometer\adxl345目錄。

由於ADXL345是以I2C形式接口掛接到Linux系統,因此同時需要分析Linux的I2C子系統架構(略)。其源碼位於:

1、  xx\platform\xx\kernel\drivers\i2c

2、  kernel\drivers\i2c

查看ADXL345.c文件,分析針對於其硬件工作原理的幾個函數。硬件初始化:

 

static int adxl345_init_client(struct i2c_client *client, int reset_cali)

{

    struct adxl345_i2c_data *obj = i2c_get_clientdata(client);

    int res = 0;

 

    adxl345_gpio_config();//配置GPIO口,這裏由於不使用中斷,所以將中斷引腳配置成輸入輸出口。

    

    res = ADXL345_CheckDeviceID(client); //檢測設備ID,通過讀ADXL345的DEVID寄存器

    if(res != ADXL345_SUCCESS)

    {

        return res;

    }   

 

    res = ADXL345_SetPowerMode(client, false);//設置電源模式,ADXL345有幾種電源模式,這裏設置false值指不讓芯片處於messure模式

    if(res != ADXL345_SUCCESS)

    {

        return res;

    }

    

 

    res = ADXL345_SetBWRate(client, ADXL345_BW_100HZ);//設置帶寬,100Hz

    if(res != ADXL345_SUCCESS ) //0x2C->BW=100Hz

    {

        return res;

    }

 

    //設置數據格式,具體見datasheet

    res = ADXL345_SetDataFormat(client, ADXL345_FULL_RES|ADXL345_RANGE_2G);

    if(res != ADXL345_SUCCESS) //0x2C->BW=100Hz

    {

        return res;

    }

 

    gsensor_gain.x = gsensor_gain.y = gsensor_gain.z = obj->reso->sensitivity;

 

    //設置中斷寄存器,關閉中斷

    res = ADXL345_SetIntEnable(client, 0x00);//disable INT        

    if(res != ADXL345_SUCCESS) 

    {

        return res;

    }

 

    if(0 != reset_cali)

    { 

        /*reset calibration only in power on*/

        res = ADXL345_ResetCalibration(client);

        if(res != ADXL345_SUCCESS)

        {

            return res;

        }

    }

 

#ifdef CONFIG_ADXL345_LOWPASS

    memset(&obj->fir, 0x00, sizeof(obj->fir));  

#endif

 

    return ADXL345_SUCCESS;

}




 

    函數的分析都註釋在原理裏,紅色部分。具體寄存器的設置查看ADXL345的datasheet,具體I2C的通信查看I2C.c文件(i2c控制器的驅動)。

    關鍵問題:這裏有個問題,沒有弄懂,就是從ADXL345數據寄存器裏讀取原始數據之後,這個數據並不是我們應用程序所要用的,它需要轉化,經過查看代碼,可以發現這樣一段註釋:

/*

 * @sign, map: only used in accelerometer/magnetic field

 *   sometimes, the sensor output need to be remapped before reporting to framework.

 *   the 'sign' is only -1 or +1 to align the sign for framework's coordinate system

 *   the 'map' align the value for framework's coordinate system. Take accelerometer

 *      as an exmaple:

 *      assume HAL receives original acceleration: acc[] = {100, 0, 100}

 *      sign[] = {1, -1, 1, 0};

 *      map[]  = {HWM_CODE_ACC_Y, HWM_CODE_ACC_X, HWM_CODE_ACC_Z, 0};

 *      according to the above 'sign' & 'map', the sensor output need to remap as {y, -x, z}:

 *      float resolution = unit_numerator*GRAVITY_EARTH/unit_denominator;

 *      acc_x = sign[0]*acc[map[0]]*resolution;

 *      acc_y = sign[1]*acc[map[1]]*resolution;

 *      acc_z = sign[2]*acc[map[2]]*resolution;

 */

struct hwmsen_convert {

    s8 sign[C_MAX_HWMSEN_EVENT_NUM];

    u8 map[C_MAX_HWMSEN_EVENT_NUM];

};

這樣一個轉換算法的物理意義是怎樣的?????

三、硬件抽象層(Native)

硬件抽象層主要是提供硬件層實現的接口,其代碼路徑如下:

hardware\libhardware\include\hardware\ sensors.h

其中:

struct sensors_module_t爲sensor模塊的定義。

struct sensors_module_t {

    struct hw_module_t common;

    int (*get_sensors_list)(struct sensors_module_t* module,

                            struct sensor_t const** list);

};

 

Struct sensor_t爲某一個sensor的描述性定義。

struct sensor_t {

    const char*     name;          /*    傳感器的名稱 */

    const char*     vendor;         /* 傳感器的vendor */

    int             version;         /*    傳感器的版本 */

    int             handle;         /*    傳感器的句柄 */

    int             type;           /*    傳感器的類型 */

    float           maxRange;     /*    傳感器的最大範圍 */

    float           resolution;      /*    傳感器的辨析率 */

    float           power;         /* 傳感器的耗能(估計值,mA單位)*/

    void*           reserved[9];

}

 

struct sensors_event_t表示傳感器的數據

/**

 * Union of the various types of sensor data

 * that can be returned.

 */

typedef struct sensors_event_t {

    int32_t version; /* must be sizeof(struct sensors_event_t) */

    int32_t sensor; /* sensor identifier */

    int32_t type;   /* sensor type */

    int32_t reserved0;  /* reserved */

   int64_t timestamp;  /* time is in nanosecond */

    union {

        float     data[16];

 

        /* acceleration values are in meter per second per second (m/s^2) */

        sensors_vec_t   acceleration;

        /* magnetic vector values are in micro-Tesla (uT) */

        sensors_vec_t   magnetic;

        sensors_vec_t   orientation; /* orientation values are in degrees */

        sensors_vec_t   gyro; /* gyroscope values are in rad/s */

        float    temperature; /* temperature is in degrees centigrade (Celsius) */

        float    distance; /* distance in centimeters */

       float     light;    /* light in SI lux units */

        float     pressure; /* pressure in hectopascal (hPa) */

    };

    uint32_t        reserved1[4];

} sensors_event_t;

    顯然,在看完這些數據結構之後,我們都會有這樣一個疑問:

    這裏只是申明瞭一些結構體,而這些結構體在使用時需要定義,而且結構體中還有一些函數指針,這些函數指針所對應的函數實現又在哪裏呢??顯然,那必定還要有一個.c源文件來實現這樣的一些函數。經過搜索,其文件名爲:sensors_hwmsen.c,路徑爲:

\xxk\source\hardware\sensor\hwmsen。在這裏,你會看到get_sensors_list等函數的實現。

 

四、中間層(Framework)

    這裏,我也把它叫做JNI層,這裏實現了JNI接口。其源碼目錄如下:

frameworks\base\core\jni\ android_hardware_SensorManager.cpp

在源碼裏,我們可以看到JNI接口的函數列表:

static JNINativeMethod gMethods[] = {

    {"nativeClassInit", "()V",              (void*)nativeClassInit },

    {"sensors_module_init","()I",           (void*)sensors_module_init },

    {"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I",

                                            (void*)sensors_module_get_next_sensor },

 

    {"sensors_create_queue",  "()I",        (void*)sensors_create_queue },

    {"sensors_destroy_queue", "(I)V",       (void*)sensors_destroy_queue },

    {"sensors_enable_sensor", "(ILjava/lang/String;II)Z",

                                            (void*)sensors_enable_sensor },

 

    {"sensors_data_poll",  "(I[F[I[J)I",     (void*)sensors_data_poll },

};

這些JNI接口所對應的實現,請看源碼。

 

當然了,你可能又有疑問了,上層Java又是怎樣來調用這些本地接口的呢??在android_hardware_SensorManager.cpp源碼下面有這樣一個函數:

int register_android_hardware_SensorManager(JNIEnv *env)

{

    return jniRegisterNativeMethods(env, "android/hardware/SensorManager",

            gMethods, NELEM(gMethods));

}

這個函數就將以上的JNI接口(gMethods數組)註冊進系統。看上去很簡單,其實過程是很複雜的。整個native方法初始化過程如下:start(AndroidRuntime.cpp,938行)->startReg(AndroidRuntime.cpp,1360 行)-> register_jni_procs(AndroidRuntime.cpp,1213行)。這樣JAVA上層就能夠調用這些JNI接口來操縱底層硬件了。

 

五、應用層(Java)

傳感器系統的JAVA部分包含了以下幾個文件:

u       SensorManager.java

實現傳感器系統核心的管理類SensorManager

u       Sensor.java

單一傳感器的描述性文件Sensor

u       SensorEvent.java

表示傳感器系統的事件類SensorEvent

u       SensorEventListener.java

傳感器事件的監聽者SensorEventListener接口

u       SensorListener.java

傳感器的監聽者SensorListener接口

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章