From 740f6868a58d40d5963d592a9d19dce6cee8ea00 Mon Sep 17 00:00:00 2001 From: Kevin Townsend Date: Thu, 7 Nov 2019 17:29:19 +0100 Subject: [PATCH] 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 --- drivers/sensor/hmc5883l/Kconfig | 29 ---------- drivers/sensor/hmc5883l/hmc5883l.c | 18 +++--- drivers/sensor/hmc5883l/hmc5883l.h | 32 +++++----- drivers/sensor/hmc5883l/hmc5883l_trigger.c | 25 +++++--- dts/bindings/sensor/honeywell,hmc5883l.yaml | 17 ++++++ samples/sensor/hmc5883l/CMakeLists.txt | 8 +++ samples/sensor/hmc5883l/README.txt | 5 ++ .../sensor/hmc5883l/boards/frdm_k64f.overlay | 14 +++++ samples/sensor/hmc5883l/prj.conf | 5 ++ samples/sensor/hmc5883l/sample.yaml | 8 +++ samples/sensor/hmc5883l/src/main.c | 58 +++++++++++++++++++ tests/drivers/build_all/dts_fixup.h | 9 +++ 12 files changed, 166 insertions(+), 62 deletions(-) create mode 100644 dts/bindings/sensor/honeywell,hmc5883l.yaml create mode 100644 samples/sensor/hmc5883l/CMakeLists.txt create mode 100644 samples/sensor/hmc5883l/README.txt create mode 100644 samples/sensor/hmc5883l/boards/frdm_k64f.overlay create mode 100644 samples/sensor/hmc5883l/prj.conf create mode 100644 samples/sensor/hmc5883l/sample.yaml create mode 100644 samples/sensor/hmc5883l/src/main.c diff --git a/drivers/sensor/hmc5883l/Kconfig b/drivers/sensor/hmc5883l/Kconfig index 227e520f431..22ce71756e7 100644 --- a/drivers/sensor/hmc5883l/Kconfig +++ b/drivers/sensor/hmc5883l/Kconfig @@ -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 diff --git a/drivers/sensor/hmc5883l/hmc5883l.c b/drivers/sensor/hmc5883l/hmc5883l.c index 6a97b73f583..ab98b480037 100644 --- a/drivers/sensor/hmc5883l/hmc5883l.c +++ b/drivers/sensor/hmc5883l/hmc5883l.c @@ -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); diff --git a/drivers/sensor/hmc5883l/hmc5883l.h b/drivers/sensor/hmc5883l/hmc5883l.h index f7d3ead8992..f1735cf7577 100644 --- a/drivers/sensor/hmc5883l/hmc5883l.h +++ b/drivers/sensor/hmc5883l/hmc5883l.h @@ -12,29 +12,27 @@ #include #include -#define HMC5883L_I2C_ADDR 0x1E +#define HMC5883L_REG_CONFIG_A 0x00 +#define HMC5883L_ODR_SHIFT 2 -#define HMC5883L_REG_CONFIG_A 0x00 -#define HMC5883L_ODR_SHIFT 2 +#define HMC5883L_REG_CONFIG_B 0x01 +#define HMC5883L_GAIN_SHIFT 5 -#define HMC5883L_REG_CONFIG_B 0x01 -#define HMC5883L_GAIN_SHIFT 5 +#define HMC5883L_REG_MODE 0x02 +#define HMC5883L_MODE_CONTINUOUS 0 -#define HMC5883L_REG_MODE 0x02 -#define HMC5883L_MODE_CONTINUOUS 0 +#define HMC5883L_REG_DATA_START 0x03 -#define HMC5883L_REG_DATA_START 0x03 +#define HMC5883L_REG_CHIP_ID 0x0A +#define HMC5883L_CHIP_ID_A 'H' +#define HMC5883L_CHIP_ID_B '4' +#define HMC5883L_CHIP_ID_C '3' -#define HMC5883L_REG_CHIP_ID 0x0A -#define HMC5883L_CHIP_ID_A 'H' -#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" }; @@ -70,8 +68,8 @@ struct hmc5883l_data { #ifdef CONFIG_HMC5883L_TRIGGER int hmc5883l_trigger_set(struct device *dev, - const struct sensor_trigger *trig, - sensor_trigger_handler_t handler); + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); int hmc5883l_init_interrupt(struct device *dev); #endif diff --git a/drivers/sensor/hmc5883l/hmc5883l_trigger.c b/drivers/sensor/hmc5883l/hmc5883l_trigger.c index 939c4699786..64c0215c12a 100644 --- a/drivers/sensor/hmc5883l/hmc5883l_trigger.c +++ b/drivers/sensor/hmc5883l/hmc5883l_trigger.c @@ -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; } diff --git a/dts/bindings/sensor/honeywell,hmc5883l.yaml b/dts/bindings/sensor/honeywell,hmc5883l.yaml new file mode 100644 index 00000000000..23a14f08a39 --- /dev/null +++ b/dts/bindings/sensor/honeywell,hmc5883l.yaml @@ -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 diff --git a/samples/sensor/hmc5883l/CMakeLists.txt b/samples/sensor/hmc5883l/CMakeLists.txt new file mode 100644 index 00000000000..fc07b57cf04 --- /dev/null +++ b/samples/sensor/hmc5883l/CMakeLists.txt @@ -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}) diff --git a/samples/sensor/hmc5883l/README.txt b/samples/sensor/hmc5883l/README.txt new file mode 100644 index 00000000000..0214bc4314c --- /dev/null +++ b/samples/sensor/hmc5883l/README.txt @@ -0,0 +1,5 @@ +Title: hmc5883l + +Description: + +A simple example using the hmc5883l 3-axis magnetometer sensor. diff --git a/samples/sensor/hmc5883l/boards/frdm_k64f.overlay b/samples/sensor/hmc5883l/boards/frdm_k64f.overlay new file mode 100644 index 00000000000..644644acbe8 --- /dev/null +++ b/samples/sensor/hmc5883l/boards/frdm_k64f.overlay @@ -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"; + }; +}; diff --git a/samples/sensor/hmc5883l/prj.conf b/samples/sensor/hmc5883l/prj.conf new file mode 100644 index 00000000000..9cf4c6e0864 --- /dev/null +++ b/samples/sensor/hmc5883l/prj.conf @@ -0,0 +1,5 @@ +CONFIG_I2C=y +CONFIG_GPIO=y +CONFIG_SENSOR=y +CONFIG_HMC5883L=y +CONFIG_HMC5883L_TRIGGER_GLOBAL_THREAD=y diff --git a/samples/sensor/hmc5883l/sample.yaml b/samples/sensor/hmc5883l/sample.yaml new file mode 100644 index 00000000000..6a9b72aef72 --- /dev/null +++ b/samples/sensor/hmc5883l/sample.yaml @@ -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") diff --git a/samples/sensor/hmc5883l/src/main.c b/samples/sensor/hmc5883l/src/main.c new file mode 100644 index 00000000000..15e659694f6 --- /dev/null +++ b/samples/sensor/hmc5883l/src/main.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019, Linaro Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + + +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)); + } +} diff --git a/tests/drivers/build_all/dts_fixup.h b/tests/drivers/build_all/dts_fixup.h index 93f062e4237..68f700c3d0a 100644 --- a/tests/drivers/build_all/dts_fixup.h +++ b/tests/drivers/build_all/dts_fixup.h @@ -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