Browse Source
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
31 changed files with 558 additions and 22 deletions
@ -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 |
@ -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); |
@ -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(); |
||||
} |
@ -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_ */ |
@ -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}) |
@ -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 |
||||
|
||||
... |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
/* |
||||
* Copyright (c) 2024 Cienet |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
&rtc0 { |
||||
status = "okay"; |
||||
}; |
||||
|
||||
&timer0 { |
||||
status = "okay"; |
||||
}; |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
/* |
||||
* Copyright (c) 2024 Cienet |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
&rtc0 { |
||||
status = "okay"; |
||||
}; |
||||
|
||||
&timer0 { |
||||
status = "okay"; |
||||
}; |
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
/* |
||||
* Copyright (c) 2024 Cienet |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
/ { |
||||
chosen { |
||||
zephyr,sensor-clock = &timer0; |
||||
}; |
||||
}; |
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
/* |
||||
* Copyright (c) 2024 Cienet |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
/ { |
||||
chosen { |
||||
zephyr,sensor-clock = &rtc0; |
||||
}; |
||||
}; |
@ -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 |
@ -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 |
@ -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; |
||||
} |
Loading…
Reference in new issue