Browse Source

drivers: sensor: Add sensor clock API support

This commit introduces a new Sensor Clock API, enabling the retrieval
of cycle counts and conversion to nanoseconds based on the system or
external clock. The API includes:

- `sensor_clock_get_cycles()` to get the current cycle count from the
  sensor clock.
- `sensor_clock_cycles_to_ns()` to convert cycles to nanoseconds using
  the clock's frequency.

The implementation supports both system clocks and external clocks
defined in the device tree, making the sensor clock integration more
flexible for various sensor use cases.

Signed-off-by: Mark Chen <mark.chen@cienet.com>
pull/84050/head
Mark Chen 9 months ago committed by Benjamin Cabé
parent
commit
f4da9b9705
  1. 27
      doc/releases/release-notes-4.1.rst
  2. 12
      drivers/sensor/CMakeLists.txt
  3. 2
      drivers/sensor/Kconfig
  4. 30
      drivers/sensor/Kconfig.sensor_clock
  5. 14
      drivers/sensor/adi/adxl345/adxl345_stream.c
  6. 14
      drivers/sensor/adi/adxl362/adxl362_stream.c
  7. 14
      drivers/sensor/adi/adxl367/adxl367_stream.c
  8. 13
      drivers/sensor/adi/adxl372/adxl372_stream.c
  9. 11
      drivers/sensor/asahi_kasei/akm09918c/akm09918c_async.c
  10. 11
      drivers/sensor/bosch/bma4xx/bma4xx.c
  11. 11
      drivers/sensor/bosch/bme280/bme280_async.c
  12. 15
      drivers/sensor/default_rtio_sensor.c
  13. 11
      drivers/sensor/memsic/mmc56x3/mmc56x3_async.c
  14. 63
      drivers/sensor/sensor_clock_external.c
  15. 29
      drivers/sensor/sensor_clock_sys.c
  16. 11
      drivers/sensor/st/lsm6dsv16x/lsm6dsv16x_rtio.c
  17. 12
      drivers/sensor/st/lsm6dsv16x/lsm6dsv16x_rtio_stream.c
  18. 11
      drivers/sensor/tdk/icm42688/icm42688_decoder.c
  19. 7
      drivers/sensor/tdk/icm42688/icm42688_rtio.c
  20. 13
      drivers/sensor/tdk/icm42688/icm42688_rtio_stream.c
  21. 45
      include/zephyr/drivers/sensor_clock.h
  22. 12
      samples/sensor/clock/CMakeLists.txt
  23. 53
      samples/sensor/clock/README.rst
  24. 13
      samples/sensor/clock/boards/nrf52833dk_nrf52833.overlay
  25. 13
      samples/sensor/clock/boards/nrf52840dk_nrf52840.overlay
  26. 11
      samples/sensor/clock/boards/nrf528xx_counter.overlay
  27. 11
      samples/sensor/clock/boards/nrf528xx_rtc.overlay
  28. 14
      samples/sensor/clock/prj.conf
  29. 38
      samples/sensor/clock/sample.yaml
  30. 36
      samples/sensor/clock/src/main.c
  31. 3
      tests/drivers/sensor/icm42688/prj.conf

27
doc/releases/release-notes-4.1.rst

@ -242,6 +242,33 @@ Drivers and Sensors @@ -242,6 +242,33 @@ Drivers and Sensors
* Sensors
* Sensor Clock
* The asynchronous sensor API now supports external clock sources. To use an external clock source
with the asynchronous sensor API, the following configurations are required:
* Enable one of the Kconfig options:
:kconfig:option:`CONFIG_SENSOR_CLOCK_COUNTER`,
:kconfig:option:`CONFIG_SENSOR_CLOCK_RTC`, or
:kconfig:option:`CONFIG_SENSOR_CLOCK_SYSTEM`.
* If not using the system clock, define the ``zephyr,sensor-clock`` property in the device tree to specify
the external clock source.
A typical configuration in the device tree structure is as follows:
.. code-block:: devicetree
/ {
chosen {
zephyr,sensor-clock = &timer0;
};
};
&timer0 {
status = "okay";
};
* Serial
* SPI

12
drivers/sensor/CMakeLists.txt

@ -74,3 +74,15 @@ zephyr_library_sources_ifdef(CONFIG_SENSOR_SHELL sensor_shell.c) @@ -74,3 +74,15 @@ zephyr_library_sources_ifdef(CONFIG_SENSOR_SHELL sensor_shell.c)
zephyr_library_sources_ifdef(CONFIG_SENSOR_SHELL_STREAM sensor_shell_stream.c)
zephyr_library_sources_ifdef(CONFIG_SENSOR_SHELL_BATTERY shell_battery.c)
zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API sensor_decoders_init.c default_rtio_sensor.c)
dt_has_chosen(has_zephyr_sensor_clock PROPERTY "zephyr,sensor-clock")
if(CONFIG_SENSOR_CLOCK_RTC OR CONFIG_SENSOR_CLOCK_COUNTER)
if(has_zephyr_sensor_clock)
zephyr_library_sources(sensor_clock_external.c)
else()
message(FATAL_ERROR "Sensor clock type (RTC or Counter) is selected, but no zephyr,sensor-clock is defined in the device tree.")
endif()
elseif(CONFIG_SENSOR_CLOCK_SYSTEM)
zephyr_library_sources(sensor_clock_sys.c)
endif()

2
drivers/sensor/Kconfig

@ -82,6 +82,8 @@ config SENSOR_SHELL_MAX_TRIGGER_DEVICES @@ -82,6 +82,8 @@ config SENSOR_SHELL_MAX_TRIGGER_DEVICES
config SENSOR_INFO
bool "Sensor Info iterable section"
source "drivers/sensor/Kconfig.sensor_clock"
comment "Device Drivers"
# zephyr-keep-sorted-start

30
drivers/sensor/Kconfig.sensor_clock

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
# Sensor clock configuration options
# Copyright(c) 2024 Cienet
# SPDX-License-Identifier: Apache-2.0
config SENSOR_CLOCK
bool
default y if SENSOR_ASYNC_API
help
Configure the sensor clock source for the system.
if SENSOR_CLOCK
choice
prompt "Sensor clock type"
default SENSOR_CLOCK_SYSTEM
help
Select the clock source to be used for sensor timing.
config SENSOR_CLOCK_SYSTEM
bool "Use the system counter for sensor time"
config SENSOR_CLOCK_COUNTER
bool "Use a counter device/API for sensor time"
config SENSOR_CLOCK_RTC
bool "Use an RTC device/API for sensor time"
endchoice
endif # SENSOR_CLOCK

14
drivers/sensor/adi/adxl345/adxl345_stream.c

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
#include <zephyr/logging/log.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/sensor_clock.h>
#include "adxl345.h"
LOG_MODULE_DECLARE(ADXL345, CONFIG_SENSOR_LOG_LEVEL);
@ -358,11 +358,21 @@ void adxl345_stream_irq_handler(const struct device *dev) @@ -358,11 +358,21 @@ void adxl345_stream_irq_handler(const struct device *dev)
{
struct adxl345_dev_data *data = (struct adxl345_dev_data *) dev->data;
const struct adxl345_dev_config *cfg = (const struct adxl345_dev_config *) dev->config;
uint64_t cycles;
int rc;
if (data->sqe == NULL) {
return;
}
data->timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
rc = sensor_clock_get_cycles(&cycles);
if (rc != 0) {
LOG_ERR("Failed to get sensor clock cycles");
rtio_iodev_sqe_err(data->sqe, rc);
return;
}
data->timestamp = sensor_clock_cycles_to_ns(cycles);
struct rtio_sqe *write_status_addr = rtio_sqe_acquire(data->rtio_ctx);
struct rtio_sqe *read_status_reg = rtio_sqe_acquire(data->rtio_ctx);
struct rtio_sqe *check_status_reg = rtio_sqe_acquire(data->rtio_ctx);

14
drivers/sensor/adi/adxl362/adxl362_stream.c

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
#include <zephyr/logging/log.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/sensor_clock.h>
#include "adxl362.h"
LOG_MODULE_DECLARE(ADXL362, CONFIG_SENSOR_LOG_LEVEL);
@ -384,12 +384,20 @@ static void adxl362_process_status_cb(struct rtio *r, const struct rtio_sqe *sqr @@ -384,12 +384,20 @@ static void adxl362_process_status_cb(struct rtio *r, const struct rtio_sqe *sqr
void adxl362_stream_irq_handler(const struct device *dev)
{
struct adxl362_data *data = (struct adxl362_data *) dev->data;
uint64_t cycles;
int rc;
if (data->sqe == NULL) {
return;
}
data->timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
rc = sensor_clock_get_cycles(&cycles);
if (rc != 0) {
LOG_ERR("Failed to get sensor clock cycles");
rtio_iodev_sqe_err(data->sqe, rc);
return;
}
data->timestamp = sensor_clock_cycles_to_ns(cycles);
struct rtio_sqe *write_status_addr = rtio_sqe_acquire(data->rtio_ctx);
struct rtio_sqe *read_status_reg = rtio_sqe_acquire(data->rtio_ctx);

14
drivers/sensor/adi/adxl367/adxl367_stream.c

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
#include <zephyr/logging/log.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/sensor_clock.h>
#include "adxl367.h"
LOG_MODULE_DECLARE(ADXL362, CONFIG_SENSOR_LOG_LEVEL);
@ -537,12 +537,20 @@ static void adxl367_process_status_cb(struct rtio *r, const struct rtio_sqe *sqr @@ -537,12 +537,20 @@ static void adxl367_process_status_cb(struct rtio *r, const struct rtio_sqe *sqr
void adxl367_stream_irq_handler(const struct device *dev)
{
struct adxl367_data *data = (struct adxl367_data *) dev->data;
uint64_t cycles;
int rc;
if (data->sqe == NULL) {
return;
}
data->timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
rc = sensor_clock_get_cycles(&cycles);
if (rc != 0) {
LOG_ERR("Failed to get sensor clock cycles");
rtio_iodev_sqe_err(data->sqe, rc);
return;
}
data->timestamp = sensor_clock_cycles_to_ns(cycles);
struct rtio_sqe *write_status_addr = rtio_sqe_acquire(data->rtio_ctx);
struct rtio_sqe *read_status_reg = rtio_sqe_acquire(data->rtio_ctx);

13
drivers/sensor/adi/adxl372/adxl372_stream.c

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
#include <zephyr/logging/log.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/sensor_clock.h>
#include "adxl372.h"
@ -424,12 +425,20 @@ static void adxl372_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq @@ -424,12 +425,20 @@ static void adxl372_process_status1_cb(struct rtio *r, const struct rtio_sqe *sq
void adxl372_stream_irq_handler(const struct device *dev)
{
struct adxl372_data *data = (struct adxl372_data *)dev->data;
uint64_t cycles;
int rc;
if (data->sqe == NULL) {
return;
}
data->timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
rc = sensor_clock_get_cycles(&cycles);
if (rc != 0) {
LOG_ERR("Failed to get sensor clock cycles");
rtio_iodev_sqe_err(data->sqe, rc);
return;
}
data->timestamp = sensor_clock_cycles_to_ns(cycles);
struct rtio_sqe *write_status_addr = rtio_sqe_acquire(data->rtio_ctx);
struct rtio_sqe *read_status_reg = rtio_sqe_acquire(data->rtio_ctx);

11
drivers/sensor/asahi_kasei/akm09918c/akm09918c_async.c

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
#include <zephyr/logging/log.h>
#include <zephyr/rtio/work.h>
#include <zephyr/drivers/sensor_clock.h>
#include "akm09918c.h"
@ -20,6 +21,7 @@ void akm09918c_submit_sync(struct rtio_iodev_sqe *iodev_sqe) @@ -20,6 +21,7 @@ void akm09918c_submit_sync(struct rtio_iodev_sqe *iodev_sqe)
struct akm09918c_data *data = dev->data;
const struct sensor_chan_spec *const channels = cfg->channels;
const size_t num_channels = cfg->count;
uint64_t cycles;
int rc;
/* Check if the requested channels are supported */
@ -46,8 +48,15 @@ void akm09918c_submit_sync(struct rtio_iodev_sqe *iodev_sqe) @@ -46,8 +48,15 @@ void akm09918c_submit_sync(struct rtio_iodev_sqe *iodev_sqe)
return;
}
rc = sensor_clock_get_cycles(&cycles);
if (rc != 0) {
LOG_ERR("Failed to get sensor clock cycles");
rtio_iodev_sqe_err(iodev_sqe, rc);
return;
}
/* save information for the work item */
data->work_ctx.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
data->work_ctx.timestamp = sensor_clock_cycles_to_ns(cycles);
data->work_ctx.iodev_sqe = iodev_sqe;
rc = k_work_schedule(&data->work_ctx.async_fetch_work, K_USEC(AKM09918C_MEASURE_TIME_US));

11
drivers/sensor/bosch/bma4xx/bma4xx.c

@ -14,6 +14,7 @@ @@ -14,6 +14,7 @@
#include <zephyr/logging/log.h>
#include <zephyr/pm/device.h>
#include <zephyr/rtio/work.h>
#include <zephyr/drivers/sensor_clock.h>
LOG_MODULE_REGISTER(bma4xx, CONFIG_SENSOR_LOG_LEVEL);
#include "bma4xx.h"
@ -352,6 +353,7 @@ static void bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_s @@ -352,6 +353,7 @@ static void bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_s
struct bma4xx_encoded_data *edata;
uint8_t *buf;
uint32_t buf_len;
uint64_t cycles;
int rc;
/* Get the buffer for the frame, it may be allocated dynamically by the rtio context */
@ -362,11 +364,18 @@ static void bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_s @@ -362,11 +364,18 @@ static void bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_s
return;
}
rc = sensor_clock_get_cycles(&cycles);
if (rc != 0) {
LOG_ERR("Failed to get sensor clock cycles");
rtio_iodev_sqe_err(iodev_sqe, rc);
return;
}
/* Prepare response */
edata = (struct bma4xx_encoded_data *)buf;
edata->header.is_fifo = false;
edata->header.accel_fs = bma4xx->accel_fs_range;
edata->header.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
edata->header.timestamp = sensor_clock_cycles_to_ns(cycles);
edata->has_accel = 0;
edata->has_temp = 0;

11
drivers/sensor/bosch/bme280/bme280_async.c

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
#include <zephyr/rtio/work.h>
#include <zephyr/logging/log.h>
#include <zephyr/drivers/sensor_clock.h>
#include "bme280.h"
@ -16,6 +17,7 @@ void bme280_submit_sync(struct rtio_iodev_sqe *iodev_sqe) @@ -16,6 +17,7 @@ void bme280_submit_sync(struct rtio_iodev_sqe *iodev_sqe)
{
uint32_t min_buf_len = sizeof(struct bme280_encoded_data);
int rc;
uint64_t cycles;
uint8_t *buf;
uint32_t buf_len;
@ -31,10 +33,17 @@ void bme280_submit_sync(struct rtio_iodev_sqe *iodev_sqe) @@ -31,10 +33,17 @@ void bme280_submit_sync(struct rtio_iodev_sqe *iodev_sqe)
return;
}
rc = sensor_clock_get_cycles(&cycles);
if (rc != 0) {
LOG_ERR("Failed to get sensor clock cycles");
rtio_iodev_sqe_err(iodev_sqe, rc);
return;
}
struct bme280_encoded_data *edata;
edata = (struct bme280_encoded_data *)buf;
edata->header.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
edata->header.timestamp = sensor_clock_cycles_to_ns(cycles);
edata->has_temp = 0;
edata->has_humidity = 0;
edata->has_press = 0;

15
drivers/sensor/default_rtio_sensor.c

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
#include <errno.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/sensor_clock.h>
#include <zephyr/dsp/types.h>
#include <zephyr/logging/log.h>
#include <zephyr/rtio/work.h>
@ -119,11 +120,21 @@ static void sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe) @@ -119,11 +120,21 @@ static void sensor_submit_fallback_sync(struct rtio_iodev_sqe *iodev_sqe)
const struct sensor_chan_spec *const channels = cfg->channels;
const int num_output_samples = compute_num_samples(channels, cfg->count);
uint32_t min_buf_len = compute_min_buf_len(num_output_samples);
uint64_t timestamp_ns = k_ticks_to_ns_floor64(k_uptime_ticks());
int rc = sensor_sample_fetch(dev);
uint64_t cycles;
int rc;
rc = sensor_clock_get_cycles(&cycles);
if (rc != 0) {
LOG_ERR("Failed to get sensor clock cycles");
rtio_iodev_sqe_err(iodev_sqe, rc);
return;
}
uint64_t timestamp_ns = sensor_clock_cycles_to_ns(cycles);
uint8_t *buf;
uint32_t buf_len;
rc = sensor_sample_fetch(dev);
/* Check that the fetch succeeded */
if (rc != 0) {
LOG_WRN("Failed to fetch samples");

11
drivers/sensor/memsic/mmc56x3/mmc56x3_async.c

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
#include <zephyr/logging/log.h>
#include <zephyr/rtio/work.h>
#include <zephyr/drivers/sensor_clock.h>
#include "mmc56x3.h"
@ -16,6 +17,7 @@ void mmc56x3_submit_sync(struct rtio_iodev_sqe *iodev_sqe) @@ -16,6 +17,7 @@ void mmc56x3_submit_sync(struct rtio_iodev_sqe *iodev_sqe)
int rc;
uint8_t *buf;
uint32_t buf_len;
uint64_t cycles;
const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data;
const struct device *dev = cfg->sensor;
@ -29,10 +31,17 @@ void mmc56x3_submit_sync(struct rtio_iodev_sqe *iodev_sqe) @@ -29,10 +31,17 @@ void mmc56x3_submit_sync(struct rtio_iodev_sqe *iodev_sqe)
return;
}
rc = sensor_clock_get_cycles(&cycles);
if (rc != 0) {
LOG_ERR("Failed to get sensor clock cycles");
rtio_iodev_sqe_err(iodev_sqe, rc);
return;
}
struct mmc56x3_encoded_data *edata;
edata = (struct mmc56x3_encoded_data *)buf;
edata->header.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
edata->header.timestamp = sensor_clock_cycles_to_ns(cycles);
edata->has_temp = 0;
edata->has_magn_x = 0;
edata->has_magn_y = 0;

63
drivers/sensor/sensor_clock_external.c

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
/*
* Copyright (c) 2024 Cienet
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/device.h>
#include <zephyr/sys/util.h>
#include <zephyr/sys_clock.h>
#include <zephyr/drivers/counter.h>
#include <zephyr/logging/log.h>
#include <zephyr/init.h>
LOG_MODULE_REGISTER(sensor_clock, CONFIG_SENSOR_LOG_LEVEL);
static const struct device *external_sensor_clock = DEVICE_DT_GET(DT_CHOSEN(zephyr_sensor_clock));
static uint32_t freq;
static int external_sensor_clock_init(void)
{
int rc;
rc = counter_start(external_sensor_clock);
if (rc != 0) {
LOG_ERR("Failed to start sensor clock counter: %d\n", rc);
return rc;
}
freq = counter_get_frequency(external_sensor_clock);
if (freq == 0) {
LOG_ERR("Sensor clock %s has no fixed frequency\n", external_sensor_clock->name);
return -EINVAL;
}
return 0;
}
int sensor_clock_get_cycles(uint64_t *cycles)
{
__ASSERT_NO_MSG(counter_is_counting_up(external_sensor_clock));
int rc;
const struct counter_driver_api *api =
(const struct counter_driver_api *)external_sensor_clock->api;
if (api->get_value_64) {
rc = counter_get_value_64(external_sensor_clock, cycles);
} else {
uint32_t result_32;
rc = counter_get_value(external_sensor_clock, &result_32);
*cycles = (uint64_t)result_32;
}
return rc;
}
uint64_t sensor_clock_cycles_to_ns(uint64_t cycles)
{
return (cycles * NSEC_PER_SEC) / freq;
}
SYS_INIT(external_sensor_clock_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);

29
drivers/sensor/sensor_clock_sys.c

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
/*
* Copyright (c) 2024 Cienet
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/drivers/sensor_clock.h>
#include <zephyr/sys_clock.h>
int sensor_clock_get_cycles(uint64_t *cycles)
{
if (cycles == NULL) {
return -EINVAL;
}
#ifdef CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER
*cycles = k_cycle_get_64();
#else
*cycles = (uint64_t)k_cycle_get_32();
#endif
return 0;
}
uint64_t sensor_clock_cycles_to_ns(uint64_t cycles)
{
return (cycles * NSEC_PER_SEC) / sys_clock_hw_cycles_per_sec();
}

11
drivers/sensor/st/lsm6dsv16x/lsm6dsv16x_rtio.c

@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
#include "lsm6dsv16x_rtio.h"
#include "lsm6dsv16x_decoder.h"
#include <zephyr/rtio/work.h>
#include <zephyr/drivers/sensor_clock.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(LSM6DSV16X_RTIO, CONFIG_SENSOR_LOG_LEVEL);
@ -21,6 +22,7 @@ static void lsm6dsv16x_submit_sample(const struct device *dev, struct rtio_iodev @@ -21,6 +22,7 @@ static void lsm6dsv16x_submit_sample(const struct device *dev, struct rtio_iodev
const struct sensor_chan_spec *const channels = cfg->channels;
const size_t num_channels = cfg->count;
uint32_t min_buf_len = sizeof(struct lsm6dsv16x_rtio_data);
uint64_t cycles;
int rc = 0;
uint8_t *buf;
uint32_t buf_len;
@ -112,10 +114,17 @@ static void lsm6dsv16x_submit_sample(const struct device *dev, struct rtio_iodev @@ -112,10 +114,17 @@ static void lsm6dsv16x_submit_sample(const struct device *dev, struct rtio_iodev
}
}
rc = sensor_clock_get_cycles(&cycles);
if (rc != 0) {
LOG_ERR("Failed to get sensor clock cycles");
rtio_iodev_sqe_err(iodev_sqe, rc);
goto err;
}
edata->header.is_fifo = false;
edata->header.accel_fs = data->accel_fs;
edata->header.gyro_fs = data->gyro_fs;
edata->header.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
edata->header.timestamp = sensor_clock_cycles_to_ns(cycles);
rtio_iodev_sqe_ok(iodev_sqe, 0);

12
drivers/sensor/st/lsm6dsv16x/lsm6dsv16x_rtio_stream.c

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
#include "lsm6dsv16x.h"
#include "lsm6dsv16x_decoder.h"
#include <zephyr/rtio/work.h>
#include <zephyr/drivers/sensor_clock.h>
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(LSM6DSV16X_RTIO);
@ -377,13 +378,22 @@ void lsm6dsv16x_stream_irq_handler(const struct device *dev) @@ -377,13 +378,22 @@ void lsm6dsv16x_stream_irq_handler(const struct device *dev)
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
const struct lsm6dsv16x_config *config = dev->config;
#endif
uint64_t cycles;
int rc;
if (lsm6dsv16x->streaming_sqe == NULL) {
return;
}
rc = sensor_clock_get_cycles(&cycles);
if (rc != 0) {
LOG_ERR("Failed to get sensor clock cycles");
rtio_iodev_sqe_err(lsm6dsv16x->streaming_sqe, rc);
return;
}
/* get timestamp as soon as the irq is served */
lsm6dsv16x->fifo_timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
lsm6dsv16x->fifo_timestamp = sensor_clock_cycles_to_ns(cycles);
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
if (ON_I3C_BUS(config) && (!I3C_INT_PIN(config))) {

11
drivers/sensor/tdk/icm42688/icm42688_decoder.c

@ -10,6 +10,8 @@ @@ -10,6 +10,8 @@
#include <errno.h>
#include <zephyr/logging/log.h>
#include <zephyr/drivers/sensor_clock.h>
LOG_MODULE_REGISTER(ICM42688_DECODER, CONFIG_SENSOR_LOG_LEVEL);
#define DT_DRV_COMPAT invensense_icm42688
@ -183,6 +185,8 @@ int icm42688_encode(const struct device *dev, const struct sensor_chan_spec *con @@ -183,6 +185,8 @@ int icm42688_encode(const struct device *dev, const struct sensor_chan_spec *con
{
struct icm42688_dev_data *data = dev->data;
struct icm42688_encoded_data *edata = (struct icm42688_encoded_data *)buf;
uint64_t cycles;
int rc;
edata->channels = 0;
@ -190,10 +194,15 @@ int icm42688_encode(const struct device *dev, const struct sensor_chan_spec *con @@ -190,10 +194,15 @@ int icm42688_encode(const struct device *dev, const struct sensor_chan_spec *con
edata->channels |= icm42688_encode_channel(channels[i].chan_type);
}
rc = sensor_clock_get_cycles(&cycles);
if (rc != 0) {
return rc;
}
edata->header.is_fifo = false;
edata->header.accel_fs = data->cfg.accel_fs;
edata->header.gyro_fs = data->cfg.gyro_fs;
edata->header.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
edata->header.timestamp = sensor_clock_cycles_to_ns(cycles);
return 0;
}

7
drivers/sensor/tdk/icm42688/icm42688_rtio.c

@ -66,7 +66,12 @@ static void icm42688_submit_one_shot(const struct device *dev, struct rtio_iodev @@ -66,7 +66,12 @@ static void icm42688_submit_one_shot(const struct device *dev, struct rtio_iodev
edata = (struct icm42688_encoded_data *)buf;
icm42688_encode(dev, channels, num_channels, buf);
rc = icm42688_encode(dev, channels, num_channels, buf);
if (rc != 0) {
LOG_ERR("Failed to encode sensor data");
rtio_iodev_sqe_err(iodev_sqe, rc);
return;
}
rc = icm42688_rtio_sample_fetch(dev, edata->readings);
/* Check that the fetch succeeded */

13
drivers/sensor/tdk/icm42688/icm42688_rtio_stream.c

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
*/
#include <zephyr/logging/log.h>
#include <zephyr/drivers/sensor_clock.h>
#include "icm42688.h"
#include "icm42688_decoder.h"
#include "icm42688_reg.h"
@ -292,12 +292,21 @@ void icm42688_fifo_event(const struct device *dev) @@ -292,12 +292,21 @@ void icm42688_fifo_event(const struct device *dev)
struct icm42688_dev_data *drv_data = dev->data;
struct rtio_iodev *spi_iodev = drv_data->spi_iodev;
struct rtio *r = drv_data->r;
uint64_t cycles;
int rc;
if (drv_data->streaming_sqe == NULL) {
return;
}
drv_data->timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
rc = sensor_clock_get_cycles(&cycles);
if (rc != 0) {
LOG_ERR("Failed to get sensor clock cycles");
rtio_iodev_sqe_err(drv_data->streaming_sqe, err);
return;
}
drv_data->timestamp = sensor_clock_cycles_to_ns(cycles);
/*
* Setup rtio chain of ops with inline calls to make decisions

45
include/zephyr/drivers/sensor_clock.h

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
/*
* Copyright (c) 2024 Cienet
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_DRIVERS_SENSOR_CLOCK_H_
#define ZEPHYR_DRIVERS_SENSOR_CLOCK_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Retrieve the current sensor clock cycles.
*
* This function obtains the current cycle count from the selected
* sensor clock source. The clock source may be the system clock or
* an external clock, depending on the configuration.
*
* @param[out] cycles Pointer to a 64-bit unsigned integer where the
* current clock cycle count will be stored.
*
* @return 0 on success, or an error code on failure.
*/
int sensor_clock_get_cycles(uint64_t *cycles);
/**
* @brief Convert clock cycles to nanoseconds.
*
* This function converts clock cycles into nanoseconds based on the
* clock frequency.
*
* @param cycles Clock cycles to convert.
* @return Time in nanoseconds.
*/
uint64_t sensor_clock_cycles_to_ns(uint64_t cycles);
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_DRIVERS_SENSOR_CLOCK_H_ */

12
samples/sensor/clock/CMakeLists.txt

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
#
# Copyright (c) 2024 Cienet
#
# SPDX-License-Identifier: Apache-2.0
#
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(clock)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})

53
samples/sensor/clock/README.rst

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
.. zephyr:code-sample:: sensor_clock
:name: Sensor Clock
:relevant-api: sensor_interface
Test and debug Sensor Clock functionality.
Overview
********
This sample application demonstrates how to select the sensor clock source
and utilize the Sensor Clock API.
Building and Running
********************
The sample below uses the :ref:`nrf52840dk_nrf52840` and :ref:`nrf52833dk_nrf52833` boards.
To run this sample, ensure the following configurations:
* Enable one of the Kconfig options:
:kconfig:option:`CONFIG_SENSOR_CLOCK_COUNTER`,
:kconfig:option:`CONFIG_SENSOR_CLOCK_RTC`, or
:kconfig:option:`CONFIG_SENSOR_CLOCK_SYSTEM`.
Build and run the sample with the following command:
.. zephyr-app-commands::
:zephyr-app: samples/sensor/clock
:board: <board to use>
:goals: build flash
Sample Output
=============
The application will print the current sensor clock cycles and
their corresponding time in nanoseconds.
.. code-block:: console
Cycles: 143783087
Nanoseconds: 8986442937
Cycles: 159776386
Nanoseconds: 9986024125
Cycles: 175772543
Nanoseconds: 10985783937
Cycles: 191771203
Nanoseconds: 11985700187
Cycles: 207758870
Nanoseconds: 12984929375
Cycles: 223752074
Nanoseconds: 13984504625
...

13
samples/sensor/clock/boards/nrf52833dk_nrf52833.overlay

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
/*
* Copyright (c) 2024 Cienet
*
* SPDX-License-Identifier: Apache-2.0
*/
&rtc0 {
status = "okay";
};
&timer0 {
status = "okay";
};

13
samples/sensor/clock/boards/nrf52840dk_nrf52840.overlay

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
/*
* Copyright (c) 2024 Cienet
*
* SPDX-License-Identifier: Apache-2.0
*/
&rtc0 {
status = "okay";
};
&timer0 {
status = "okay";
};

11
samples/sensor/clock/boards/nrf528xx_counter.overlay

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
/*
* Copyright (c) 2024 Cienet
*
* SPDX-License-Identifier: Apache-2.0
*/
/ {
chosen {
zephyr,sensor-clock = &timer0;
};
};

11
samples/sensor/clock/boards/nrf528xx_rtc.overlay

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
/*
* Copyright (c) 2024 Cienet
*
* SPDX-License-Identifier: Apache-2.0
*/
/ {
chosen {
zephyr,sensor-clock = &rtc0;
};
};

14
samples/sensor/clock/prj.conf

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
#
# Copyright (c) 2024 Cienet
#
# SPDX-License-Identifier: Apache-2.0
#
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3
CONFIG_SENSOR=y
CONFIG_COUNTER=y
CONFIG_RTC=y
CONFIG_SENSOR_ASYNC_API=y
CONFIG_SENSOR_CLOCK_COUNTER=y

38
samples/sensor/clock/sample.yaml

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
#
# Copyright (c) 2024 Cienet
#
# SPDX-License-Identifier: Apache-2.0
tests:
sample.sensor.clock.counter:
filter: CONFIG_SENSOR_CLOCK_COUNTER
tags:
- drivers
- sensor
- counter
platform_allow:
- nrf52840dk/nrf52840
- nrf52833dk/nrf52833
extra_dtc_overlay_files:
- "boards/${BOARD}${NORMALIZED_BOARD_QUALIFIERS}.overlay"
- "boards/nrf528xx_counter.overlay"
sample.sensor.clock.rtc:
filter: CONFIG_SENSOR_CLOCK_RTC
tags:
- drivers
- sensor
- rtc
platform_allow:
- nrf52840dk/nrf52840
- nrf52833dk/nrf52833
extra_dtc_overlay_files:
- "boards/${BOARD}${NORMALIZED_BOARD_QUALIFIERS}.overlay"
- "boards/nrf528xx_rtc.overlay"
sample.sensor.clock.system:
filter: CONFIG_SENSOR_CLOCK_SYSTEM
tags:
- drivers
- sensor
- system_clock

36
samples/sensor/clock/src/main.c

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
/*
* Copyright (c) 2024 Cienet
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/drivers/sensor_clock.h>
#include <zephyr/sys_clock.h>
#include <zephyr/drivers/counter.h>
#include <stdio.h>
int main(void)
{
uint64_t cycles = 0;
uint64_t delta_ns = 0;
int err;
while (true) {
k_sleep(K_MSEC(1000));
err = sensor_clock_get_cycles(&cycles);
if (err) {
printf("Failed to get sensor clock cycles, error: %d\n", err);
continue;
}
printf("Cycles: %llu\n", cycles);
delta_ns = sensor_clock_cycles_to_ns(cycles);
printf("Nanoseconds: %llu\n", delta_ns);
}
return 0;
}

3
tests/drivers/sensor/icm42688/prj.conf

@ -11,3 +11,6 @@ CONFIG_SENSOR=y @@ -11,3 +11,6 @@ CONFIG_SENSOR=y
# Enable emulation
CONFIG_EMUL=y
CONFIG_SENSOR_ASYNC_API=y
CONFIG_SENSOR_CLOCK_SYSTEM=y

Loading…
Cancel
Save