2021/5/21

G Sensor: IIS2DLPC, wakeup function

Control Register 4 (23h):
  • bit 5: INT1_WU : 將 wakeup 狀態由 INT1 輸出
Status Register (27h):
  • bit 6: WU_IA : Wake Up Event Status
WAKE_UP_THS (34h):
  • bit 7: Single/Double : 0 - only single tap enabled, 1 - single and double tap enabled
  • bit 6: Sleep on : 0 - sleep disabled, 1 - enabled
  • bit 0-5 : threshold, 6bit unsigned
WAKE_UP_DUR (35h): -- 太複雜了...

WAKE_UP_SRC (38h):
  • bit 5 : Free Fall
  • bit 4 : Sleep Event Detected
  • bit 3 : Wake Up Event Detected
  • bit 2 : Wake Up Event on X
  • bit 1 : Wake Up Event on Y
  • bit 0 : Wake Up Event on Z
ALL_INT_SRC (3bh): 讀取這個 register 會 reset 所有 關聯到 INT 的 interrupt 狀態
  • bit 1: Wake Up
X/Y/Z_OFS_USR(3ch,3dh,3eh): 不知道是什麼意思
  • bit 0-7 : wo's complement user offset value on X/Y/Z-axis data, used for wakeup function
linux kernel driver 有時做出四個input device driver
  • input0 : accel
  • input1 : free_fall
  • input2 : tap
  • input3 : double_tap
  • input4 : wake_up
其中 input0, accel 的 configurable 內容有 enable, polling_rate, resolution, scale, scale_avail
其他的input1~4 都只有 enable 而已。

source code:
static DEVICE_ATTR(enable,
           S_IWUSR | S_IRUGO,
           lis2dw12_get_enable,
           lis2dw12_set_enable);
然後..
static struct attribute *lis2dw12_accel_attribute[] = {
    &dev_attr_enable.attr,
    &dev_attr_resolution.attr,
    &dev_attr_polling_rate.attr,
    &dev_attr_scale_avail.attr,
    &dev_attr_scale.attr,
    NULL,
};

static struct attribute *lis2dw12_step_ff_attribute[] = {
    &dev_attr_enable.attr,
    NULL,
};

static struct attribute *lis2dw12_tap_attribute[] = {
    &dev_attr_enable.attr,
    NULL,
};

static struct attribute *lis2dw12_double_tap_attribute[] = {
    &dev_attr_enable.attr,
    NULL,
};

static struct attribute *lis2dw12_wakeup_attribute[] = {
    &dev_attr_enable.attr,
    NULL,
};
可以看到,所有 inputX 的 attrib enable 都共用 function : lis2dw12_set_enable( )
然後 lis2dw12_set_enable( ) 依照傳入的 dev 決定是那一個 input call 的..

查 enable --- 最後到 _lis2dw21_enable_sensors( ),先..err = lis2dw12_update_drdy_irq(sdata),啟動 INT1..
CTRL4 就是控制 interrput 到 INT1 的開關
     7            6             5        4         3            2           1           0
------------------------------------------------------------------------------------------------
| INT1_6D | INT1_SINGLE_TAP | INT1_WU | INT1_FF | INT1_TAP | INT1_DIFF5 | INT1_FTH | INT1_DRDY |
------------------------------------------------------------------------------------------------
其中,INT1_WU 就是 wake up
static int lis2dw12_update_drdy_irq(struct lis2dw12_sensor_data *sdata)
{
    u8 reg_addr = LIS2DW12_CTRL4_INT1_PAD_ADDR, reg_val, reg_mask;

    switch (sdata->sindex) {
    case LIS2DW12_FF:
    case LIS2DW12_TAP:
    case LIS2DW12_DOUBLE_TAP:
    case LIS2DW12_WAKEUP:
        reg_val = lis2dw12_event_irq1_value(sdata->cdata);
        reg_mask = LIS2DW12_INT1_EVENTS_MASK;
        break;
    case LIS2DW12_ACCEL:
        return 0;
    default:
        return -EINVAL;
    }

    return lis2dw12_write_data_with_mask(sdata->cdata, reg_addr, reg_mask,
                       reg_val >> __ffs(reg_mask), true);
}
所以driver 中,Wakeup 的 threshold, duration 都是hard-code,不是 configurable.
sysfs 中只有 enable/disable 功能。就是把 interrupt 開啟/關閉。
#define LIS2DW12_WAKE_UP_THS_WU_MASK    0x3f
#define LIS2DW12_WAKE_UP_THS_WU_DEFAULT 0x02


static int lis2dw12_init_sensors(struct lis2dw12_data *cdata)
{
      ...
      err = lis2dw12_write_data_with_mask(sdata->cdata,
                      LIS2DW12_WAKE_UP_THS_ADDR,
                      LIS2DW12_WAKE_UP_THS_WU_MASK,
                      LIS2DW12_WAKE_UP_THS_WU_DEFAULT, true);
這個 write_data_with_mask( )就是 read, mask, update 的動作。
mask 就是把這幾個 bit 都 clear,然後填熱 後面的 data。
然後 DURATION 都沒設。

--- 結果沒這麼簡單...

查 application note AN5201, 5.1 Interrupt pin configutation:
All the embedded function interrupt signals are subordinate to the INTERRUPTS_ENABLE bit in register CTRL7.
If this bit is set, the embedded functions are enabled and the interrupts signals can be routed to the INT1 and/or
INT2 pins; otherwise, if this bit is not set, the embedded functions are disabled
可是 source code 中沒有看到CTRL7 的宣告,也沒有設定。(除非 reset value 是 SET)
所以 INT1 沒有動作。

沒有留言:

張貼留言