drivers: sensor: lsm6dsl: add trigger support
Add DATA_READY trigger support to ST LSM6DSL driver. Signed-off-by: Armando Visconti <armando.visconti@st.com>
This commit is contained in:
parent
d7b7f51157
commit
6fb326ce06
5 changed files with 245 additions and 0 deletions
|
@ -1,3 +1,4 @@
|
|||
zephyr_sources_ifdef(CONFIG_LSM6DSL lsm6dsl.c)
|
||||
zephyr_sources_ifdef(CONFIG_LSM6DSL_SPI lsm6dsl_spi.c)
|
||||
zephyr_sources_ifdef(CONFIG_LSM6DSL_I2C lsm6dsl_i2c.c)
|
||||
zephyr_sources_ifdef(CONFIG_LSM6DSL_TRIGGER lsm6dsl_trigger.c)
|
||||
|
|
|
@ -107,6 +107,67 @@ config LSM6DSL_SPI_GPIO_CS_PIN
|
|||
This option is mandatory to set which GPIO pin to use in order
|
||||
to actually emulate the SPI CS.
|
||||
|
||||
choice
|
||||
prompt "Trigger mode"
|
||||
depends on LSM6DSL
|
||||
default LSM6DSL_TRIGGER_NONE
|
||||
help
|
||||
Specify the type of triggering to be used by the driver.
|
||||
|
||||
config LSM6DSL_TRIGGER_NONE
|
||||
bool
|
||||
prompt "No trigger"
|
||||
|
||||
config LSM6DSL_TRIGGER_GLOBAL_THREAD
|
||||
bool
|
||||
prompt "Use global thread"
|
||||
depends on GPIO
|
||||
select LSM6DSL_TRIGGER
|
||||
|
||||
config LSM6DSL_TRIGGER_OWN_THREAD
|
||||
bool
|
||||
prompt "Use own thread"
|
||||
depends on GPIO
|
||||
select LSM6DSL_TRIGGER
|
||||
|
||||
endchoice
|
||||
|
||||
config LSM6DSL_TRIGGER
|
||||
bool
|
||||
depends on LSM6DSL
|
||||
|
||||
config LSM6DSL_GPIO_DEV_NAME
|
||||
string
|
||||
prompt "GPIO device"
|
||||
depends on LSM6DSL && LSM6DSL_TRIGGER
|
||||
help
|
||||
The device name of the GPIO device to which the LSM6DSL interrupt pin
|
||||
is connected.
|
||||
|
||||
config LSM6DSL_GPIO_PIN_NUM
|
||||
int
|
||||
prompt "Interrupt GPIO pin number"
|
||||
depends on LSM6DSL && LSM6DSL_TRIGGER
|
||||
help
|
||||
The number of the GPIO on which the interrupt signal from the LSM6DSL
|
||||
chip will be received.
|
||||
|
||||
config LSM6DSL_THREAD_PRIORITY
|
||||
int
|
||||
prompt "Thread priority"
|
||||
depends on LSM6DSL && LSM6DSL_TRIGGER_OWN_THREAD
|
||||
default 10
|
||||
help
|
||||
Priority of thread used by the driver to handle interrupts.
|
||||
|
||||
config LSM6DSL_THREAD_STACK_SIZE
|
||||
int
|
||||
prompt "Thread stack size"
|
||||
depends on LSM6DSL && LSM6DSL_TRIGGER_OWN_THREAD
|
||||
default 1024
|
||||
help
|
||||
Stack size of thread used by the driver to handle interrupts.
|
||||
|
||||
config LSM6DSL_ENABLE_TEMP
|
||||
bool "Enable temperature"
|
||||
depends on LSM6DSL
|
||||
|
|
|
@ -327,6 +327,9 @@ static int lsm6dsl_channel_get(struct device *dev,
|
|||
}
|
||||
|
||||
static const struct sensor_driver_api lsm6dsl_api_funcs = {
|
||||
#if CONFIG_LSM6DSL_TRIGGER
|
||||
.trigger_set = lsm6dsl_trigger_set,
|
||||
#endif
|
||||
.sample_fetch = lsm6dsl_sample_fetch,
|
||||
.channel_get = lsm6dsl_channel_get,
|
||||
};
|
||||
|
@ -424,6 +427,13 @@ static int lsm6dsl_init(struct device *dev)
|
|||
lsm6dsl_i2c_init(dev);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LSM6DSL_TRIGGER
|
||||
if (lsm6dsl_init_interrupt(dev) < 0) {
|
||||
SYS_LOG_ERR("Failed to initialize interrupt.");
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (lsm6dsl_init_chip(dev) < 0) {
|
||||
SYS_LOG_DBG("failed to initialize chip");
|
||||
return -EIO;
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
#ifndef __SENSOR_LSM6DSL_H__
|
||||
#define __SENSOR_LSM6DSL_H__
|
||||
|
||||
#include <sensor.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <gpio.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
|
||||
|
@ -716,11 +718,37 @@ struct lsm6dsl_data {
|
|||
int temp_sample;
|
||||
#endif
|
||||
const struct lsm6dsl_transfer_function *hw_tf;
|
||||
|
||||
#ifdef CONFIG_LSM6DSL_TRIGGER
|
||||
struct device *gpio;
|
||||
struct gpio_callback gpio_cb;
|
||||
|
||||
struct sensor_trigger data_ready_trigger;
|
||||
sensor_trigger_handler_t data_ready_handler;
|
||||
|
||||
#if defined(CONFIG_LSM6DSL_TRIGGER_OWN_THREAD)
|
||||
K_THREAD_STACK_MEMBER(thread_stack, CONFIG_LSM6DSL_THREAD_STACK_SIZE);
|
||||
struct k_thread thread;
|
||||
struct k_sem gpio_sem;
|
||||
#elif defined(CONFIG_LSM6DSL_TRIGGER_GLOBAL_THREAD)
|
||||
struct k_work work;
|
||||
struct device *dev;
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_LSM6DSL_TRIGGER */
|
||||
};
|
||||
|
||||
int lsm6dsl_spi_init(struct device *dev);
|
||||
int lsm6dsl_i2c_init(struct device *dev);
|
||||
|
||||
#ifdef CONFIG_LSM6DSL_TRIGGER
|
||||
int lsm6dsl_trigger_set(struct device *dev,
|
||||
const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler);
|
||||
|
||||
int lsm6dsl_init_interrupt(struct device *dev);
|
||||
#endif
|
||||
|
||||
#define SYS_LOG_DOMAIN "LSM6DSL"
|
||||
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SENSOR_LEVEL
|
||||
#include <logging/sys_log.h>
|
||||
|
|
145
drivers/sensor/lsm6dsl/lsm6dsl_trigger.c
Normal file
145
drivers/sensor/lsm6dsl/lsm6dsl_trigger.c
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (c) 2018 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <device.h>
|
||||
#include <i2c.h>
|
||||
#include <misc/__assert.h>
|
||||
#include <misc/util.h>
|
||||
#include <kernel.h>
|
||||
#include <sensor.h>
|
||||
|
||||
#include "lsm6dsl.h"
|
||||
|
||||
int lsm6dsl_trigger_set(struct device *dev,
|
||||
const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler)
|
||||
{
|
||||
struct lsm6dsl_data *drv_data = dev->driver_data;
|
||||
|
||||
__ASSERT_NO_MSG(trig->type == SENSOR_TRIG_DATA_READY);
|
||||
|
||||
gpio_pin_disable_callback(drv_data->gpio, CONFIG_LSM6DSL_GPIO_PIN_NUM);
|
||||
|
||||
drv_data->data_ready_handler = handler;
|
||||
if (handler == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
drv_data->data_ready_trigger = *trig;
|
||||
|
||||
gpio_pin_enable_callback(drv_data->gpio, CONFIG_LSM6DSL_GPIO_PIN_NUM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lsm6dsl_gpio_callback(struct device *dev,
|
||||
struct gpio_callback *cb, u32_t pins)
|
||||
{
|
||||
struct lsm6dsl_data *drv_data =
|
||||
CONTAINER_OF(cb, struct lsm6dsl_data, gpio_cb);
|
||||
|
||||
ARG_UNUSED(pins);
|
||||
|
||||
gpio_pin_disable_callback(dev, CONFIG_LSM6DSL_GPIO_PIN_NUM);
|
||||
|
||||
#if defined(CONFIG_LSM6DSL_TRIGGER_OWN_THREAD)
|
||||
k_sem_give(&drv_data->gpio_sem);
|
||||
#elif defined(CONFIG_LSM6DSL_TRIGGER_GLOBAL_THREAD)
|
||||
k_work_submit(&drv_data->work);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void lsm6dsl_thread_cb(void *arg)
|
||||
{
|
||||
struct device *dev = arg;
|
||||
struct lsm6dsl_data *drv_data = dev->driver_data;
|
||||
|
||||
if (drv_data->data_ready_handler != NULL) {
|
||||
drv_data->data_ready_handler(dev,
|
||||
&drv_data->data_ready_trigger);
|
||||
}
|
||||
|
||||
gpio_pin_enable_callback(drv_data->gpio, CONFIG_LSM6DSL_GPIO_PIN_NUM);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LSM6DSL_TRIGGER_OWN_THREAD
|
||||
static void lsm6dsl_thread(int dev_ptr, int unused)
|
||||
{
|
||||
struct device *dev = INT_TO_POINTER(dev_ptr);
|
||||
struct lsm6dsl_data *drv_data = dev->driver_data;
|
||||
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
while (1) {
|
||||
k_sem_take(&drv_data->gpio_sem, K_FOREVER);
|
||||
lsm6dsl_thread_cb(dev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LSM6DSL_TRIGGER_GLOBAL_THREAD
|
||||
static void lsm6dsl_work_cb(struct k_work *work)
|
||||
{
|
||||
struct lsm6dsl_data *drv_data =
|
||||
CONTAINER_OF(work, struct lsm6dsl_data, work);
|
||||
|
||||
lsm6dsl_thread_cb(drv_data->dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
int lsm6dsl_init_interrupt(struct device *dev)
|
||||
{
|
||||
struct lsm6dsl_data *drv_data = dev->driver_data;
|
||||
|
||||
/* setup data ready gpio interrupt */
|
||||
drv_data->gpio = device_get_binding(CONFIG_LSM6DSL_GPIO_DEV_NAME);
|
||||
if (drv_data->gpio == NULL) {
|
||||
SYS_LOG_ERR("Cannot get pointer to %s device.",
|
||||
CONFIG_LSM6DSL_GPIO_DEV_NAME);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gpio_pin_configure(drv_data->gpio, CONFIG_LSM6DSL_GPIO_PIN_NUM,
|
||||
GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
|
||||
GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE);
|
||||
|
||||
gpio_init_callback(&drv_data->gpio_cb,
|
||||
lsm6dsl_gpio_callback,
|
||||
BIT(CONFIG_LSM6DSL_GPIO_PIN_NUM));
|
||||
|
||||
if (gpio_add_callback(drv_data->gpio, &drv_data->gpio_cb) < 0) {
|
||||
SYS_LOG_ERR("Could not set gpio callback.");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* enable data-ready interrupt */
|
||||
if (drv_data->hw_tf->update_reg(drv_data,
|
||||
LSM6DSL_REG_INT1_CTRL,
|
||||
LSM6DSL_SHIFT_INT1_CTRL_DRDY_XL |
|
||||
LSM6DSL_SHIFT_INT1_CTRL_DRDY_G,
|
||||
(1 << LSM6DSL_SHIFT_INT1_CTRL_DRDY_XL) |
|
||||
(1 << LSM6DSL_SHIFT_INT1_CTRL_DRDY_G)) < 0) {
|
||||
SYS_LOG_ERR("Could not enable data-ready interrupt.");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_LSM6DSL_TRIGGER_OWN_THREAD)
|
||||
k_sem_init(&drv_data->gpio_sem, 0, UINT_MAX);
|
||||
|
||||
k_thread_create(&drv_data->thread, drv_data->thread_stack,
|
||||
CONFIG_LSM6DSL_THREAD_STACK_SIZE,
|
||||
(k_thread_entry_t)lsm6dsl_thread, POINTER_TO_INT(dev),
|
||||
0, NULL, K_PRIO_COOP(CONFIG_LSM6DSL_THREAD_PRIORITY),
|
||||
0, 0);
|
||||
#elif defined(CONFIG_LSM6DSL_TRIGGER_GLOBAL_THREAD)
|
||||
drv_data->work.handler = lsm6dsl_work_cb;
|
||||
drv_data->dev = dev;
|
||||
#endif
|
||||
|
||||
gpio_pin_enable_callback(drv_data->gpio, CONFIG_LSM6DSL_GPIO_PIN_NUM);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue