driver/sensor: lis2mdl: make use of STdC definitions
Port the lis2mdl sensor driver on top of the lis2mdl_StdC HAL interface (in modules/hal/st/sensor/stmemsc/). Signed-off-by: Armando Visconti <armando.visconti@st.com>
This commit is contained in:
parent
a34a5885b8
commit
44f373e806
8 changed files with 343 additions and 223 deletions
|
@ -1,9 +1,11 @@
|
|||
#
|
||||
# Copyright (c) 2018 STMicroelectronics
|
||||
# Copyright (c) 2018-2019 STMicroelectronics
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
zephyr_library()
|
||||
zephyr_library_sources_ifdef(CONFIG_LIS2MDL lis2mdl.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_LIS2MDL lis2mdl_i2c.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_LIS2MDL lis2mdl_spi.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_LIS2MDL_TRIGGER lis2mdl_trigger.c)
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
# Copyright (c) 2018 STMicroelectronics
|
||||
# Copyright (c) 2018-2019 STMicroelectronics
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
menuconfig LIS2MDL
|
||||
bool "LIS2MDL Magnetometer"
|
||||
depends on (I2C && HAS_DTS_I2C)
|
||||
depends on (I2C && HAS_DTS_I2C) || SPI
|
||||
select HAS_STMEMSC
|
||||
select USE_STDC_LIS2MDL
|
||||
help
|
||||
Enable driver for LIS2MDL I2C-based magnetometer sensor.
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
/*
|
||||
* Copyright (c) 2018 STMicroelectronics
|
||||
/* ST Microelectronics LIS2MDL 3-axis magnetometer sensor
|
||||
*
|
||||
* LIS2MDL mag driver
|
||||
* Copyright (c) 2018-2019 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/lis2mdl.pdf
|
||||
*/
|
||||
|
||||
#include <init.h>
|
||||
|
@ -14,73 +16,40 @@
|
|||
|
||||
#include "lis2mdl.h"
|
||||
|
||||
struct lis2mdl_data lis2mdl_device_data;
|
||||
struct lis2mdl_data lis2mdl_data;
|
||||
|
||||
#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(LIS2MDL);
|
||||
|
||||
#ifdef CONFIG_LIS2MDL_MAG_ODR_RUNTIME
|
||||
static const struct {
|
||||
u16_t odr;
|
||||
u8_t regval;
|
||||
} lis2mdl_odr_reg[] = {
|
||||
{
|
||||
.odr = 10,
|
||||
.regval = LIS2MDL_ODR10_HZ,
|
||||
},
|
||||
{
|
||||
.odr = 20,
|
||||
.regval = LIS2MDL_ODR20_HZ,
|
||||
},
|
||||
{
|
||||
.odr = 50,
|
||||
.regval = LIS2MDL_ODR50_HZ,
|
||||
},
|
||||
{
|
||||
.odr = 100,
|
||||
.regval = LIS2MDL_ODR100_HZ,
|
||||
},
|
||||
};
|
||||
|
||||
static int lis2mdl_freq_to_odr_val(u16_t odr)
|
||||
static int lis2mdl_set_odr(struct device *dev, const struct sensor_value *val)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lis2mdl_odr_reg); i++) {
|
||||
if (odr == lis2mdl_odr_reg[i].odr) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int lis2mdl_set_odr(struct device *dev, u16_t odr)
|
||||
{
|
||||
int odr_idx;
|
||||
struct lis2mdl_data *lis2mdl = dev->driver_data;
|
||||
lis2mdl_odr_t odr;
|
||||
|
||||
/* check if power off */
|
||||
if (odr == 0U) {
|
||||
/* power off mag */
|
||||
return i2c_reg_update_byte(lis2mdl->i2c,
|
||||
lis2mdl->i2c_addr,
|
||||
LIS2MDL_CFG_REG_A,
|
||||
LIS2MDL_MAG_MODE_MASK,
|
||||
LIS2MDL_MD_IDLE1_MODE);
|
||||
switch (val->val1) {
|
||||
case 10:
|
||||
odr = LIS2MDL_ODR_10Hz;
|
||||
break;
|
||||
case 20:
|
||||
odr = LIS2MDL_ODR_20Hz;
|
||||
break;
|
||||
case 50:
|
||||
odr = LIS2MDL_ODR_50Hz;
|
||||
break;
|
||||
case 100:
|
||||
odr = LIS2MDL_ODR_100Hz;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
odr_idx = lis2mdl_freq_to_odr_val(odr);
|
||||
if (odr_idx < 0) {
|
||||
return odr_idx;
|
||||
if (lis2mdl_data_rate_set(lis2mdl->ctx, odr)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return i2c_reg_update_byte(lis2mdl->i2c,
|
||||
lis2mdl->i2c_addr,
|
||||
LIS2MDL_CFG_REG_A,
|
||||
LIS2MDL_ODR_MASK,
|
||||
lis2mdl_odr_reg[odr_idx].regval);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_LIS2MDL_MAG_ODR_RUNTIME */
|
||||
|
||||
|
@ -88,24 +57,15 @@ static int lis2mdl_set_hard_iron(struct device *dev, enum sensor_channel chan,
|
|||
const struct sensor_value *val)
|
||||
{
|
||||
struct lis2mdl_data *lis2mdl = dev->driver_data;
|
||||
u8_t regs = LIS2MDL_OFFSET_X_REG_L;
|
||||
u8_t i;
|
||||
s16_t offs;
|
||||
int ret;
|
||||
axis3bit16_t offset;
|
||||
|
||||
for (i = 0U; i < LIS2MDL_NUM_AXIS; i++) {
|
||||
offs = sys_cpu_to_le16(val->val1);
|
||||
ret = i2c_burst_write(lis2mdl->i2c, lis2mdl->i2c_addr,
|
||||
regs, (u8_t *)&offs, sizeof(offs));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
regs += sizeof(offs);
|
||||
for (i = 0U; i < 3; i++) {
|
||||
offset.i16bit[i] = sys_cpu_to_le16(val->val1);
|
||||
val++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return lis2mdl_mag_user_offset_set(lis2mdl->ctx, offset.u8bit);
|
||||
}
|
||||
|
||||
static void lis2mdl_channel_get_mag(struct device *dev,
|
||||
|
@ -179,7 +139,7 @@ static int lis2mdl_config(struct device *dev, enum sensor_channel chan,
|
|||
switch (attr) {
|
||||
#ifdef CONFIG_LIS2MDL_MAG_ODR_RUNTIME
|
||||
case SENSOR_ATTR_SAMPLING_FREQUENCY:
|
||||
return lis2mdl_set_odr(dev, val->val1);
|
||||
return lis2mdl_set_odr(dev, val);
|
||||
#endif /* CONFIG_LIS2MDL_MAG_ODR_RUNTIME */
|
||||
case SENSOR_ATTR_OFFSET:
|
||||
return lis2mdl_set_hard_iron(dev, chan, val);
|
||||
|
@ -197,6 +157,7 @@ static int lis2mdl_attr_set(struct device *dev,
|
|||
const struct sensor_value *val)
|
||||
{
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_ALL:
|
||||
case SENSOR_CHAN_MAGN_X:
|
||||
case SENSOR_CHAN_MAGN_Y:
|
||||
case SENSOR_CHAN_MAGN_Z:
|
||||
|
@ -213,25 +174,17 @@ static int lis2mdl_attr_set(struct device *dev,
|
|||
static int lis2mdl_sample_fetch_mag(struct device *dev)
|
||||
{
|
||||
struct lis2mdl_data *lis2mdl = dev->driver_data;
|
||||
|
||||
union {
|
||||
u8_t raw[LIS2MDL_OUT_REG_SIZE];
|
||||
struct {
|
||||
s16_t m_axis[3];
|
||||
};
|
||||
} buf __aligned(2);
|
||||
axis3bit16_t raw_mag;
|
||||
|
||||
/* fetch raw data sample */
|
||||
if (i2c_burst_read(lis2mdl->i2c, lis2mdl->i2c_addr,
|
||||
LIS2MDL_OUT_REG, buf.raw,
|
||||
sizeof(buf)) < 0) {
|
||||
LOG_DBG("Failed to fetch raw mag sample");
|
||||
if (lis2mdl_magnetic_raw_get(lis2mdl->ctx, raw_mag.u8bit) < 0) {
|
||||
LOG_DBG("Failed to read sample");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
lis2mdl->mag[0] = sys_le16_to_cpu(buf.m_axis[0]);
|
||||
lis2mdl->mag[1] = sys_le16_to_cpu(buf.m_axis[1]);
|
||||
lis2mdl->mag[2] = sys_le16_to_cpu(buf.m_axis[2]);
|
||||
lis2mdl->mag[0] = sys_le16_to_cpu(raw_mag.i16bit[0]);
|
||||
lis2mdl->mag[1] = sys_le16_to_cpu(raw_mag.i16bit[1]);
|
||||
lis2mdl->mag[2] = sys_le16_to_cpu(raw_mag.i16bit[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -239,21 +192,17 @@ static int lis2mdl_sample_fetch_mag(struct device *dev)
|
|||
static int lis2mdl_sample_fetch_temp(struct device *dev)
|
||||
{
|
||||
struct lis2mdl_data *lis2mdl = dev->driver_data;
|
||||
u16_t temp_raw;
|
||||
axis1bit16_t raw_temp;
|
||||
s32_t temp;
|
||||
int ret;
|
||||
|
||||
/* fetch raw temperature sample */
|
||||
ret = i2c_burst_read(lis2mdl->i2c, lis2mdl->i2c_addr,
|
||||
LIS2MDL_TEMP_OUT_L_REG,
|
||||
(u8_t *)&temp_raw, sizeof(temp_raw));
|
||||
if (ret < 0) {
|
||||
LOG_DBG("Failed to fetch raw temp sample");
|
||||
if (lis2mdl_temperature_raw_get(lis2mdl->ctx, raw_temp.u8bit) < 0) {
|
||||
LOG_DBG("Failed to read sample");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* formula is temp = 25 + (temp / 8) C */
|
||||
temp = (sys_le16_to_cpu(temp_raw) & 0x8FFF);
|
||||
temp = (sys_le16_to_cpu(raw_temp.i16bit) & 0x8FFF);
|
||||
lis2mdl->temp_sample = 2500 + (temp * 100) / 8;
|
||||
|
||||
return 0;
|
||||
|
@ -293,29 +242,47 @@ static const struct sensor_driver_api lis2mdl_driver_api = {
|
|||
|
||||
static int lis2mdl_init_interface(struct device *dev)
|
||||
{
|
||||
const struct lis2mdl_device_config *const config =
|
||||
const struct lis2mdl_config *const config =
|
||||
dev->config->config_info;
|
||||
struct lis2mdl_data *lis2mdl = dev->driver_data;
|
||||
|
||||
lis2mdl->i2c = device_get_binding(config->master_dev_name);
|
||||
if (!lis2mdl->i2c) {
|
||||
lis2mdl->bus = device_get_binding(config->master_dev_name);
|
||||
if (!lis2mdl->bus) {
|
||||
LOG_DBG("Could not get pointer to %s device",
|
||||
config->master_dev_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
lis2mdl->i2c_addr = config->i2c_addr_config;
|
||||
|
||||
return 0;
|
||||
return config->bus_init(dev);
|
||||
}
|
||||
|
||||
static const struct lis2mdl_device_config lis2mdl_dev_config = {
|
||||
static const struct lis2mdl_config lis2mdl_dev_config = {
|
||||
.master_dev_name = DT_INST_0_ST_LIS2MDL_BUS_NAME,
|
||||
#ifdef CONFIG_LIS2MDL_TRIGGER
|
||||
.gpio_name = DT_INST_0_ST_LIS2MDL_IRQ_GPIOS_CONTROLLER,
|
||||
.gpio_pin = DT_INST_0_ST_LIS2MDL_IRQ_GPIOS_PIN,
|
||||
#endif /* CONFIG_LIS2MDL_TRIGGER */
|
||||
.i2c_addr_config = DT_INST_0_ST_LIS2MDL_BASE_ADDRESS,
|
||||
#if defined(DT_ST_LIS2MDL_BUS_SPI)
|
||||
.bus_init = lis2mdl_spi_init,
|
||||
.spi_conf.frequency = DT_INST_0_ST_LIS2MDL_SPI_MAX_FREQUENCY,
|
||||
.spi_conf.operation = (SPI_OP_MODE_MASTER | SPI_MODE_CPOL |
|
||||
SPI_MODE_CPHA | SPI_WORD_SET(8) |
|
||||
SPI_LINES_SINGLE),
|
||||
.spi_conf.slave = DT_INST_0_ST_LIS2MDL_BASE_ADDRESS,
|
||||
#if defined(DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER)
|
||||
.gpio_cs_port = DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER,
|
||||
.cs_gpio = DT_INST_0_ST_LIS2MDL_CS_GPIOS_PIN,
|
||||
|
||||
.spi_conf.cs = &lis2mdl_data.cs_ctrl,
|
||||
#else
|
||||
.spi_conf.cs = NULL,
|
||||
#endif
|
||||
#elif defined(DT_ST_LIS2MDL_BUS_I2C)
|
||||
.bus_init = lis2mdl_i2c_init,
|
||||
.i2c_slv_addr = DT_INST_0_ST_LIS2MDL_BASE_ADDRESS,
|
||||
#else
|
||||
#error "BUS MACRO NOT DEFINED IN DTS"
|
||||
#endif
|
||||
};
|
||||
|
||||
static int lis2mdl_init(struct device *dev)
|
||||
|
@ -328,41 +295,53 @@ static int lis2mdl_init(struct device *dev)
|
|||
}
|
||||
|
||||
/* check chip ID */
|
||||
if (i2c_reg_read_byte(lis2mdl->i2c, lis2mdl->i2c_addr,
|
||||
LIS2MDL_WHO_AM_I_REG, &wai) < 0) {
|
||||
LOG_DBG("Failed to read chip ID");
|
||||
if (lis2mdl_device_id_get(lis2mdl->ctx, &wai) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (wai != LIS2MDL_WHOAMI_VAL) {
|
||||
LOG_DBG("Invalid chip ID");
|
||||
if (wai != LIS2MDL_ID) {
|
||||
LOG_DBG("Invalid chip ID: %02x\n", wai);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* reset sensor configuration */
|
||||
if (i2c_reg_write_byte(lis2mdl->i2c, lis2mdl->i2c_addr,
|
||||
LIS2MDL_CFG_REG_A, LIS2MDL_SOFT_RST)) {
|
||||
if (lis2mdl_reset_set(lis2mdl->ctx, PROPERTY_ENABLE) < 0) {
|
||||
LOG_DBG("s/w reset failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
k_busy_wait(100);
|
||||
|
||||
/* enable BDU */
|
||||
if (i2c_reg_update_byte(lis2mdl->i2c, lis2mdl->i2c_addr,
|
||||
LIS2MDL_CFG_REG_C, LIS2MDL_BDU_MASK,
|
||||
LIS2MDL_BDU_BIT)) {
|
||||
if (lis2mdl_block_data_update_set(lis2mdl->ctx, PROPERTY_ENABLE) < 0) {
|
||||
LOG_DBG("setting bdu failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* set continuous MODE in default ODR, enable temperature comp. */
|
||||
if (i2c_reg_write_byte(lis2mdl->i2c, lis2mdl->i2c_addr,
|
||||
LIS2MDL_CFG_REG_A,
|
||||
LIS2MDL_MD_CONT_MODE | LIS2MDL_DEFAULT_ODR |
|
||||
LIS2MDL_COMP_TEMP_MASK)) {
|
||||
/* Set Output Data Rate */
|
||||
if (lis2mdl_data_rate_set(lis2mdl->ctx, LIS2MDL_ODR_10Hz)) {
|
||||
LOG_DBG("set odr failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
lis2mdl->mag_fs_sensitivity = LIS2MDL_SENSITIVITY;
|
||||
/* Set / Reset sensor mode */
|
||||
if (lis2mdl_set_rst_mode_set(lis2mdl->ctx,
|
||||
LIS2MDL_SENS_OFF_CANC_EVERY_ODR)) {
|
||||
LOG_DBG("reset sensor mode failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Enable temperature compensation */
|
||||
if (lis2mdl_offset_temp_comp_set(lis2mdl->ctx, PROPERTY_ENABLE)) {
|
||||
LOG_DBG("enable temp compensation failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Set device in continuous mode */
|
||||
if (lis2mdl_operating_mode_set(lis2mdl->ctx, LIS2MDL_CONTINUOUS_MODE)) {
|
||||
LOG_DBG("set continuos mode failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LIS2MDL_TRIGGER
|
||||
if (lis2mdl_init_interrupt(dev) < 0) {
|
||||
|
@ -375,5 +354,5 @@ static int lis2mdl_init(struct device *dev)
|
|||
}
|
||||
|
||||
DEVICE_AND_API_INIT(lis2mdl, DT_INST_0_ST_LIS2MDL_LABEL, lis2mdl_init,
|
||||
&lis2mdl_device_data, &lis2mdl_dev_config, POST_KERNEL,
|
||||
&lis2mdl_data, &lis2mdl_dev_config, POST_KERNEL,
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &lis2mdl_driver_api);
|
||||
|
|
|
@ -1,114 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2018 STMicroelectronics
|
||||
/* ST Microelectronics LIS2MDL 3-axis magnetometer sensor
|
||||
*
|
||||
* LIS2MDL mag header file
|
||||
* Copyright (c) 2018-2019 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/lis2mdl.pdf
|
||||
*/
|
||||
|
||||
#ifndef __MAG_LIS2MDL_H
|
||||
#define __MAG_LIS2MDL_H
|
||||
|
||||
#include <drivers/spi.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <drivers/sensor.h>
|
||||
#include <sys/util.h>
|
||||
#include <drivers/i2c.h>
|
||||
|
||||
#define LIS2MDL_EN_BIT 1
|
||||
#define LIS2MDL_DIS_BIT 0
|
||||
#define LIS2MDL_I2C_ADDR(__x) (__x << 1)
|
||||
|
||||
#define LIS2MDL_AUTO_INCREMENT 0x80
|
||||
|
||||
/* Registers */
|
||||
#define LIS2MDL_WHO_AM_I_REG 0x4f
|
||||
#define LIS2MDL_WHOAMI_VAL 0x40
|
||||
|
||||
#define LIS2MDL_CFG_REG_A 0x60
|
||||
/* Device supported modes */
|
||||
#define LIS2MDL_MD_CONT_MODE 0x00
|
||||
#define LIS2MDL_MD_SINGLE_MODE 0x01
|
||||
#define LIS2MDL_MD_IDLE1_MODE 0x02
|
||||
#define LIS2MDL_MD_IDLE2_MODE 0x03
|
||||
#define LIS2MDL_MAG_MODE_MASK 0x03
|
||||
/* Device supported ODRs */
|
||||
#define LIS2MDL_ODR10_HZ 0x00
|
||||
#define LIS2MDL_ODR20_HZ 0x04
|
||||
#define LIS2MDL_ODR50_HZ 0x08
|
||||
#define LIS2MDL_ODR100_HZ 0x0c
|
||||
#define LIS2MDL_ODR_MASK 0x0c
|
||||
|
||||
#if defined(CONFIG_LIS2MDL_MAG_ODR_10) || \
|
||||
defined(CONFIG_LIS2MDL_MAG_ODR_RUNTIME)
|
||||
#define LIS2MDL_DEFAULT_ODR LIS2MDL_ODR10_HZ
|
||||
#elif defined(CONFIG_LIS2MDL_MAG_ODR_20)
|
||||
#define LIS2MDL_DEFAULT_ODR LIS2MDL_ODR20_HZ
|
||||
#elif defined(CONFIG_LIS2MDL_MAG_ODR_50)
|
||||
#define LIS2MDL_DEFAULT_ODR LIS2MDL_ODR50_HZ
|
||||
#elif defined(CONFIG_LIS2MDL_MAG_ODR_100)
|
||||
#define LIS2MDL_DEFAULT_ODR LIS2MDL_ODR100_HZ
|
||||
#endif
|
||||
|
||||
/* Sensors registers */
|
||||
#define LIS2MDL_OFFSET_X_REG_L 0x45
|
||||
#define LIS2MDL_OFFSET_X_REG_H 0x46
|
||||
#define LIS2MDL_OFFSET_Y_REG_L 0x47
|
||||
#define LIS2MDL_OFFSET_Y_REG_H 0x48
|
||||
#define LIS2MDL_OFFSET_Z_REG_L 0x49
|
||||
#define LIS2MDL_OFFSET_Z_REG_H 0x4A
|
||||
#define LIS2MDL_CFG_REG_B 0x61
|
||||
#define LIS2MDL_CFG_REG_C 0x62
|
||||
#define LIS2MDL_INT_CTRL_REG 0x63
|
||||
#define LIS2MDL_STATUS_REG 0x67
|
||||
#define LIS2MDL_OUT_REG 0x68
|
||||
#define LIS2MDL_TEMP_OUT_L_REG 0x6E
|
||||
#define LIS2MDL_TEMP_OUT_H_REG 0x6F
|
||||
|
||||
/* Registers bitmask */
|
||||
#define LIS2MDL_STS_MDA_UP 0x08
|
||||
#define LIS2MDL_REBOOT 0x40
|
||||
#define LIS2MDL_SOFT_RST 0x20
|
||||
#define LIS2MDL_BDU_MASK 0x10
|
||||
#define LIS2MDL_BDU_BIT 0x10
|
||||
#define LIS2MDL_INT_MAG_PIN 0x40
|
||||
#define LIS2MDL_INT_MAG_PIN_MASK 0x40
|
||||
#define LIS2MDL_INT_MAG 0x01
|
||||
#define LIS2MDL_INT_MAG_MASK 0x01
|
||||
#define LIS2MDL_MODE_MASK 0x03
|
||||
#define LIS2MDL_LP_MASK 0x10
|
||||
#define LIS2MDL_IEA 0x04
|
||||
#define LIS2MDL_IEL 0x02
|
||||
#define LIS2MDL_IEN 0x01
|
||||
#define LIS2MDL_COMP_TEMP_MASK 0x80
|
||||
|
||||
/* Output data size */
|
||||
#define LIS2MDL_OUT_REG_SIZE 6
|
||||
#define LIS2MDL_NUM_AXIS 3
|
||||
|
||||
/* Define ODR supported range */
|
||||
#define LIS2MDL_MAX_ODR 100
|
||||
#define LIS2MDL_MIN_ODR 10
|
||||
#include "lis2mdl_reg.h"
|
||||
|
||||
/* Sensor sensitivity in uGa/LSB */
|
||||
#define LIS2MDL_SENSITIVITY 1500
|
||||
|
||||
struct lis2mdl_device_config {
|
||||
struct lis2mdl_config {
|
||||
char *master_dev_name;
|
||||
int (*bus_init)(struct device *dev);
|
||||
#ifdef CONFIG_LIS2MDL_TRIGGER
|
||||
char *gpio_name;
|
||||
u32_t gpio_pin;
|
||||
#endif /* CONFIG_LIS2MDL_TRIGGER */
|
||||
u16_t i2c_addr_config;
|
||||
#ifdef DT_ST_LIS2MDL_BUS_I2C
|
||||
u16_t i2c_slv_addr;
|
||||
#elif DT_ST_LIS2MDL_BUS_SPI
|
||||
struct spi_config spi_conf;
|
||||
#if defined(DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER)
|
||||
const char *gpio_cs_port;
|
||||
u8_t cs_gpio;
|
||||
#endif /* DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER */
|
||||
#endif /* DT_ST_LIS2MDL_BUS_SPI */
|
||||
};
|
||||
|
||||
/* Sensor data */
|
||||
struct lis2mdl_data {
|
||||
struct device *i2c;
|
||||
struct device *bus;
|
||||
u16_t i2c_addr;
|
||||
s16_t mag[3];
|
||||
s32_t temp_sample;
|
||||
|
||||
/* save sensitivity */
|
||||
u16_t mag_fs_sensitivity;
|
||||
lis2mdl_ctx_t *ctx;
|
||||
|
||||
#ifdef DT_ST_LIS2MDL_BUS_I2C
|
||||
lis2mdl_ctx_t ctx_i2c;
|
||||
#elif DT_ST_LIS2MDL_BUS_SPI
|
||||
lis2mdl_ctx_t ctx_spi;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIS2MDL_TRIGGER
|
||||
struct device *gpio;
|
||||
|
@ -125,8 +69,14 @@ struct lis2mdl_data {
|
|||
struct device *dev;
|
||||
#endif /* CONFIG_LIS2MDL_TRIGGER_GLOBAL_THREAD */
|
||||
#endif /* CONFIG_LIS2MDL_TRIGGER */
|
||||
#if defined(DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER)
|
||||
struct spi_cs_control cs_ctrl;
|
||||
#endif /* DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER */
|
||||
};
|
||||
|
||||
int lis2mdl_spi_init(struct device *dev);
|
||||
int lis2mdl_i2c_init(struct device *dev);
|
||||
|
||||
#ifdef CONFIG_LIS2MDL_TRIGGER
|
||||
int lis2mdl_init_interrupt(struct device *dev);
|
||||
int lis2mdl_trigger_set(struct device *dev,
|
||||
|
|
54
drivers/sensor/lis2mdl/lis2mdl_i2c.c
Normal file
54
drivers/sensor/lis2mdl/lis2mdl_i2c.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/* ST Microelectronics LIS2MDL 3-axis magnetometer sensor
|
||||
*
|
||||
* Copyright (c) 2019 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/lis2mdl.pdf
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <drivers/i2c.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
#include "lis2mdl.h"
|
||||
|
||||
#ifdef DT_ST_LIS2MDL_BUS_I2C
|
||||
|
||||
#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
|
||||
LOG_MODULE_DECLARE(LIS2MDL);
|
||||
|
||||
static int lis2mdl_i2c_read(struct device *dev, u8_t reg_addr,
|
||||
u8_t *value, u16_t len)
|
||||
{
|
||||
struct lis2mdl_data *data = dev->driver_data;
|
||||
const struct lis2mdl_config *cfg = dev->config->config_info;
|
||||
|
||||
return i2c_burst_read(data->bus, cfg->i2c_slv_addr,
|
||||
reg_addr, value, len);
|
||||
}
|
||||
|
||||
static int lis2mdl_i2c_write(struct device *dev, u8_t reg_addr,
|
||||
u8_t *value, u16_t len)
|
||||
{
|
||||
struct lis2mdl_data *data = dev->driver_data;
|
||||
const struct lis2mdl_config *cfg = dev->config->config_info;
|
||||
|
||||
return i2c_burst_write(data->bus, cfg->i2c_slv_addr,
|
||||
reg_addr, value, len);
|
||||
}
|
||||
|
||||
int lis2mdl_i2c_init(struct device *dev)
|
||||
{
|
||||
struct lis2mdl_data *data = dev->driver_data;
|
||||
|
||||
data->ctx_i2c.read_reg = (lis2mdl_read_ptr) lis2mdl_i2c_read;
|
||||
data->ctx_i2c.write_reg = (lis2mdl_write_ptr) lis2mdl_i2c_write;
|
||||
|
||||
data->ctx = &data->ctx_i2c;
|
||||
data->ctx->handle = dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* DT_ST_LIS2MDL_BUS_I2C */
|
127
drivers/sensor/lis2mdl/lis2mdl_spi.c
Normal file
127
drivers/sensor/lis2mdl/lis2mdl_spi.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
/* ST Microelectronics LIS2MDL 3-axis magnetometer sensor
|
||||
*
|
||||
* Copyright (c) 2019 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/lis2mdl.pdf
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "lis2mdl.h"
|
||||
#include <logging/log.h>
|
||||
|
||||
#ifdef DT_ST_LIS2MDL_BUS_SPI
|
||||
|
||||
#define LIS2MDL_SPI_READ (1 << 7)
|
||||
|
||||
#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
|
||||
LOG_MODULE_DECLARE(LIS2MDL);
|
||||
|
||||
static int lis2mdl_spi_read(struct device *dev, u8_t reg_addr,
|
||||
u8_t *value, u8_t len)
|
||||
{
|
||||
struct lis2mdl_data *data = dev->driver_data;
|
||||
const struct lis2mdl_config *cfg = dev->config->config_info;
|
||||
const struct spi_config *spi_cfg = &cfg->spi_conf;
|
||||
u8_t buffer_tx[2] = { reg_addr | LIS2MDL_SPI_READ, 0 };
|
||||
const struct spi_buf tx_buf = {
|
||||
.buf = buffer_tx,
|
||||
.len = 2,
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = &tx_buf,
|
||||
.count = 1
|
||||
};
|
||||
const struct spi_buf rx_buf[2] = {
|
||||
{
|
||||
.buf = NULL,
|
||||
.len = 1,
|
||||
},
|
||||
{
|
||||
.buf = value,
|
||||
.len = len,
|
||||
}
|
||||
};
|
||||
const struct spi_buf_set rx = {
|
||||
.buffers = rx_buf,
|
||||
.count = 2
|
||||
};
|
||||
|
||||
|
||||
if (len > 64) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (spi_transceive(data->bus, spi_cfg, &tx, &rx)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lis2mdl_spi_write(struct device *dev, u8_t reg_addr,
|
||||
u8_t *value, u8_t len)
|
||||
{
|
||||
struct lis2mdl_data *data = dev->driver_data;
|
||||
const struct lis2mdl_config *cfg = dev->config->config_info;
|
||||
const struct spi_config *spi_cfg = &cfg->spi_conf;
|
||||
u8_t buffer_tx[1] = { reg_addr & ~LIS2MDL_SPI_READ };
|
||||
const struct spi_buf tx_buf[2] = {
|
||||
{
|
||||
.buf = buffer_tx,
|
||||
.len = 1,
|
||||
},
|
||||
{
|
||||
.buf = value,
|
||||
.len = len,
|
||||
}
|
||||
};
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = tx_buf,
|
||||
.count = 2
|
||||
};
|
||||
|
||||
|
||||
if (len > 64) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (spi_write(data->bus, spi_cfg, &tx)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lis2mdl_spi_init(struct device *dev)
|
||||
{
|
||||
struct lis2mdl_data *data = dev->driver_data;
|
||||
|
||||
data->ctx_spi.read_reg = (lis2mdl_read_ptr) lis2mdl_spi_read;
|
||||
data->ctx_spi.write_reg = (lis2mdl_write_ptr) lis2mdl_spi_write;
|
||||
|
||||
data->ctx = &data->ctx_spi;
|
||||
data->ctx->handle = dev;
|
||||
|
||||
#if defined(DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER)
|
||||
const struct lis2mdl_config *cfg = dev->config->config_info;
|
||||
|
||||
/* handle SPI CS thru GPIO if it is the case */
|
||||
data->cs_ctrl.gpio_dev = device_get_binding(cfg->gpio_cs_port);
|
||||
if (!data->cs_ctrl.gpio_dev) {
|
||||
LOG_ERR("Unable to get GPIO SPI CS device");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
data->cs_ctrl.gpio_pin = cfg->cs_gpio;
|
||||
data->cs_ctrl.delay = 0;
|
||||
|
||||
LOG_DBG("SPI GPIO CS configured on %s:%u",
|
||||
cfg->gpio_cs_port, cfg->cs_gpio);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* DT_ST_LIS2MDL_BUS_SPI */
|
|
@ -1,9 +1,11 @@
|
|||
/*
|
||||
* Copyright (c) 2018 STMicroelectronics
|
||||
/* ST Microelectronics LIS2MDL 3-axis magnetometer sensor
|
||||
*
|
||||
* LIS2MDL mag interrupt configuration and management
|
||||
* Copyright (c) 2018-2019 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/lis2mdl.pdf
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
|
@ -21,10 +23,7 @@ static int lis2mdl_enable_int(struct device *dev, int enable)
|
|||
struct lis2mdl_data *lis2mdl = dev->driver_data;
|
||||
|
||||
/* set interrupt on mag */
|
||||
return i2c_reg_update_byte(lis2mdl->i2c, lis2mdl->i2c_addr,
|
||||
LIS2MDL_CFG_REG_C,
|
||||
LIS2MDL_INT_MAG_MASK,
|
||||
enable ? LIS2MDL_INT_MAG : 0);
|
||||
return lis2mdl_drdy_on_pin_set(lis2mdl->ctx, enable);
|
||||
}
|
||||
|
||||
/* link external trigger to event data ready */
|
||||
|
@ -33,18 +32,14 @@ int lis2mdl_trigger_set(struct device *dev,
|
|||
sensor_trigger_handler_t handler)
|
||||
{
|
||||
struct lis2mdl_data *lis2mdl = dev->driver_data;
|
||||
u8_t raw[LIS2MDL_OUT_REG_SIZE];
|
||||
axis3bit16_t raw;
|
||||
|
||||
if (trig->chan == SENSOR_CHAN_MAGN_XYZ) {
|
||||
lis2mdl->handler_drdy = handler;
|
||||
if (handler) {
|
||||
/* fetch raw data sample: re-trigger lost interrupt */
|
||||
if (i2c_burst_read(lis2mdl->i2c, lis2mdl->i2c_addr,
|
||||
LIS2MDL_OUT_REG, raw,
|
||||
sizeof(raw)) < 0) {
|
||||
LOG_ERR("Failed to fetch raw data sample.");
|
||||
return -EIO;
|
||||
}
|
||||
lis2mdl_magnetic_raw_get(lis2mdl->ctx, raw.u8bit);
|
||||
|
||||
return lis2mdl_enable_int(dev, 1);
|
||||
} else {
|
||||
return lis2mdl_enable_int(dev, 0);
|
||||
|
@ -59,7 +54,7 @@ static void lis2mdl_handle_interrupt(void *arg)
|
|||
{
|
||||
struct device *dev = arg;
|
||||
struct lis2mdl_data *lis2mdl = dev->driver_data;
|
||||
const struct lis2mdl_device_config *const config =
|
||||
const struct lis2mdl_config *const config =
|
||||
dev->config->config_info;
|
||||
struct sensor_trigger drdy_trigger = {
|
||||
.type = SENSOR_TRIG_DATA_READY,
|
||||
|
@ -77,8 +72,7 @@ static void lis2mdl_gpio_callback(struct device *dev,
|
|||
{
|
||||
struct lis2mdl_data *lis2mdl =
|
||||
CONTAINER_OF(cb, struct lis2mdl_data, gpio_cb);
|
||||
const struct lis2mdl_device_config *const config =
|
||||
dev->config->config_info;
|
||||
const struct lis2mdl_config *const config = dev->config->config_info;
|
||||
|
||||
ARG_UNUSED(pins);
|
||||
|
||||
|
@ -119,8 +113,7 @@ static void lis2mdl_work_cb(struct k_work *work)
|
|||
int lis2mdl_init_interrupt(struct device *dev)
|
||||
{
|
||||
struct lis2mdl_data *lis2mdl = dev->driver_data;
|
||||
const struct lis2mdl_device_config *const config =
|
||||
dev->config->config_info;
|
||||
const struct lis2mdl_config *const config = dev->config->config_info;
|
||||
|
||||
/* setup data ready gpio interrupt */
|
||||
lis2mdl->gpio = device_get_binding(config->gpio_name);
|
||||
|
|
|
@ -195,6 +195,7 @@
|
|||
#define DT_INST_0_ST_LIS2MDL_BASE_ADDRESS 0x19
|
||||
#define DT_INST_0_ST_LIS2MDL_IRQ_GPIOS_CONTROLLER ""
|
||||
#define DT_INST_0_ST_LIS2MDL_IRQ_GPIOS_PIN 0
|
||||
#define DT_ST_LIS2MDL_BUS_I2C 1
|
||||
#endif
|
||||
|
||||
#ifndef DT_INST_0_ST_LIS2DW12_LABEL
|
||||
|
@ -336,6 +337,18 @@
|
|||
#define DT_ST_LIS2DW12_BUS_SPI 1
|
||||
#endif
|
||||
|
||||
#ifndef DT_INST_0_ST_LIS2MDL_LABEL
|
||||
#define DT_INST_0_ST_LIS2MDL_LABEL ""
|
||||
#define DT_INST_0_ST_LIS2MDL_BUS_NAME ""
|
||||
#define DT_INST_0_ST_LIS2MDL_SPI_MAX_FREQUENCY 100000
|
||||
#define DT_INST_0_ST_LIS2MDL_BASE_ADDRESS 1
|
||||
#define DT_INST_0_ST_LIS2MDL_IRQ_GPIOS_CONTROLLER ""
|
||||
#define DT_INST_0_ST_LIS2MDL_IRQ_GPIOS_PIN 0
|
||||
#define DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER 0
|
||||
#define DT_INST_0_ST_LIS2MDL_CS_GPIOS_PIN 0
|
||||
#define DT_ST_LIS2MDL_BUS_SPI 1
|
||||
#endif
|
||||
|
||||
#ifndef DT_INST_0_ST_LPS22HH_LABEL
|
||||
#define DT_INST_0_ST_LPS22HH_LABEL ""
|
||||
#define DT_INST_0_ST_LPS22HH_BUS_NAME ""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue