Skip to content

Commit

Permalink
sensors: generate attributes/channels/triggers
Browse files Browse the repository at this point in the history
Add code generation for the sensor attribute, channel, and trigger
enums. Included in this is the ability to query the sensor's
information statically using the compatible string similar to how
devicetree does it.

Signed-off-by: Yuval Peress <[email protected]>
  • Loading branch information
yperess committed Dec 17, 2024
1 parent 4cec01f commit 6fc1215
Show file tree
Hide file tree
Showing 23 changed files with 1,222 additions and 316 deletions.
18 changes: 14 additions & 4 deletions doc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ endfunction()
#-------------------------------------------------------------------------------
# Doxygen (standalone)

set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_C_COMPILER> cr <TARGET> <OBJECTS>")
set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_C_COMPILER> s <TARGET>")
add_library(zephyr_interface INTERFACE)
include(${ZEPHYR_BASE}/drivers/sensor/codegen.cmake)
set_target_properties(zephyr_sensor.constants PROPERTIES LINKER_LANGUAGE C)

set(DOXY_OUT ${CMAKE_CURRENT_BINARY_DIR}/doxygen)
set(DOXYFILE_IN ${CMAKE_CURRENT_LIST_DIR}/zephyr.doxyfile.in)
set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/zephyr.doxyfile)
Expand All @@ -116,6 +122,8 @@ set_target_properties(
ADDITIONAL_CLEAN_FILES "${DOXY_OUT}"
)

add_dependencies(doxygen zephyr_sensor.constants.__generate_constants)

#-------------------------------------------------------------------------------
# devicetree

Expand Down Expand Up @@ -149,6 +157,8 @@ set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${GEN_DEVICETREE_
#-------------------------------------------------------------------------------
# html

set(SPHINXOPTS_EXTRA ${SPHINXOPTS_EXTRA} -D sensor_yaml_files="${sensor_yaml_files}")

add_doc_target(
html
COMMAND ${CMAKE_COMMAND} -E env ${SPHINX_ENV} OUTPUT_DIR=${DOCS_HTML_DIR}
Expand All @@ -172,7 +182,7 @@ set_target_properties(
ADDITIONAL_CLEAN_FILES "${DOCS_SRC_DIR};${DOCS_HTML_DIR};${DOCS_DOCTREE_DIR}"
)

add_dependencies(html devicetree)
add_dependencies(html devicetree zephyr_sensor.constants.__generate_constants)

#-------------------------------------------------------------------------------
# html-live
Expand Down Expand Up @@ -202,7 +212,7 @@ set_target_properties(
ADDITIONAL_CLEAN_FILES "${DOCS_SRC_DIR};${DOCS_HTML_DIR};${DOCS_DOCTREE_DIR}"
)

add_dependencies(html-live devicetree)
add_dependencies(html-live devicetree zephyr_sensor.constants.__generate_constants)
#-------------------------------------------------------------------------------
# pdf

Expand Down Expand Up @@ -230,7 +240,7 @@ set_target_properties(
ADDITIONAL_CLEAN_FILES "${DOCS_SRC_DIR};${DOCS_LATEX_DIR};${DOCS_DOCTREE_DIR}"
)

add_dependencies(latex devicetree)
add_dependencies(latex devicetree zephyr_sensor.constants.__generate_constants)

if(LATEX_PDFLATEX_FOUND AND LATEXMK)
if(WIN32)
Expand All @@ -252,7 +262,7 @@ if(LATEX_PDFLATEX_FOUND AND LATEXMK)
USES_TERMINAL
)

add_dependencies(pdf latex)
add_dependencies(pdf latex zephyr_sensor.constants.__generate_constants)
endif()

#-------------------------------------------------------------------------------
Expand Down
6 changes: 5 additions & 1 deletion doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,11 @@
doxyrunner_doxyfile = ZEPHYR_BASE / "doc" / "zephyr.doxyfile.in"
doxyrunner_outdir = ZEPHYR_BUILD / "doxygen"
doxyrunner_fmt = True
doxyrunner_fmt_vars = {"ZEPHYR_BASE": str(ZEPHYR_BASE), "ZEPHYR_VERSION": version}
doxyrunner_fmt_vars = {
"ZEPHYR_BASE": str(ZEPHYR_BASE),
"CMAKE_BINARY_DIR": str(ZEPHYR_BUILD.parent),
"ZEPHYR_VERSION": version,
}
doxyrunner_outdir_var = "DOXY_OUT"

# -- Options for zephyr.doxybridge plugin ---------------------------------
Expand Down
67 changes: 67 additions & 0 deletions doc/hardware/peripherals/sensor/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,77 @@ Implementing Read and Decode
* MUST implement :c:type:`sensor_get_decoder_t` returning the
:c:struct:`sensor_decoder_api` for that device type.

Adding your ``sensor.yaml``
===========================

Sensor YAML files can be added to enhance your driver writing experience. Each
sensor can introduce a ``sensor.yaml`` file which follows the schema described
in `pw_sensor`_. In tree, the file will automatically be picked up by the build
system and entries will be created for your driver. See the example at
``tests/drivers/sensor/generator/`` for the macro usage, you can do things
like:

* Get the number of attributes, channels, and triggers supported by a specific
compatible string.
* Get the number of instances of a specific channel of a sensor.
* Check if a driver supports setting a specific attribute/channel pair.
* Automatically index your drivers into the Zephyr documentation

The primary use case for these is to verify that a DT entry's compatible value
supports specific requirements. For example:

* Assume we're building a lid angle calculation which requires 2
accelerometers. These accelerometers will be specified in the devicetree
using the chosen nodes so we can access them via ``DT_CHOSEN(lid_accel)``
and ``DT_CHOSEN(base_accel)``.
* We can now run a static assert like
``BUILD_ASSERT(SENSOR_SPEC_CHAN_INST_COUNT(DT_PROP(DT_CHOSEN(lid_accel), compatible), accel_xyz) > 0);``

Additional features are in development and will allow drivers to:

* Generate boilerplate code for the sensor API such as attribute set/get,
submit, etc.
* Generate common config/data struct definitions.
* Abstract the bus API so you can read/write registers without worrying about
i2c/spi/etc.
* Optimize memory allocation based to YAML metadata. Using the static data
available in the ``sensor.yaml`` file, we will be able to allocate the right
size buffer for streaming and one-shot reading APIs as well as client side
buffers.

Adding sensors out of tree
--------------------------

Zephyr supports adding sensors from modules. There are 3 CMake variables that
should be updated to make that happen:

* ``ZEPHYR_EXTRA_SENSOR_YAML_FILES``: this is a cmake list containing full
paths to sensor YAML files that are not in the Zephyr tree.
* ``ZEPHYR_EXTRA_SENSOR_INCLUDE_PATHS``: this is a cmake list containing full
paths to directories which contains custom attributes, channels, triggers, or
units. These paths are directories which the ``zephyr_sensor_library`` cmake
function will use to find definition files which are included in your sensor
YAML file. It's similar to header include paths.
* ``ZEPHYR_EXTRA_SENSOR_DEFINITION_FILES``: this is a cmake list containing
full paths to files containing custom attributes, channels, triggers, or
units. The file list is used to determine when the sensor library needs to be
rebuilt.

Why ``sensor.yaml`` files?
--------------------------

* We already use YAML files to describe boards.
* They allow us to add metadata per driver type. See below for a comparison to
devicetree.
* They're portable. Downstream users may implement additional generators to do
new things.

.. _sensor-api-reference:

API Reference
***************

.. doxygengroup:: sensor_interface
.. doxygengroup:: sensor_emulator_backend

.. _`pw_sensor`: https://pigweed.dev/pw_sensor/py/
1 change: 1 addition & 0 deletions doc/zephyr.doxyfile.in
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,7 @@ WARN_LOGFILE =

INPUT = @ZEPHYR_BASE@/doc/_doxygen/mainpage.md \
@ZEPHYR_BASE@/doc/_doxygen/groups.dox \
@CMAKE_BINARY_DIR@/zephyr_sensor.constants/ \
@ZEPHYR_BASE@/kernel/include/kernel_arch_interface.h \
@ZEPHYR_BASE@/include/zephyr/arch/cache.h \
@ZEPHYR_BASE@/include/zephyr/sys/atomic.h \
Expand Down
2 changes: 2 additions & 0 deletions drivers/sensor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ add_subdirectory_ifdef(CONFIG_VEAA_X_3 veaa_x_3)
add_subdirectory_ifdef(CONFIG_VOLTAGE_DIVIDER voltage_divider)
add_subdirectory_ifdef(CONFIG_TACH_ENE_KB1200 ene_tach_kb1200)

include(codegen.cmake)

zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/sensor.h)

zephyr_library()
Expand Down
24 changes: 24 additions & 0 deletions drivers/sensor/asahi_kasei/akm09918c/sensor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright (c) 2024 Google Inc
# SPDX-License-Identifier: BDS-3-Clause

deps:
- "drivers/sensor/attributes.yaml"
- "drivers/sensor/channels.yaml"
- "drivers/sensor/triggers.yaml"
- "drivers/sensor/units.yaml"
compatible:
org: "asahi-kasei"
part: "akm09918c"
supported-buses:
- i2c
channels:
magn_xyz: []
magn_x: []
magn_y: []
magn_z: []
attributes:
- attribute: "sampling_frequency"
channel: "magn_xyz"
units: "frequency"
extras:
doc-link: "asahi_kasei_akm09918c_driver"
68 changes: 68 additions & 0 deletions drivers/sensor/attributes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright (c) 2024 Google Inc
# SPDX-License-Identifier: BDS-3-Clause

attributes:
sampling_frequency:
name: "sampling rate"
description: >
Sensor sampling frequency, i.e. how many times a second the sensor takes a measurement.
lower_thresh:
name: "lower threshold"
description: "Lower threshold for trigger."
upper_thresh:
name: "upper threshold"
description: "Upper threshold for trigger."
slope_th:
name: "any motion threshold"
description: "Threshold for any-motion (slope) trigger."
slope_dur:
name: "slope value threshold duration"
description: >
Duration for which the slope values needs to be outside the threshold for the trigger to
fire.
hysteresis:
name: "hysteresis"
description: "Hysteresis for trigger thresholds."
oversampling:
name: "oversampling factor"
description: "Oversampling factor"
full_scale:
name: "range"
description: "Sensor range, in SI units."
offset:
name: "value offset"
description: >
The sensor value returned will be altered by the amount indicated by offset: final_value =
sensor_value + offset.
calib_target:
name: "calibration target"
description: >
Calibration target. This will be used by the internal chip's algorithms to calibrate itself
on a certain axis, or all of them.
configuration:
name: "operating mode"
description: "Configure the operating modes of a sensor."
calibration:
name: "calibration value"
description: "Set a calibration value needed by a sensor."
feature_mask:
name: "enabled/disabled feature"
description: "Enable/disable sensor features"
alert:
name: "alert threshold"
description: "Alert threshold or alert enable/disable"
ff_dur:
name: "free-fall duration"
description: >
Free-fall duration represented in milliseconds. If the sampling frequency is changed during
runtime, this attribute should be set to adjust freefall duration to the new sampling
frequency.
batch_duration:
name: "batch duration"
description: "Hardware batch duration in ticks"
gain:
name: "gain"
description: "Configure the gain of a sensor."
resolution:
name: "resolution"
description: "Configure the resolution of a sensor."
34 changes: 34 additions & 0 deletions drivers/sensor/bosch/bma4xx/sensor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (c) 2024 Google Inc
# SPDX-License-Identifier: BDS-3-Clause

deps:
- "drivers/sensor/attributes.yaml"
- "drivers/sensor/channels.yaml"
- "drivers/sensor/triggers.yaml"
- "drivers/sensor/units.yaml"
compatible:
org: "bosch"
part: "bma4xx"
supported-buses:
- i2c
- spi
description: |
Sensor driver implementation for bma422 and bma423.
channels:
accel_x: []
accel_y: []
accel_z: []
accel_xyz: []
die_temp: []
attributes:
- attribute: "sampling_frequency"
channel: "accel_xyz"
units: "frequency"
- attribute: "full_scale"
channel: "accel_xyz"
units: "acceleration"
- attribute: "offset"
channel: "accel_xyz"
units: "acceleration"
extras:
doc-link: "bosch_bma4xx_driver"
50 changes: 50 additions & 0 deletions drivers/sensor/bosch/bmi160/sensor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copyright (c) 2024 Google Inc
# SPDX-License-Identifier: BDS-3-Clause

deps:
- "drivers/sensor/attributes.yaml"
- "drivers/sensor/channels.yaml"
- "drivers/sensor/triggers.yaml"
- "drivers/sensor/units.yaml"
compatible:
org: "bosch"
part: "bmi160"
supported-buses:
- i2c
- spi
description: |
Sensor driver implementation for bmi160.
channels:
accel_x: []
accel_y: []
accel_z: []
accel_xyz: []
gyro_x: []
gyro_y: []
gyro_z: []
gyro_xyz: []
die_temp: []
attributes:
- attribute: "sampling_frequency"
channel: "accel_xyz"
units: "frequency"
- attribute: "sampling_frequency"
channel: "gyro_xyz"
units: "frequency"
- attribute: "full_scale"
channel: "accel_xyz"
units: "acceleration"
- attribute: "full_scale"
channel: "gyro_xyz"
units: "angular_velocity"
- attribute: "offset"
channel: "accel_xyz"
units: "acceleration"
- attribute: "offset"
channel: "gyro_xyz"
units: "angular_velocity"
triggers:
- data_ready
- delta
extras:
doc-link: "bosch_bmi160_driver"
Loading

0 comments on commit 6fc1215

Please sign in to comment.