drivers: sensor: lis2dh: Level triggered interrupts

Both DRDY and motion interrupts behaves like level signals since they
remain asserted until they're cleared. Configuring them as edge
interrupts is dangerous because if we ever miss an interrupt, it may
never get cleared and thus will never trigger again.

Treating them as edge signals seems to have no advantages, other than
being marginally simpler to implement.

The patch has gotten many hours of run-time on real hardware using a
nRF52-based board and a LIS3DH with both interrupts connected and
heavily utilized.

Signed-off-by: Benjamin Lindqvist <benjamin.lindqvist@endian.se>
This commit is contained in:
Benjamin Lindqvist 2021-10-28 16:06:35 +02:00 committed by Maureen Helm
parent 3c450b103e
commit 0ab1bf42b3

View file

@ -25,7 +25,7 @@ static inline void setup_int1(const struct device *dev,
gpio_pin_interrupt_configure_dt(&cfg->gpio_drdy,
enable
? GPIO_INT_EDGE_TO_ACTIVE
? GPIO_INT_LEVEL_ACTIVE
: GPIO_INT_DISABLE);
}
@ -121,7 +121,7 @@ static inline void setup_int2(const struct device *dev,
gpio_pin_interrupt_configure_dt(&cfg->gpio_int,
enable
? GPIO_INT_EDGE_TO_ACTIVE
? GPIO_INT_LEVEL_ACTIVE
: GPIO_INT_DISABLE);
}
@ -254,6 +254,9 @@ static void lis2dh_gpio_int1_callback(const struct device *dev,
atomic_set_bit(&lis2dh->trig_flags, TRIGGED_INT1);
/* int is level trigged so disable until we clear it */
setup_int1(lis2dh->dev, false);
#if defined(CONFIG_LIS2DH_TRIGGER_OWN_THREAD)
k_sem_give(&lis2dh->gpio_sem);
#elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD)
@ -271,6 +274,9 @@ static void lis2dh_gpio_int2_callback(const struct device *dev,
atomic_set_bit(&lis2dh->trig_flags, TRIGGED_INT2);
/* int is level trigged so disable until we clear it */
setup_int2(lis2dh->dev, false);
#if defined(CONFIG_LIS2DH_TRIGGER_OWN_THREAD)
k_sem_give(&lis2dh->gpio_sem);
#elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD)
@ -316,6 +322,14 @@ static void lis2dh_thread_cb(const struct device *dev)
if (likely(lis2dh->handler_drdy != NULL)) {
lis2dh->handler_drdy(dev, &drdy_trigger);
}
/* Reactivate level triggered interrupt if handler did not
* disable itself
*/
if (likely(lis2dh->handler_drdy != NULL)) {
setup_int1(dev, true);
}
return;
@ -342,6 +356,13 @@ static void lis2dh_thread_cb(const struct device *dev)
lis2dh->handler_anymotion(dev, &anym_trigger);
}
/* Reactivate level triggered interrupt if handler did not
* disable itself
*/
if (lis2dh->handler_anymotion != NULL) {
setup_int2(dev, true);
}
LOG_DBG("@tick=%u int2_src=0x%x", k_cycle_get_32(),
reg_val);