diff --git a/cmake/modules/header_files.cmake b/cmake/modules/header_files.cmake new file mode 100644 index 00000000000000..f180e1813798b6 --- /dev/null +++ b/cmake/modules/header_files.cmake @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2023, Google LLC + +include_guard(GLOBAL) + +# Generate headers are used by the base system. +# The logic for generating devicetree_generated.h is kept separately +# in dts.cmake. +# +# Outcome: +# ${BINARY_DIR_INCLUDE_GENERATED}/sensor_channels.h exists +# +# Required variables: +# BINARY_DIR_INCLUDE_GENERATED: where to put generated include files +# +# Optional variables: +# None +# +# Optional environment variables: +# None + +set(SENSOR_CHANNELS_INPUT ${ZEPHYR_BASE}/include/zephyr/dt-bindings/sensor/sensor.h) +set(SENSOR_CHANNELS_LINE_REGEX "^#define[ \t\r\n]*SENSOR_CHAN_.*$") +set(SENSOR_CHANNELS_ENUM_REGEX "^#define[ \t\r\n]+(SENSOR_CHAN_[^ \t\r\n]+)[ \t\r\n]+([^ \t\r\n]+).*$") +set(SENSOR_CHANNELS ${BINARY_DIR_INCLUDE_GENERATED}/sensor_channels.h) + +# Generate an enum from an array of strings containing macro definitions +# TODO document this +function(zephyr_gen_enum_from_macros name list out) +# TODO Add header guards and "generated by" text + file(WRITE ${out} "enum " ${name} "{\n") + foreach(line ${list}) + string(REGEX REPLACE ${SENSOR_CHANNELS_ENUM_REGEX} "\t\\1 = \\2,\n" symbol ${line}) + file(APPEND ${out} ${symbol}) + endforeach() + file(APPEND ${out} "};") +endfunction() + +file(STRINGS ${SENSOR_CHANNELS_INPUT} channels REGEX ${SENSOR_CHANNELS_LINE_REGEX}) +zephyr_gen_enum_from_macros("sensor_channel" "${channels}" ${SENSOR_CHANNELS}) diff --git a/cmake/modules/zephyr_default.cmake b/cmake/modules/zephyr_default.cmake index 98a580c3a2d5da..9125d6d9509dd1 100644 --- a/cmake/modules/zephyr_default.cmake +++ b/cmake/modules/zephyr_default.cmake @@ -106,6 +106,7 @@ list(APPEND zephyr_cmake_modules "\${pre_dt_board}") # DTS should be close to kconfig because CONFIG_ variables from # kconfig and dts should be available at the same time. +list(APPEND zephyr_cmake_modules header_files) list(APPEND zephyr_cmake_modules dts) list(APPEND zephyr_cmake_modules kconfig) list(APPEND zephyr_cmake_modules soc) diff --git a/drivers/sensor/sensor_shell.c b/drivers/sensor/sensor_shell.c index a85eab23e43ec3..cd158c686d1857 100644 --- a/drivers/sensor/sensor_shell.c +++ b/drivers/sensor/sensor_shell.c @@ -658,12 +658,31 @@ static int cmd_get_sensor_info(const struct shell *sh, size_t argc, char **argv) const char *null_str = "(null)"; STRUCT_SECTION_FOREACH(sensor_info, sensor) { - shell_print(sh, + /* + * shell_fprintf is a must here as we need to calll the printf + * multiple times, without having a newline char inserted + * between invocations. + */ + shell_fprintf(sh, SHELL_NORMAL, "device name: %s, vendor: %s, model: %s, " "friendly name: %s", sensor->dev->name, sensor->vendor ? sensor->vendor : null_str, sensor->model ? sensor->model : null_str, sensor->friendly_name ? sensor->friendly_name : null_str); + if (sensor->num_channels > 0) { + /* Can't use shell_print here as it appends '\n'. */ + shell_fprintf(sh, SHELL_NORMAL, ", supported channels:"); + for (int i = 0; i < sensor->num_channels; i++) { + if (sensor->channels[i] < ARRAY_SIZE(sensor_channel_name)) { + shell_fprintf(sh, SHELL_NORMAL, " %s", + sensor_channel_name[sensor->channels[i]]); + } else { + shell_fprintf(sh, SHELL_NORMAL, " unknown(%d)", + sensor->channels[i]); + } + } + } + shell_fprintf(sh, SHELL_NORMAL, "\n"); } return 0; #else diff --git a/dts/bindings/sensor/sensor-device.yaml b/dts/bindings/sensor/sensor-device.yaml index ad905e26957701..e0e9e76509f1ae 100644 --- a/dts/bindings/sensor/sensor-device.yaml +++ b/dts/bindings/sensor/sensor-device.yaml @@ -17,3 +17,16 @@ properties: This property is defined in the Generic Sensor Property Usages of the HID Usage Tables specification (https://usb.org/sites/default/files/hut1_3_0.pdf, section 22.5). + + "#sensor-cells": + type: int + description: | + Number of items to expect in a sensor specifier. Only one cell is + supported by the sensor API. It's used to describe the sensor channel + used by a consumer. + + supported-channels: + type: array + description: | + List of sensor channels supported by this device. Example: + diff --git a/dts/bindings/test/vnd,phandle-holder.yaml b/dts/bindings/test/vnd,phandle-holder.yaml index daf0b0beba00fe..7e60306e3f2e32 100644 --- a/dts/bindings/test/vnd,phandle-holder.yaml +++ b/dts/bindings/test/vnd,phandle-holder.yaml @@ -17,6 +17,8 @@ properties: foo-names: {type: "string-array"} pwms: {type: "phandle-array"} pwm-names: {type: "string-array"} + sensors: {type: "phandle-array"} + sensor-names: {type: "string-array"} bar: type: "phandle-array" specifier-space: baz diff --git a/dts/bindings/test/vnd,sensor-device.yaml b/dts/bindings/test/vnd,sensor-device.yaml new file mode 100644 index 00000000000000..23130d0b8e2c4b --- /dev/null +++ b/dts/bindings/test/vnd,sensor-device.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: VND sensor device + +compatible: "vnd,sensor-device" + +include: [sensor-device.yaml, base.yaml] + +properties: + reg: + required: true + + "#sensor-cells": + const: 1 + +sensor-cells: + - channel diff --git a/include/zephyr/devicetree.h b/include/zephyr/devicetree.h index c249ad371e2e4a..8159410daa0739 100644 --- a/include/zephyr/devicetree.h +++ b/include/zephyr/devicetree.h @@ -4315,5 +4315,6 @@ #include #include #include +#include #endif /* DEVICETREE_H */ diff --git a/include/zephyr/devicetree/sensors.h b/include/zephyr/devicetree/sensors.h new file mode 100644 index 00000000000000..dc0986a73ef0b2 --- /dev/null +++ b/include/zephyr/devicetree/sensors.h @@ -0,0 +1,135 @@ +/** + * @file + * @brief Sensor Devicetree macro public API header file. + */ + +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DEVICETREE_SENSORS_H_ +#define ZEPHYR_INCLUDE_DEVICETREE_SENSORS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup devicetree-sensors Devicetree Sensor API + * @ingroup devicetree + * @{ + */ + +/** + * @brief Get the node identifier for the sensor device from a + * sensors property at an index + * + * Example devicetree fragment: + * + * temp_amb: amb-sensor@... { ... }; + * + * temp_cpu: cpu-sensor@... { ... }; + * + * n: node { + * sensors = <&temp_cpu DT_SENSOR_CHAN_DIE_TEMP>, + * <&temp_amb DT_SENSOR_CHAN_AMBIENT_TEMP>; + * }; + * + * Example usage: + * + * DT_SENSOR_DEV_BY_IDX(DT_NODELABEL(n), 0) // DT_NODELABEL(temp_cpu) + * DT_SENSOR_DEV_BY_IDX(DT_NODELABEL(n), 1) // DT_NODELABEL(temp_amb) + * + * @param node_id node identifier for a node with a sensors property + * @param idx logical index into sensors property + * @return the node identifier for the sensor device referenced at index "idx" + * @see DT_PROP_BY_PHANDLE_IDX() + */ +#define DT_SENSOR_DEV_BY_IDX(node_id, idx) \ + DT_PHANDLE_BY_IDX(node_id, sensors, idx) + +/** + * @brief Equivalent to DT_SENSOR_DEV_BY_IDX(node_id, 0) + * @param node_id node identifier for a node with a sensors property + * @return the node identifier for the sensor device at index 0 + * in the node's "sensors" property + * @see DT_SENSOR_DEV_BY_IDX() + */ +#define DT_SENSOR_DEV(node_id) DT_SENSOR_DEV_BY_IDX(node_id, 0) + +/** + * @brief Get the node identifier for the sensor device from a + * sensors property by name + * + * Example devicetree fragment: + * + * temp_amb: amb-sensor@... { ... }; + * + * temp_cpu: cpu-sensor@... { ... }; + * + * n: node { + * sensors = <&temp_cpu DT_SENSOR_CHAN_DIE_TEMP>, + * <&temp_amb DT_SENSOR_CHAN_AMBIENT_TEMP>; + * sensor-names = "cpu", "ambient"; + * }; + * + * Example usage: + * + * DT_SENSOR_DEV_BY_NAME(DT_NODELABEL(n), cpu) // DT_NODELABEL(temp_cpu) + * DT_SENSOR_DEV_BY_NAME(DT_NODELABEL(n), ambient) // DT_NODELABEL(temp_amb) + * + * @param node_id node identifier for a node with a sensors property + * @param name lowercase-and-underscores name of a sensors element + * as defined by the node's sensor-names property + * @return the node identifier for the sensor device in the named element + * @see DT_PHANDLE_BY_NAME() + */ +#define DT_SENSOR_DEV_BY_NAME(node_id, name) \ + DT_PHANDLE_BY_NAME(node_id, sensors, name) + +/** + * @brief Get a sensor specifier's channel cell value at an index + * + * This macro only works for sensor specifiers with cells named "channel". + * Refer to the node's binding to check if necessary. + * + * @param node_id node identifier for a node with a sensor property + * @param idx logical index into sensor property + * @return the channel cell value at index "idx" + */ +#define DT_SENSOR_CHANNEL_BY_IDX(node_id, idx) \ + DT_PHA_BY_IDX(node_id, sensors, idx, channel) + +/** + * @brief Equivalent to DT_SENSOR_CHANNEL_BY_IDX(node_id, 0) + * @param node_id node identifier for a node with a sensors property + * @return the channel cell value at index 0 + * @see DT_SENSOR_CHANNEL_BY_IDX() + */ +#define DT_SENSOR_CHANNEL(node_id) DT_SENSOR_CHANNEL_BY_IDX(node_id, 0) + +/** + * @brief Get a sensor specifier's channel cell value by name + * + * This macro only works for sensor specifiers with cells named "channel". + * Refer to the node's binding to check if necessary. + * + * @param node_id node identifier for a node with a sensor property + * @param name lowercase-and-underscores name of a sensor element + * as defined by the node's sensor-names property + * @return the channel cell value in the specifier at the named element + */ +#define DT_SENSOR_CHANNEL_BY_NAME(node_id, name) \ + DT_PHA_BY_NAME(node_id, sensors, name, channel) + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DEVICETREE_SENSORS_H_ */ diff --git a/include/zephyr/drivers/sensor.h b/include/zephyr/drivers/sensor.h index 903acb6f03ac46..f47c7d2d9d3566 100644 --- a/include/zephyr/drivers/sensor.h +++ b/include/zephyr/drivers/sensor.h @@ -29,6 +29,9 @@ #include #include +/* Autogenerated during build */ +#include + #ifdef __cplusplus extern "C" { #endif @@ -53,160 +56,6 @@ struct sensor_value { int32_t val2; }; -/** - * @brief Sensor channels. - */ -enum sensor_channel { - /** Acceleration on the X axis, in m/s^2. */ - SENSOR_CHAN_ACCEL_X, - /** Acceleration on the Y axis, in m/s^2. */ - SENSOR_CHAN_ACCEL_Y, - /** Acceleration on the Z axis, in m/s^2. */ - SENSOR_CHAN_ACCEL_Z, - /** Acceleration on the X, Y and Z axes. */ - SENSOR_CHAN_ACCEL_XYZ, - /** Angular velocity around the X axis, in radians/s. */ - SENSOR_CHAN_GYRO_X, - /** Angular velocity around the Y axis, in radians/s. */ - SENSOR_CHAN_GYRO_Y, - /** Angular velocity around the Z axis, in radians/s. */ - SENSOR_CHAN_GYRO_Z, - /** Angular velocity around the X, Y and Z axes. */ - SENSOR_CHAN_GYRO_XYZ, - /** Magnetic field on the X axis, in Gauss. */ - SENSOR_CHAN_MAGN_X, - /** Magnetic field on the Y axis, in Gauss. */ - SENSOR_CHAN_MAGN_Y, - /** Magnetic field on the Z axis, in Gauss. */ - SENSOR_CHAN_MAGN_Z, - /** Magnetic field on the X, Y and Z axes. */ - SENSOR_CHAN_MAGN_XYZ, - /** Device die temperature in degrees Celsius. */ - SENSOR_CHAN_DIE_TEMP, - /** Ambient temperature in degrees Celsius. */ - SENSOR_CHAN_AMBIENT_TEMP, - /** Pressure in kilopascal. */ - SENSOR_CHAN_PRESS, - /** - * Proximity. Adimensional. A value of 1 indicates that an - * object is close. - */ - SENSOR_CHAN_PROX, - /** Humidity, in percent. */ - SENSOR_CHAN_HUMIDITY, - /** Illuminance in visible spectrum, in lux. */ - SENSOR_CHAN_LIGHT, - /** Illuminance in infra-red spectrum, in lux. */ - SENSOR_CHAN_IR, - /** Illuminance in red spectrum, in lux. */ - SENSOR_CHAN_RED, - /** Illuminance in green spectrum, in lux. */ - SENSOR_CHAN_GREEN, - /** Illuminance in blue spectrum, in lux. */ - SENSOR_CHAN_BLUE, - /** Altitude, in meters */ - SENSOR_CHAN_ALTITUDE, - - /** 1.0 micro-meters Particulate Matter, in ug/m^3 */ - SENSOR_CHAN_PM_1_0, - /** 2.5 micro-meters Particulate Matter, in ug/m^3 */ - SENSOR_CHAN_PM_2_5, - /** 10 micro-meters Particulate Matter, in ug/m^3 */ - SENSOR_CHAN_PM_10, - /** Distance. From sensor to target, in meters */ - SENSOR_CHAN_DISTANCE, - - /** CO2 level, in parts per million (ppm) **/ - SENSOR_CHAN_CO2, - /** VOC level, in parts per billion (ppb) **/ - SENSOR_CHAN_VOC, - /** Gas sensor resistance in ohms. */ - SENSOR_CHAN_GAS_RES, - - /** Voltage, in volts **/ - SENSOR_CHAN_VOLTAGE, - - /** Current Shunt Voltage in milli-volts **/ - SENSOR_CHAN_VSHUNT, - - /** Current, in amps **/ - SENSOR_CHAN_CURRENT, - /** Power in watts **/ - SENSOR_CHAN_POWER, - - /** Resistance , in Ohm **/ - SENSOR_CHAN_RESISTANCE, - - /** Angular rotation, in degrees */ - SENSOR_CHAN_ROTATION, - - /** Position change on the X axis, in points. */ - SENSOR_CHAN_POS_DX, - /** Position change on the Y axis, in points. */ - SENSOR_CHAN_POS_DY, - /** Position change on the Z axis, in points. */ - SENSOR_CHAN_POS_DZ, - - /** Revolutions per minute, in RPM. */ - SENSOR_CHAN_RPM, - - /** Voltage, in volts **/ - SENSOR_CHAN_GAUGE_VOLTAGE, - /** Average current, in amps **/ - SENSOR_CHAN_GAUGE_AVG_CURRENT, - /** Standby current, in amps **/ - SENSOR_CHAN_GAUGE_STDBY_CURRENT, - /** Max load current, in amps **/ - SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT, - /** Gauge temperature **/ - SENSOR_CHAN_GAUGE_TEMP, - /** State of charge measurement in % **/ - SENSOR_CHAN_GAUGE_STATE_OF_CHARGE, - /** Full Charge Capacity in mAh **/ - SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY, - /** Remaining Charge Capacity in mAh **/ - SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY, - /** Nominal Available Capacity in mAh **/ - SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY, - /** Full Available Capacity in mAh **/ - SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY, - /** Average power in mW **/ - SENSOR_CHAN_GAUGE_AVG_POWER, - /** State of health measurement in % **/ - SENSOR_CHAN_GAUGE_STATE_OF_HEALTH, - /** Time to empty in minutes **/ - SENSOR_CHAN_GAUGE_TIME_TO_EMPTY, - /** Time to full in minutes **/ - SENSOR_CHAN_GAUGE_TIME_TO_FULL, - /** Cycle count (total number of charge/discharge cycles) **/ - SENSOR_CHAN_GAUGE_CYCLE_COUNT, - /** Design voltage of cell in V (max voltage)*/ - SENSOR_CHAN_GAUGE_DESIGN_VOLTAGE, - /** Desired voltage of cell in V (nominal voltage) */ - SENSOR_CHAN_GAUGE_DESIRED_VOLTAGE, - /** Desired charging current in mA */ - SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT, - - /** All channels. */ - SENSOR_CHAN_ALL, - - /** - * Number of all common sensor channels. - */ - SENSOR_CHAN_COMMON_COUNT, - - /** - * This and higher values are sensor specific. - * Refer to the sensor header file. - */ - SENSOR_CHAN_PRIV_START = SENSOR_CHAN_COMMON_COUNT, - - /** - * Maximum value describing a sensor channel type. - */ - SENSOR_CHAN_MAX = INT16_MAX, -}; - /** * @brief Sensor trigger types. */ @@ -345,6 +194,106 @@ enum sensor_attribute { SENSOR_ATTR_MAX = INT16_MAX, }; +/** + * @brief Container for sensor information specified in devicetree. + * + * This type contains a pointer to a sensor device and the sensor channel number + * to read the data from. + * + * @see SENSOR_DT_SPEC_GET_BY_IDX + * @see SENSOR_DT_SPEC_GET + */ +struct sensor_dt_channel_spec { + /** Sensor device instance. */ + const struct device *dev; + /** Channel number. */ + enum sensor_channel channel; +}; + +/** + * @brief Static initializer for a struct sensor_dt_channel_spec + * + * This returns a static initializer for a struct sensor_dt_channel_spec given a devicetree + * node identifier and an index. + * + * Example devicetree fragment: + * + * @code{.dts} + * n: node { + * sensors = <&temp_cpu SENSOR_CHAN_DIE_TEMP>, + * <&temp_amb SENSOR_CHAN_AMBIENT_TEMP>; + * }; + * @endcode + * + * Example usage: + * + * @code{.c} + * const struct sensor_dt_channel_spec spec = + * SENSOR_DT_SPEC_GET_BY_IDX(DT_NODELABEL(n), 1); + * + * // Initializes 'spec' to: + * // { + * // .dev = DEVICE_DT_GET(DT_NODELABEL(temp_amb)), + * // .channel = SENSOR_CHAN_AMBIENT_TEMP, + * // } + * @endcode + * + * The device (dev) must still be checked for readiness, e.g. using + * device_is_ready(). It is an error to use this macro unless the node exists, + * has the 'sensors' property, and that 'sensors' property specifies a sensor device + * and a sensor channel. + * + * @param node_id Devicetree node identifier. + * @param idx Logical index into 'sensors' property. + * + * @return Static initializer for a struct sensor_dt_channel_spec for the property. + * + * @see SENSOR_DT_SPEC_INST_GET_BY_IDX + */ +#define SENSOR_DT_SPEC_GET_BY_IDX(node_id, idx) \ + { \ + .dev = DEVICE_DT_GET(DT_SENSOR_DEV_BY_IDX(node_id, idx)), \ + .channel = DT_SENSOR_CHANNEL_BY_IDX(node_id, idx), \ + } + +/** + * @brief Static initializer for a struct sensor_dt_channel_spec from a DT_DRV_COMPAT + * instance. + * + * @param inst DT_DRV_COMPAT instance number + * @param idx Logical index into 'sensors' property. + * + * @return Static initializer for a struct sensor_dt_channel_spec for the property. + * + * @see SENSOR_DT_SPEC_GET_BY_IDX + */ +#define SENSOR_DT_SPEC_INST_GET_BY_IDX(inst, idx) \ + SENSOR_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx) + +/** + * @brief Equivalent to SENSOR_DT_SPEC_GET_BY_IDX(node_id, 0). + * + * @param node_id Devicetree node identifier. + * + * @return Static initializer for a struct sensor_dt_channel_spec for the property. + * + * @see SENSOR_DT_SPEC_GET_BY_IDX + * @see SENSOR_DT_SPEC_INST_GET + */ +#define SENSOR_DT_SPEC_GET(node_id) SENSOR_DT_SPEC_GET_BY_IDX(node_id, 0) + +/** + * @brief Equivalent to SENSOR_DT_SPEC_INST_GET_BY_IDX(inst, 0). + * + * @param inst DT_DRV_COMPAT instance number + * + * @return Static initializer for a struct sensor_dt_channel_spec for the property. + * + * @see SENSOR_DT_SPEC_INST_GET_BY_IDX + * @see SENSOR_DT_SPEC_GET + */ +#define SENSOR_DT_SPEC_INST_GET(inst) SENSOR_DT_SPEC_GET(DT_DRV_INST(inst)) + /** * @typedef sensor_trigger_handler_t * @brief Callback API upon firing of a trigger @@ -1155,14 +1104,18 @@ struct sensor_info { const char *vendor; const char *model; const char *friendly_name; + enum sensor_channel *const channels; + size_t num_channels; }; -#define SENSOR_INFO_INITIALIZER(_dev, _vendor, _model, _friendly_name) \ - { \ - .dev = _dev, \ - .vendor = _vendor, \ - .model = _model, \ - .friendly_name = _friendly_name, \ +#define SENSOR_INFO_INITIALIZER(_dev, _vendor, _model, _friendly_name, _channels, _num_channels)\ + { \ + .dev = _dev, \ + .vendor = _vendor, \ + .model = _model, \ + .friendly_name = _friendly_name, \ + .channels = _channels, \ + .num_channels = _num_channels \ } #define SENSOR_INFO_DEFINE(name, ...) \ @@ -1172,13 +1125,34 @@ struct sensor_info { #define SENSOR_INFO_DT_NAME(node_id) \ _CONCAT(__sensor_info, DEVICE_DT_NAME_GET(node_id)) -#define SENSOR_INFO_DT_DEFINE(node_id) \ - SENSOR_INFO_DEFINE(SENSOR_INFO_DT_NAME(node_id), \ - DEVICE_DT_GET(node_id), \ - DT_NODE_VENDOR_OR(node_id, NULL), \ - DT_NODE_MODEL_OR(node_id, NULL), \ - DT_PROP_OR(node_id, friendly_name, NULL)) \ - +#define SENSOR_INFO_DT_CHANNELS_NAME(node_id) \ + _CONCAT(__channels__sensor_info, DEVICE_DT_NAME_GET(node_id)) + +#define SENSOR_INFO_DT_DEFINE_CHANNELS(node_id) \ + IF_ENABLED(DT_NODE_HAS_PROP(node_id, supported_channels), \ + (BUILD_ASSERT(DT_PROP_LEN(node_id, supported_channels) > 0, "Invalid prop len");\ + static enum sensor_channel SENSOR_INFO_DT_CHANNELS_NAME(node_id)[] = \ + { \ + DT_FOREACH_PROP_ELEM_SEP(node_id, supported_channels, DT_PROP_BY_IDX, (,))\ + };)) + +#define SENSOR_INFO_DT_GET_CHANNELS(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, supported_channels), \ + (SENSOR_INFO_DT_CHANNELS_NAME(node_id)), (NULL)) + +#define SENSOR_INFO_DT_GET_CHANNELS_COUNT(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, supported_channels), \ + (ARRAY_SIZE(SENSOR_INFO_DT_CHANNELS_NAME(node_id))), (0)) + +#define SENSOR_INFO_DT_DEFINE(node_id) \ + SENSOR_INFO_DT_DEFINE_CHANNELS(node_id) \ + SENSOR_INFO_DEFINE(SENSOR_INFO_DT_NAME(node_id), \ + DEVICE_DT_GET(node_id), \ + DT_NODE_VENDOR_OR(node_id, NULL), \ + DT_NODE_MODEL_OR(node_id, NULL), \ + DT_PROP_OR(node_id, friendly_name, NULL), \ + SENSOR_INFO_DT_GET_CHANNELS(node_id), \ + SENSOR_INFO_DT_GET_CHANNELS_COUNT(node_id)) #else #define SENSOR_INFO_DEFINE(name, ...) diff --git a/include/zephyr/dt-bindings/sensor/sensor.h b/include/zephyr/dt-bindings/sensor/sensor.h new file mode 100644 index 00000000000000..f7d1423cf9ab05 --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/sensor.h @@ -0,0 +1,152 @@ +/* + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_SENSOR_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_SENSOR_H_ + +#include + +/** Acceleration on the X axis, in m/s^2. */ +#define SENSOR_CHAN_ACCEL_X 0 +/** Acceleration on the Y axis, in m/s^2. */ +#define SENSOR_CHAN_ACCEL_Y 1 +/** Acceleration on the Z axis, in m/s^2. */ +#define SENSOR_CHAN_ACCEL_Z 2 +/** Acceleration on the X, Y and Z axes. */ +#define SENSOR_CHAN_ACCEL_XYZ 3 +/** Angular velocity around the X axis, in radians/s. */ +#define SENSOR_CHAN_GYRO_X 4 +/** Angular velocity around the Y axis, in radians/s. */ +#define SENSOR_CHAN_GYRO_Y 5 +/** Angular velocity around the Z axis, in radians/s. */ +#define SENSOR_CHAN_GYRO_Z 6 +/** Angular velocity around the X, Y and Z axes. */ +#define SENSOR_CHAN_GYRO_XYZ 7 +/** Magnetic field on the X axis, in Gauss. */ +#define SENSOR_CHAN_MAGN_X 8 +/** Magnetic field on the Y axis, in Gauss. */ +#define SENSOR_CHAN_MAGN_Y 9 +/** Magnetic field on the Z axis, in Gauss. */ +#define SENSOR_CHAN_MAGN_Z 10 +/** Magnetic field on the X, Y and Z axes. */ +#define SENSOR_CHAN_MAGN_XYZ 11 +/** Device die temperature in degrees Celsius. */ +#define SENSOR_CHAN_DIE_TEMP 12 +/** Ambient temperature in degrees Celsius. */ +#define SENSOR_CHAN_AMBIENT_TEMP 13 +/** Pressure in kilopascal. */ +#define SENSOR_CHAN_PRESS 14 +/** Proximity. Adimensional. A value of 1 indicates that an object is close. */ +#define SENSOR_CHAN_PROX 15 +/** Humidity, in percent. */ +#define SENSOR_CHAN_HUMIDITY 16 +/** Illuminance in visible spectrum, in lux. */ +#define SENSOR_CHAN_LIGHT 17 +/** Illuminance in infra-red spectrum, in lux. */ +#define SENSOR_CHAN_IR 18 +/** Illuminance in red spectrum, in lux. */ +#define SENSOR_CHAN_RED 19 +/** Illuminance in green spectrum, in lux. */ +#define SENSOR_CHAN_GREEN 20 +/** Illuminance in blue spectrum, in lux. */ +#define SENSOR_CHAN_BLUE 21 +/** Altitude, in meters */ +#define SENSOR_CHAN_ALTITUDE 22 + +/** 1.0 micro-meters Particulate Matter, in ug/m^3 */ +#define SENSOR_CHAN_PM_1_0 23 +/** 2.5 micro-meters Particulate Matter, in ug/m^3 */ +#define SENSOR_CHAN_PM_2_5 24 +/** 10 micro-meters Particulate Matter, in ug/m^3 */ +#define SENSOR_CHAN_PM_10 25 +/** Distance. From sensor to target, in meters */ +#define SENSOR_CHAN_DISTANCE 26 + +/** CO2 level, in parts per million (ppm) **/ +#define SENSOR_CHAN_CO2 27 +/** VOC level, in parts per billion (ppb) **/ +#define SENSOR_CHAN_VOC 28 +/** Gas sensor resistance in ohms. */ +#define SENSOR_CHAN_GAS_RES 29 + +/** Voltage, in volts **/ +#define SENSOR_CHAN_VOLTAGE 30 + +/** Current Shunt Voltage in milli-volts **/ +#define SENSOR_CHAN_VSHUNT 31 + +/** Current, in amps **/ +#define SENSOR_CHAN_CURRENT 32 +/** Power in watts **/ +#define SENSOR_CHAN_POWER 33 + +/** Resistance , in Ohm **/ +#define SENSOR_CHAN_RESISTANCE 34 + +/** Angular rotation, in degrees */ +#define SENSOR_CHAN_ROTATION 35 + +/** Position change on the X axis, in points. */ +#define SENSOR_CHAN_POS_DX 36 +/** Position change on the Y axis, in points. */ +#define SENSOR_CHAN_POS_DY 37 +/** Position change on the Z axis, in points. */ +#define SENSOR_CHAN_POS_DZ 38 + +/** Revolutions per minute, in RPM. */ +#define SENSOR_CHAN_RPM 39 + +/** Voltage, in volts **/ +#define SENSOR_CHAN_GAUGE_VOLTAGE 40 +/** Average current, in amps **/ +#define SENSOR_CHAN_GAUGE_AVG_CURRENT 41 +/** Standby current, in amps **/ +#define SENSOR_CHAN_GAUGE_STDBY_CURRENT 42 +/** Max load current, in amps **/ +#define SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT 43 +/** Gauge temperature **/ +#define SENSOR_CHAN_GAUGE_TEMP 44 +/** State of charge measurement in % **/ +#define SENSOR_CHAN_GAUGE_STATE_OF_CHARGE 45 +/** Full Charge Capacity in mAh **/ +#define SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY 46 +/** Remaining Charge Capacity in mAh **/ +#define SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY 47 +/** Nominal Available Capacity in mAh **/ +#define SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY 48 +/** Full Available Capacity in mAh **/ +#define SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY 49 +/** Average power in mW **/ +#define SENSOR_CHAN_GAUGE_AVG_POWER 50 +/** State of health measurement in % **/ +#define SENSOR_CHAN_GAUGE_STATE_OF_HEALTH 51 +/** Time to empty in minutes **/ +#define SENSOR_CHAN_GAUGE_TIME_TO_EMPTY 52 +/** Time to full in minutes **/ +#define SENSOR_CHAN_GAUGE_TIME_TO_FULL 53 +/** Cycle count (total number of charge/discharge cycles) **/ +#define SENSOR_CHAN_GAUGE_CYCLE_COUNT 54 +/** Design voltage of cell in V (max voltage)*/ +#define SENSOR_CHAN_GAUGE_DESIGN_VOLTAGE 55 +/** Desired voltage of cell in V (nominal voltage) */ +#define SENSOR_CHAN_GAUGE_DESIRED_VOLTAGE 56 +/** Desired charging current in mA */ +#define SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT 57 + +/** All channels. */ +#define SENSOR_CHAN_ALL 58 + +/** Number of all common sensor channels. */ +#define SENSOR_CHAN_COMMON_COUNT 59 + +/** + * This and higher values are sensor specific. + * Refer to the sensor header file. + */ +#define SENSOR_CHAN_PRIV_START SENSOR_CHAN_COMMON_COUNT + +#define SENSOR_CHAN_MAX INT16_MAX + +#endif diff --git a/tests/lib/devicetree/api/app.overlay b/tests/lib/devicetree/api/app.overlay index 585008a8837693..eee8ebdb644bb7 100644 --- a/tests/lib/devicetree/api/app.overlay +++ b/tests/lib/devicetree/api/app.overlay @@ -10,6 +10,8 @@ * (and be extended to test) real hardware. */ +#include + / { aliases { test-alias = &test_nodelabel; @@ -63,6 +65,9 @@ foo-names = "A", "b-c"; pwms = <&test_pwm1 8 200 3>, <&test_pwm2 5 100 1>; pwm-names = "red", "green"; + sensors = <&test_sensor1 SENSOR_CHAN_DIE_TEMP>, + <&test_sensor2 SENSOR_CHAN_AMBIENT_TEMP>; + sensor-names = "cpu", "ambient"; bar = <&test_gpio_1 200>, <&test_gpio_2 210>; baz-names = "john", "doe"; }; @@ -473,6 +478,20 @@ status = "okay"; }; + test_sensor1: sensor@66661111 { + compatible = "vnd,sensor-device"; + reg = <0x66661111 0x1000>; + #sensor-cells = <1>; + status = "okay"; + }; + + test_sensor2: sensor@66662222 { + compatible = "vnd,sensor-device"; + reg = <0x66662222 0x1000>; + #sensor-cells = <1>; + status = "okay"; + }; + test_transceiver0: can-phy0 { compatible = "vnd,can-transceiver"; status = "okay"; diff --git a/tests/lib/devicetree/api/src/main.c b/tests/lib/devicetree/api/src/main.c index 255357e85e852e..d718703f43a943 100644 --- a/tests/lib/devicetree/api/src/main.c +++ b/tests/lib/devicetree/api/src/main.c @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -78,6 +79,9 @@ #define TEST_PWM_CTLR_1 DT_NODELABEL(test_pwm1) #define TEST_PWM_CTLR_2 DT_NODELABEL(test_pwm2) +#define TEST_SENSOR_DEV_1 DT_NODELABEL(test_sensor1) +#define TEST_SENSOR_DEV_2 DT_NODELABEL(test_sensor2) + #define TEST_CAN_CTRL_0 DT_NODELABEL(test_can0) #define TEST_CAN_CTRL_1 DT_NODELABEL(test_can1) @@ -1311,6 +1315,31 @@ ZTEST(devicetree_api, test_pwms) zassert_equal(DT_INST_PWMS_FLAGS(0), 3, ""); } +ZTEST(devicetree_api, test_sensors) +{ + /* DT_SENSOR_DEV_BY_IDX */ + zassert_true(DT_SAME_NODE(DT_SENSOR_DEV_BY_IDX(TEST_PH, 0), TEST_SENSOR_DEV_1)); + zassert_true(DT_SAME_NODE(DT_SENSOR_DEV_BY_IDX(TEST_PH, 1), TEST_SENSOR_DEV_2)); + + /* DT_SENSOR_DEV */ + zassert_true(DT_SAME_NODE(DT_SENSOR_DEV(TEST_PH), TEST_SENSOR_DEV_1)); + + /* DT_SENSOR_DEV_BY_NAME */ + zassert_true(DT_SAME_NODE(DT_SENSOR_DEV_BY_NAME(TEST_PH, cpu), TEST_SENSOR_DEV_1)); + zassert_true(DT_SAME_NODE(DT_SENSOR_DEV_BY_NAME(TEST_PH, ambient), TEST_SENSOR_DEV_2)); + + /* DT_SENSOR_CHANNEL_BY_IDX */ + zassert_equal(DT_SENSOR_CHANNEL_BY_IDX(TEST_PH, 0), SENSOR_CHAN_DIE_TEMP); + zassert_equal(DT_SENSOR_CHANNEL_BY_IDX(TEST_PH, 1), SENSOR_CHAN_AMBIENT_TEMP); + + /* DT_SENSOR_CHANNEL */ + zassert_equal(DT_SENSOR_CHANNEL(TEST_PH), SENSOR_CHAN_DIE_TEMP); + + /* DT_SENSOR_CHANNEL_BY_NAME */ + zassert_equal(DT_SENSOR_CHANNEL_BY_NAME(TEST_PH, cpu), SENSOR_CHAN_DIE_TEMP); + zassert_equal(DT_SENSOR_CHANNEL_BY_NAME(TEST_PH, ambient), SENSOR_CHAN_AMBIENT_TEMP); +} + #undef DT_DRV_COMPAT #define DT_DRV_COMPAT vnd_can_controller ZTEST(devicetree_api, test_can)