sensor: hmc5883l: convert to device tree

This commit converts the existing hcm5883l 3-axis magnetometer
driver to use device tree for the I2C and GPIO selection.

It also adds a basic sample application for this sensor, using the
frdm-k64f development board to demonstrate how the interrupt
GPIO pin and I2C bus can be selected.

Signed-off-by: Kevin Townsend <kevin@ktownsend.com>
This commit is contained in:
Kevin Townsend 2019-11-07 17:29:19 +01:00 committed by Kumar Gala
commit 740f6868a5
12 changed files with 166 additions and 62 deletions

View file

@ -9,19 +9,6 @@ menuconfig HMC5883L
if HMC5883L
config HMC5883L_NAME
string "Driver name"
default "HMC5883L"
help
Device name with which the HMC5883L sensor is identified.
config HMC5883L_I2C_MASTER_DEV_NAME
string "I2C master where HMC5883L is connected"
default "I2C_0"
help
Specify the device name of the I2C master device to which HMC5883L
is connected.
choice
prompt "Trigger mode"
default HMC5883L_TRIGGER_GLOBAL_THREAD
@ -46,22 +33,6 @@ endchoice
config HMC5883L_TRIGGER
bool
config HMC5883L_GPIO_DEV_NAME
string "GPIO device"
default "GPIO_0"
depends on HMC5883L_TRIGGER
help
The device name of the GPIO device to which the HMC5883L interrupt
pin is connected.
config HMC5883L_GPIO_PIN_NUM
int "Interrupt GPIO pin number"
default 0
depends on HMC5883L_TRIGGER
help
The number of the GPIO on which the interrupt signal from the
HMC5883L chip will be received.
config HMC5883L_THREAD_PRIORITY
int "Thread priority"
depends on HMC5883L_TRIGGER_OWN_THREAD

View file

@ -59,7 +59,8 @@ static int hmc5883l_sample_fetch(struct device *dev, enum sensor_channel chan)
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL);
/* fetch magnetometer sample */
if (i2c_burst_read(drv_data->i2c, HMC5883L_I2C_ADDR,
if (i2c_burst_read(drv_data->i2c,
DT_INST_0_HONEYWELL_HMC5883L_BASE_ADDRESS,
HMC5883L_REG_DATA_START, (u8_t *)buf, 6) < 0) {
LOG_ERR("Failed to fetch megnetometer sample.");
return -EIO;
@ -85,15 +86,17 @@ int hmc5883l_init(struct device *dev)
struct hmc5883l_data *drv_data = dev->driver_data;
u8_t chip_cfg[3], id[3], idx;
drv_data->i2c = device_get_binding(CONFIG_HMC5883L_I2C_MASTER_DEV_NAME);
drv_data->i2c = device_get_binding(
DT_INST_0_HONEYWELL_HMC5883L_BUS_NAME);
if (drv_data->i2c == NULL) {
LOG_ERR("Failed to get pointer to %s device.",
CONFIG_HMC5883L_I2C_MASTER_DEV_NAME);
DT_INST_0_HONEYWELL_HMC5883L_BUS_NAME);
return -EINVAL;
}
/* check chip ID */
if (i2c_burst_read(drv_data->i2c, HMC5883L_I2C_ADDR,
if (i2c_burst_read(drv_data->i2c,
DT_INST_0_HONEYWELL_HMC5883L_BASE_ADDRESS,
HMC5883L_REG_CHIP_ID, id, 3) < 0) {
LOG_ERR("Failed to read chip ID.");
return -EIO;
@ -136,7 +139,8 @@ int hmc5883l_init(struct device *dev)
chip_cfg[1] = drv_data->gain_idx << HMC5883L_GAIN_SHIFT;
chip_cfg[2] = HMC5883L_MODE_CONTINUOUS;
if (i2c_burst_write(drv_data->i2c, HMC5883L_I2C_ADDR,
if (i2c_burst_write(drv_data->i2c,
DT_INST_0_HONEYWELL_HMC5883L_BASE_ADDRESS,
HMC5883L_REG_CONFIG_A, chip_cfg, 3) < 0) {
LOG_ERR("Failed to configure chip.");
return -EIO;
@ -154,6 +158,6 @@ int hmc5883l_init(struct device *dev)
struct hmc5883l_data hmc5883l_driver;
DEVICE_AND_API_INIT(hmc5883l, CONFIG_HMC5883L_NAME, hmc5883l_init,
&hmc5883l_driver, NULL, POST_KERNEL,
DEVICE_AND_API_INIT(hmc5883l, DT_INST_0_HONEYWELL_HMC5883L_LABEL,
hmc5883l_init, &hmc5883l_driver, NULL, POST_KERNEL,
CONFIG_SENSOR_INIT_PRIORITY, &hmc5883l_driver_api);

View file

@ -12,8 +12,6 @@
#include <zephyr/types.h>
#include <drivers/gpio.h>
#define HMC5883L_I2C_ADDR 0x1E
#define HMC5883L_REG_CONFIG_A 0x00
#define HMC5883L_ODR_SHIFT 2
@ -30,11 +28,11 @@
#define HMC5883L_CHIP_ID_B '4'
#define HMC5883L_CHIP_ID_C '3'
static const char * const hmc5883l_odr_strings[] = {
static const char *const hmc5883l_odr_strings[] = {
"0.75", "1.5", "3", "7.5", "15", "30", "75"
};
static const char * const hmc5883l_fs_strings[] = {
static const char *const hmc5883l_fs_strings[] = {
"0.88", "1.3", "1.9", "2.5", "4", "4.7", "5.6", "8.1"
};

View file

@ -23,7 +23,8 @@ int hmc5883l_trigger_set(struct device *dev,
__ASSERT_NO_MSG(trig->type == SENSOR_TRIG_DATA_READY);
gpio_pin_disable_callback(drv_data->gpio, CONFIG_HMC5883L_GPIO_PIN_NUM);
gpio_pin_disable_callback(drv_data->gpio,
DT_INST_0_HONEYWELL_HMC5883L_INT_GPIOS_PIN);
drv_data->data_ready_handler = handler;
if (handler == NULL) {
@ -32,7 +33,8 @@ int hmc5883l_trigger_set(struct device *dev,
drv_data->data_ready_trigger = *trig;
gpio_pin_enable_callback(drv_data->gpio, CONFIG_HMC5883L_GPIO_PIN_NUM);
gpio_pin_enable_callback(drv_data->gpio,
DT_INST_0_HONEYWELL_HMC5883L_INT_GPIOS_PIN);
return 0;
}
@ -45,7 +47,8 @@ static void hmc5883l_gpio_callback(struct device *dev,
ARG_UNUSED(pins);
gpio_pin_disable_callback(dev, CONFIG_HMC5883L_GPIO_PIN_NUM);
gpio_pin_disable_callback(dev,
DT_INST_0_HONEYWELL_HMC5883L_INT_GPIOS_PIN);
#if defined(CONFIG_HMC5883L_TRIGGER_OWN_THREAD)
k_sem_give(&drv_data->gpio_sem);
@ -64,7 +67,8 @@ static void hmc5883l_thread_cb(void *arg)
&drv_data->data_ready_trigger);
}
gpio_pin_enable_callback(drv_data->gpio, CONFIG_HMC5883L_GPIO_PIN_NUM);
gpio_pin_enable_callback(drv_data->gpio,
DT_INST_0_HONEYWELL_HMC5883L_INT_GPIOS_PIN);
}
#ifdef CONFIG_HMC5883L_TRIGGER_OWN_THREAD
@ -97,20 +101,22 @@ int hmc5883l_init_interrupt(struct device *dev)
struct hmc5883l_data *drv_data = dev->driver_data;
/* setup data ready gpio interrupt */
drv_data->gpio = device_get_binding(CONFIG_HMC5883L_GPIO_DEV_NAME);
drv_data->gpio = device_get_binding(
DT_INST_0_HONEYWELL_HMC5883L_INT_GPIOS_CONTROLLER);
if (drv_data->gpio == NULL) {
LOG_ERR("Failed to get pointer to %s device.",
CONFIG_HMC5883L_GPIO_DEV_NAME);
DT_INST_0_HONEYWELL_HMC5883L_INT_GPIOS_CONTROLLER);
return -EINVAL;
}
gpio_pin_configure(drv_data->gpio, CONFIG_HMC5883L_GPIO_PIN_NUM,
gpio_pin_configure(drv_data->gpio,
DT_INST_0_HONEYWELL_HMC5883L_INT_GPIOS_PIN,
GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE);
gpio_init_callback(&drv_data->gpio_cb,
hmc5883l_gpio_callback,
BIT(CONFIG_HMC5883L_GPIO_PIN_NUM));
BIT(DT_INST_0_HONEYWELL_HMC5883L_INT_GPIOS_PIN));
if (gpio_add_callback(drv_data->gpio, &drv_data->gpio_cb) < 0) {
LOG_ERR("Failed to set gpio callback.");
@ -130,7 +136,8 @@ int hmc5883l_init_interrupt(struct device *dev)
drv_data->dev = dev;
#endif
gpio_pin_enable_callback(drv_data->gpio, CONFIG_HMC5883L_GPIO_PIN_NUM);
gpio_pin_enable_callback(drv_data->gpio,
DT_INST_0_HONEYWELL_HMC5883L_INT_GPIOS_PIN);
return 0;
}

View file

@ -0,0 +1,17 @@
# Copyright (c) 2019 Linaro Limited
# SPDX-License-Identifier: Apache-2.0
title: Honeywell MEMS sensors HMC5883L
description: |
This binding gives a base representation of the HMC5883L 3-axis
magnetometer sensor
compatible: "honeywell,hmc5883l"
include: i2c-device.yaml
properties:
int-gpios:
type: phandle-array
required: false

View file

@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.13.1)
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
project(hmc5883l)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})

View file

@ -0,0 +1,5 @@
Title: hmc5883l
Description:
A simple example using the hmc5883l 3-axis magnetometer sensor.

View file

@ -0,0 +1,14 @@
/*
* Copyright (c) 2019, Linaro Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
&i2c0 {
hmc5883l@1e {
compatible = "honeywell,hmc5883l";
reg = <0x1E>;
int-gpios = <&gpioc 12 0>;
label = "HMC5883L";
};
};

View file

@ -0,0 +1,5 @@
CONFIG_I2C=y
CONFIG_GPIO=y
CONFIG_SENSOR=y
CONFIG_HMC5883L=y
CONFIG_HMC5883L_TRIGGER_GLOBAL_THREAD=y

View file

@ -0,0 +1,8 @@
sample:
name: HMC5883L Sensor Sample
tests:
sample.sensor.hmc5883l:
harness: sensor
tags: sensors
depends_on: i2c gpio
filter: dt_compat_enabled("honeywell,hmc5883l")

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019, Linaro Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <device.h>
#include <drivers/sensor.h>
#include <stdio.h>
#include <sys/printk.h>
static s32_t read_sensor(struct device *sensor)
{
struct sensor_value val[3];
s32_t ret = 0;
ret = sensor_sample_fetch(sensor);
if (ret) {
printk("sensor_sample_fetch failed ret %d\n", ret);
goto end;
}
ret = sensor_channel_get(sensor, SENSOR_CHAN_MAGN_XYZ, val);
if (ret < 0) {
printf("Cannot read sensor channels\n");
goto end;
}
printf("( x y z ) = ( %f %f %f )\n", sensor_value_to_double(&val[0]),
sensor_value_to_double(&val[1]),
sensor_value_to_double(&val[2]));
end:
return ret;
}
void main(void)
{
struct device *dev;
dev = device_get_binding(DT_INST_0_HONEYWELL_HMC5883L_LABEL);
if (dev == NULL) {
printk("Could not get %s device at I2C addr 0x%02X\n",
DT_INST_0_HONEYWELL_HMC5883L_LABEL,
DT_INST_0_HONEYWELL_HMC5883L_BASE_ADDRESS);
return;
}
printk("device is %p, name is %s\n", dev, dev->config->name);
while (1) {
read_sensor(dev);
k_sleep(K_MSEC(1000));
}
}

View file

@ -399,6 +399,15 @@
#define DT_INST_0_BOSCH_BMC150_MAGN_DRDY_GPIOS_PIN 0
#endif
#ifndef DT_INST_0_HONEYWELL_HMC5883L_LABEL
#define DT_INST_0_HONEYWELL_HMC5883L_LABEL ""
#define DT_INST_0_HONEYWELL_HMC5883L_BASE_ADDRESS 0
#define DT_INST_0_HONEYWELL_HMC5883L_BUS_NAME ""
#define DT_INST_0_HONEYWELL_HMC5883L_INT_GPIOS_CONTROLLER ""
#define DT_INST_0_HONEYWELL_HMC5883L_INT_GPIOS_FLAGS 0
#define DT_INST_0_HONEYWELL_HMC5883L_INT_GPIOS_PIN 0
#endif
#endif /* CONFIG_HAS_DTS_I2C */
#ifndef DT_ADXL372_DEV_NAME