zoukankan      html  css  js  c++  java
  • linux驱动由浅入深系列:高通sensor架构实例分析之三(adsp上报数据详解、校准流程详解)【转】

    本文转载自:https://blog.csdn.net/radianceblau/article/details/76180915

    本系列导航:

    linux驱动由浅入深系列:高通sensor架构实例分析之一(整体概览+AP侧代码分析)

    linux驱动由浅入深系列:高通sensor架构实例分析之二(adsp驱动代码结构)
    linux驱动由浅入深系列:高通sensor架构实例分析之三(adsp上报数据详解、校准流程详解)


    从adsp获取数据的方法分为同步、异步两种方式,但一般在实际使用中使用异步方式,因为同步获取数据会因外设总线速率低的问题阻塞smgr,降低效率,增加功耗。

    Sensor上报数据的方式分为如下几种

    sync          同步数据上报,(每次上报一个数据)

    async        异步数据上报,每次请求之后不阻塞,定时查看状态,(收到一个数据即上报)

    self-scheduling         异步数据上报,每次请求之后不阻塞,等待中断或定时查看状态,(收到一个数据即上报)

    FIFO          异步数据上报,每次请求一组数据,当传感器数据累积设定水位,由水位中断触发一组数据上报。

    S4S(Synchronization for Sensors)              用来同步时钟,避免数据遗漏或同一数据被取两次

    在实际使用中归纳起来分成3种方式:

    1,  (Polling)0x00同步方式[sync]:smgr向传感器请求数据,阻塞等待数据到来再返回;异步方式[async]:调用一次get_data后启动timer,等timer中断到达后调用sns_ddf_driver_if_s中指定的handle_timer()函数上报一组传感器数据。handle_timer()中一般采用ddf提供的sns_ddf_smgr_notify_data()函数上报数据。

    2,  (DRI)0x80又称作[self-scheduling]调用enable_sched_data()启用DRI(DataReadyInterrupt,数据完成中断),等待数据完成中断或启动timer按照set_cycle_time指定的ODR(Output Data Rate,数据输出速率)进行数据采集,采集完成后调用sns_ddf_driver_if_s中指定的handle_irq()函数上报传感器数据。

    3,  (FIFO)0xD0调用trigger_fifo_data()函数启动FIFO模式,当数据量到达指定的阈值,触发sns_ddf_smgr_data_notify()函数上报一批数据。

    (handle_irq->report_data->sns_ddf_smgr_notify_data  上报数据)

     一般加速度、陀螺仪等数据量较大的使用FIFO模式,光线、距离等有数据有变化才需要上报的传感器使用DRI模式。

    下面以g-sensor bmi160为例具体分析一下:

    sns_ddf_driver_if_s SNS_DD_IF_BMI160 =
    {

    .init = &sns_dd_bmi160_init,

    .get_data = &sns_dd_bmi160_get_data,

    .set_attrib = &sns_dd_bmi160_set_attr,

    .get_attrib = &sns_dd_bmi160_get_attr,

    .handle_timer = &sns_dd_bmi160_handle_timer,

    .handle_irq = &sns_dd_bmi160_interrupt_handler,

    .reset = &sns_dd_bmi160_reset,

    .run_test = &sns_dd_bmi160_self_test,

    .enable_sched_data = &sns_dd_bmi160_enable_sched_data,

    .probe = &sns_dd_bmi160_probe,

    .trigger_fifo_data = &sns_dd_bmi160_trigger_fifo_data
    };
    这个结构体是实现高通adsp下sensor驱动的关键,驱动程序只需要实现相应的函数,然后将结构体指针填到smgr_sensor_fn_ptr_map表中就会被系统注册了。

    仔细观察上述结构体中的函数发现有的函数在sns_dd_xxxx.c文件中如sns_dd_bmi160_init,有的则在sns_dd_xxxx_uimg.c文件中中如&sns_dd_bmi160_get_data,其实这是一种高通adsp侧代码特有的架构,即带有uimg标识的代码运行在缓存中,其中代码一般是做数据上报相关工作的,运行期间可以将外部ddr关闭以实现最低功耗的传感器运行;不带有umig标识的代码运行期间是需要ddr开启的,其中代码一般做一些初始化相关的工作。

    下面列出高通平台上对传感器类型的编号,有一个整体认识。
    typedef enum
    {
    SNS_DDF_SENSOR__NONE, // 0
    SNS_DDF_SENSOR_ACCEL, // 1
    SNS_DDF_SENSOR_MAG, // 2
    SNS_DDF_SENSOR_GYRO, // 3
    SNS_DDF_SENSOR_TEMP, // 4
    SNS_DDF_SENSOR_PROXIMITY, // 5
    SNS_DDF_SENSOR_AMBIENT, // 6
    SNS_DDF_SENSOR_PRESSURE, // 7
    SNS_DDF_SENSOR_MAG_6D, // 8
    SNS_DDF_SENSOR_GYRO_6D, // 9
    SNS_DDF_SENSOR_DOUBLETAP, // 10
    SNS_DDF_SENSOR_SINGLETAP, // 11
    SNS_DDF_SENSOR_IR_GESTURE, //12
    SNS_DDF_SENSOR_OEM_SENSOR_01, // 13
    SNS_DDF_SENSOR_OEM_SENSOR_02, // 14
    SNS_DDF_SENSOR_OEM_SENSOR_03, // 15
    SNS_DDF_SENSOR_OEM_SENSOR_04, // 16
    SNS_DDF_SENSOR_OEM_SENSOR_05, // 17
    SNS_DDF_SENSOR_OEM_SENSOR_06, // 18
    SNS_DDF_SENSOR_OEM_SENSOR_07, // 19
    SNS_DDF_SENSOR_OEM_SENSOR_08, // 20
    SNS_DDF_SENSOR_OEM_SENSOR_09, // 21
    SNS_DDF_SENSOR_OEM_SENSOR_10, // 22
    SNS_DDF_SENSOR_STEP_EVENT, // 23
    SNS_DDF_SENSOR_STEP_COUNT, // 24
    SNS_DDF_SENSOR_SMD, // 25
    SNS_DDF_SENSOR_GAME_RV, // 26
    SNS_DDF_SENSOR_HUMIDITY, // 27
    SNS_DDF_SENSOR_RGB, // 28
    SNS_DDF_SENSOR_CT_C, // 29
    SNS_DDF_SENSOR_SAR, // 30
    SNS_DDF_SENSOR_HALL_EFFECT, // 31
    SNS_DDF_SENSOR_AMBIENT_TEMP, // 32
    SNS_DDF_SENSOR_ULTRA_VIOLET, // 33
    SNS_DDF_SENSOR_HEART_RATE, //34
    SNS_DDF_SENSOR_HEART_RATE_RAW, //35
    SNS_DDF_SENSOR_OBJECT_TEMP, //36
    SNS_DDF_SENSOR_TILT_EVENT, //37
    SNS_DDF_SENSOR_ORIENTATION_EVENT, //38

    SNS_DDF_SENSOR__ALL, /**< Addresses all sensors */
    SNS_DDF_SENSOR_LAST
    } sns_ddf_sensor_e;
    在具体看数据流程之前,先了解一下高通定义的各种用来配置传感器的属性

    typedef enum
    {
    SNS_DDF_ATTRIB_POWER_INFO,//0
    SNS_DDF_ATTRIB_POWER_STATE,//1
    SNS_DDF_ATTRIB_DELAYS,//2
    SNS_DDF_ATTRIB_RANGE,//3
    SNS_DDF_ATTRIB_RESOLUTION_ADC,//4
    SNS_DDF_ATTRIB_RESOLUTION,//5
    SNS_DDF_ATTRIB_LOWPASS,//6
    SNS_DDF_ATTRIB_MOTION_DETECT,//7
    SNS_DDF_ATTRIB_DRIVER_INFO,//8
    SNS_DDF_ATTRIB_DEVICE_INFO,//9
    SNS_DDF_ATTRIB_THRESHOLD,//10
    SNS_DDF_ATTRIB_ACCURACY,//11
    SNS_DDF_ATTRIB_BIAS,//12
    SNS_DDF_ATTRIB_ODR,//13
    SNS_DDF_ATTRIB_SUPPORTED_ODR_LIST,//14
    SNS_DDF_ATTRIB_REGISTRY_GROUP,//15
    SNS_DDF_ATTRIB_IO_REGISTER,//16
    SNS_DDF_ATTRIB_FIFO,//17
    SNS_DDF_ATTRIB_ODR_TOLERANCE,//18
    SNS_DDF_ATTRIB_FILTER_DELAY//19

    } sns_ddf_attribute_e;


    初始化流程

    1,probe

    2,init

    3,get_attr

    SNS_DDF_ATTRIB_RESOLUTION_ADC

    SNS_DDF_ATTRIB_LOWPASS,

    SNS_DDF_ATTRIB_ODR,

    SNS_DDF_ATTRIB_SUPPORTED_ODR_LIST,

    SNS_DDF_ATTRIB_FIFO,

    SNS_DDF_ATTRIB_DEVICE_INFO,

    SNS_DDF_ATTRIB_POWER_INFO,

    SNS_DDF_ATTRIB_RESOLUTION,

    SNS_DDF_ATTRIB_RANGE,

    4,reset

    FIFO模式时按power键流程

    1,reset

    2,set_attr 设置SNS_DDF_ATTRIB_POWER_INFO属性

    SNS_DDF_ATTRIB_RANGE,

    SNS_DDF_ATTRIB_ODR,

    SNS_DDF_ATTRIB_FILTER_DELAY

    SNS_DDF_ATTRIB_FIFO

      

    FIFO模式数据上报流程

    enable_sched_data

    reset

    handle_timer

    interrupt_handler

    handle_irq_attach_temp

    interrupt_handler

    handle_irq_attach_temp

    ...

     DRI模式数据上报流程

    reset

    set_attr

    enable_sched_data

    reset

    handle_timer

    interrupt_handler

    handle_irq_drdy

    handle_irq_attach_temp

    interrupt_handler

    handle_irq_drdy

    handle_irq_attach_temp

    ...

     POLLING模式数据上报流程

    1,reset

    2,get_data

    3,handle_timer

    4,get_data

    5,get_data

    ...

    校准流程

    最后看一下传感器的校准流程,因为器件一致性差异等原因,每台机器的在出厂前都需要进行校准。实现校准的具体流程如下:

    1,校准app想ssc(高通传感器控制器缩写)发出校准请求

    2,ssc调用传感器驱动中sns_ddf_driver_if_s结构体中指定的run_test函数

    3,run_test 函数中由多种校准模式其中SNS_DDF_TEST_OEM模式会计算当前机器的数据bias,并存储下来。

    /**
    * Factory tests.
    */
    typedef enum
    {
    SNS_DDF_TEST_SELF, /**< Self test. */
    SNS_DDF_TEST_IRQ, /**< Interrupt test. */
    SNS_DDF_TEST_CONNECTIVITY, /**< Basic connectivity test. */
    SNS_DDF_TEST_SELF_HW, /**< Hardware self test. */
    SNS_DDF_TEST_SELF_SW, /**< Software self test. */
    SNS_DDF_TEST_OEM /**< OEM test. */

    } sns_ddf_test_e;
    4,随后ssc会调用get_attr获取SNS_DDF_ATTRIB_BIAS属性,拿到这次的校准值,最后将校准数据存放在/persist/sensor/sns.reg中
    5,之后每次SSC初始化都会从sns.reg文件中读取到当前传感器的bias值

    6,我们每次对校准后的传感器进行数据读取get_data 时,获取到的原始数据都会与这个bias值进行运算,从而返回给上层校准后的数据。

  • 相关阅读:
    lecture 11.4
    lecture 10.30
    boolean functions and beyon
    lecture10.21
    golang hex to string
    golang中 将string转化为json
    ubuntu16报错: add-apt-repository command not found
    ubuntu16的防火墙关闭
    ubuntu 16 解决错误 manpath: can't set the locale; make sure $LC_* and $LANG are correct
    go get 安装时报 (https fetch: Get https://golang.org/x/crypto/acme/autocert?go-get=1: dial tcp 220.255.2.153:443: i/o timeout)
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/10963720.html
Copyright © 2011-2022 走看看