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爲例具體分析一下:

 


 
  1. sns_ddf_driver_if_s SNS_DD_IF_BMI160 =

  2. {

  3.  
  4. .init = &sns_dd_bmi160_init,

  5.  
  6. .get_data = &sns_dd_bmi160_get_data,

  7.  
  8. .set_attrib = &sns_dd_bmi160_set_attr,

  9.  
  10. .get_attrib = &sns_dd_bmi160_get_attr,

  11.  
  12. .handle_timer = &sns_dd_bmi160_handle_timer,

  13.  
  14. .handle_irq = &sns_dd_bmi160_interrupt_handler,

  15.  
  16. .reset = &sns_dd_bmi160_reset,

  17.  
  18. .run_test = &sns_dd_bmi160_self_test,

  19.  
  20. .enable_sched_data = &sns_dd_bmi160_enable_sched_data,

  21.  
  22. .probe = &sns_dd_bmi160_probe,

  23.  
  24. .trigger_fifo_data = &sns_dd_bmi160_trigger_fifo_data

  25. };

 

這個結構體是實現高通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開啓的,其中代碼一般做一些初始化相關的工作。

 

下面列出高通平臺上對傳感器類型的編號,有一個整體認識。

 


 
  1. typedef enum

  2. {

  3. SNS_DDF_SENSOR__NONE, // 0

  4. SNS_DDF_SENSOR_ACCEL, // 1

  5. SNS_DDF_SENSOR_MAG, // 2

  6. SNS_DDF_SENSOR_GYRO, // 3

  7. SNS_DDF_SENSOR_TEMP, // 4

  8. SNS_DDF_SENSOR_PROXIMITY, // 5

  9. SNS_DDF_SENSOR_AMBIENT, // 6

  10. SNS_DDF_SENSOR_PRESSURE, // 7

  11. SNS_DDF_SENSOR_MAG_6D, // 8

  12. SNS_DDF_SENSOR_GYRO_6D, // 9

  13. SNS_DDF_SENSOR_DOUBLETAP, // 10

  14. SNS_DDF_SENSOR_SINGLETAP, // 11

  15. SNS_DDF_SENSOR_IR_GESTURE, //12

  16. SNS_DDF_SENSOR_OEM_SENSOR_01, // 13

  17. SNS_DDF_SENSOR_OEM_SENSOR_02, // 14

  18. SNS_DDF_SENSOR_OEM_SENSOR_03, // 15

  19. SNS_DDF_SENSOR_OEM_SENSOR_04, // 16

  20. SNS_DDF_SENSOR_OEM_SENSOR_05, // 17

  21. SNS_DDF_SENSOR_OEM_SENSOR_06, // 18

  22. SNS_DDF_SENSOR_OEM_SENSOR_07, // 19

  23. SNS_DDF_SENSOR_OEM_SENSOR_08, // 20

  24. SNS_DDF_SENSOR_OEM_SENSOR_09, // 21

  25. SNS_DDF_SENSOR_OEM_SENSOR_10, // 22

  26. SNS_DDF_SENSOR_STEP_EVENT, // 23

  27. SNS_DDF_SENSOR_STEP_COUNT, // 24

  28. SNS_DDF_SENSOR_SMD, // 25

  29. SNS_DDF_SENSOR_GAME_RV, // 26

  30. SNS_DDF_SENSOR_HUMIDITY, // 27

  31. SNS_DDF_SENSOR_RGB, // 28

  32. SNS_DDF_SENSOR_CT_C, // 29

  33. SNS_DDF_SENSOR_SAR, // 30

  34. SNS_DDF_SENSOR_HALL_EFFECT, // 31

  35. SNS_DDF_SENSOR_AMBIENT_TEMP, // 32

  36. SNS_DDF_SENSOR_ULTRA_VIOLET, // 33

  37. SNS_DDF_SENSOR_HEART_RATE, //34

  38. SNS_DDF_SENSOR_HEART_RATE_RAW, //35

  39. SNS_DDF_SENSOR_OBJECT_TEMP, //36

  40. SNS_DDF_SENSOR_TILT_EVENT, //37

  41. SNS_DDF_SENSOR_ORIENTATION_EVENT, //38

  42.  
  43. SNS_DDF_SENSOR__ALL, /**< Addresses all sensors */

  44. SNS_DDF_SENSOR_LAST

  45. } sns_ddf_sensor_e;

 

在具體看數據流程之前,先了解一下高通定義的各種用來配置傳感器的屬性

 


 
  1. typedef enum

  2. {

  3. SNS_DDF_ATTRIB_POWER_INFO,//0

  4. SNS_DDF_ATTRIB_POWER_STATE,//1

  5. SNS_DDF_ATTRIB_DELAYS,//2

  6. SNS_DDF_ATTRIB_RANGE,//3

  7. SNS_DDF_ATTRIB_RESOLUTION_ADC,//4

  8. SNS_DDF_ATTRIB_RESOLUTION,//5

  9. SNS_DDF_ATTRIB_LOWPASS,//6

  10. SNS_DDF_ATTRIB_MOTION_DETECT,//7

  11. SNS_DDF_ATTRIB_DRIVER_INFO,//8

  12. SNS_DDF_ATTRIB_DEVICE_INFO,//9

  13. SNS_DDF_ATTRIB_THRESHOLD,//10

  14. SNS_DDF_ATTRIB_ACCURACY,//11

  15. SNS_DDF_ATTRIB_BIAS,//12

  16. SNS_DDF_ATTRIB_ODR,//13

  17. SNS_DDF_ATTRIB_SUPPORTED_ODR_LIST,//14

  18. SNS_DDF_ATTRIB_REGISTRY_GROUP,//15

  19. SNS_DDF_ATTRIB_IO_REGISTER,//16

  20. SNS_DDF_ATTRIB_FIFO,//17

  21. SNS_DDF_ATTRIB_ODR_TOLERANCE,//18

  22. SNS_DDF_ATTRIB_FILTER_DELAY//19

  23.  
  24. } 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,並存儲下來。

 


 
  1. /**

  2. * Factory tests.

  3. */

  4. typedef enum

  5. {

  6. SNS_DDF_TEST_SELF, /**< Self test. */

  7. SNS_DDF_TEST_IRQ, /**< Interrupt test. */

  8. SNS_DDF_TEST_CONNECTIVITY, /**< Basic connectivity test. */

  9. SNS_DDF_TEST_SELF_HW, /**< Hardware self test. */

  10. SNS_DDF_TEST_SELF_SW, /**< Software self test. */

  11. SNS_DDF_TEST_OEM /**< OEM test. */

  12.  
  13. } 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值進行運算,從而返回給上層校準後的數據。

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