diff --git a/samples/boards/nrf/clock_control/CMakeLists.txt b/samples/boards/nrf/clock_control/CMakeLists.txt new file mode 100644 index 00000000000..36173b99bb2 --- /dev/null +++ b/samples/boards/nrf/clock_control/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(nrf_clock_control) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/boards/nrf/clock_control/Kconfig b/samples/boards/nrf/clock_control/Kconfig new file mode 100644 index 00000000000..ce92291e2af --- /dev/null +++ b/samples/boards/nrf/clock_control/Kconfig @@ -0,0 +1,38 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config SAMPLE_CLOCK_FREQUENCY_HZ + int "Frequency specification to request from clock in Hz" + default 0 + help + 0 -> ignore frequency + >0 -> use at minimum selected frequency. To select the + highest supported frequency use UINT32_MAX. + +config SAMPLE_CLOCK_ACCURACY_PPM + int "Accuracy specification to request from clock in PPM" + default 0 + help + 0 -> ignore accuracy + 1 -> use max accuracy + >1 -> use at minimum selected accuracy + +config SAMPLE_CLOCK_PRECISION + int "Precision specification to request from clock" + default 0 + help + 0 -> low precision + 1 -> high precision + +config SAMPLE_PRE_REQUEST_TIMEOUT + int "Time to wait after boot before requesting clock specs in seconds" + default 2 + help + The distributed clock domains may need time to initialize + before a clock request can be met. + +config SAMPLE_KEEP_REQUEST_TIMEOUT + int "Time to keep request alive in seconds" + default 2 + +source "Kconfig.zephyr" diff --git a/samples/boards/nrf/clock_control/configs/cpuapp_hsfll.conf b/samples/boards/nrf/clock_control/configs/cpuapp_hsfll.conf new file mode 100644 index 00000000000..5c1bad08a80 --- /dev/null +++ b/samples/boards/nrf/clock_control/configs/cpuapp_hsfll.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_CLOCK_CONTROL_NRF2=y + +CONFIG_SAMPLE_CLOCK_FREQUENCY_HZ=320000000 diff --git a/samples/boards/nrf/clock_control/configs/cpuapp_hsfll.overlay b/samples/boards/nrf/clock_control/configs/cpuapp_hsfll.overlay new file mode 100644 index 00000000000..651f8567b7a --- /dev/null +++ b/samples/boards/nrf/clock_control/configs/cpuapp_hsfll.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/{ + aliases { + sample-clock = &cpuapp_hsfll; + }; +}; diff --git a/samples/boards/nrf/clock_control/configs/fll16m.conf b/samples/boards/nrf/clock_control/configs/fll16m.conf new file mode 100644 index 00000000000..de9942857b9 --- /dev/null +++ b/samples/boards/nrf/clock_control/configs/fll16m.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_CLOCK_CONTROL_NRF2=y + +CONFIG_SAMPLE_CLOCK_ACCURACY_PPM=30 diff --git a/samples/boards/nrf/clock_control/configs/fll16m.overlay b/samples/boards/nrf/clock_control/configs/fll16m.overlay new file mode 100644 index 00000000000..0169c5a2574 --- /dev/null +++ b/samples/boards/nrf/clock_control/configs/fll16m.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/{ + aliases { + sample-clock = &fll16m; + }; +}; diff --git a/samples/boards/nrf/clock_control/configs/lfclk.conf b/samples/boards/nrf/clock_control/configs/lfclk.conf new file mode 100644 index 00000000000..6cf09f0e4c7 --- /dev/null +++ b/samples/boards/nrf/clock_control/configs/lfclk.conf @@ -0,0 +1,7 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_CLOCK_CONTROL_NRF2=y + +CONFIG_SAMPLE_CLOCK_ACCURACY_PPM=20 +CONFIG_SAMPLE_CLOCK_PRECISION=1 diff --git a/samples/boards/nrf/clock_control/configs/lfclk.overlay b/samples/boards/nrf/clock_control/configs/lfclk.overlay new file mode 100644 index 00000000000..6a04c2de706 --- /dev/null +++ b/samples/boards/nrf/clock_control/configs/lfclk.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/{ + aliases { + sample-clock = &lfclk; + }; +}; diff --git a/samples/boards/nrf/clock_control/configs/uart135.conf b/samples/boards/nrf/clock_control/configs/uart135.conf new file mode 100644 index 00000000000..de9942857b9 --- /dev/null +++ b/samples/boards/nrf/clock_control/configs/uart135.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_CLOCK_CONTROL_NRF2=y + +CONFIG_SAMPLE_CLOCK_ACCURACY_PPM=30 diff --git a/samples/boards/nrf/clock_control/configs/uart135.overlay b/samples/boards/nrf/clock_control/configs/uart135.overlay new file mode 100644 index 00000000000..0e81f4cd2aa --- /dev/null +++ b/samples/boards/nrf/clock_control/configs/uart135.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/{ + aliases { + sample-device = &uart135; + }; +}; + +&uart135 { + status = "okay"; +}; diff --git a/samples/boards/nrf/clock_control/sample.yaml b/samples/boards/nrf/clock_control/sample.yaml new file mode 100644 index 00000000000..dd2cfe86c41 --- /dev/null +++ b/samples/boards/nrf/clock_control/sample.yaml @@ -0,0 +1,31 @@ +sample: + name: Clock control sample +common: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + harness: console + harness_config: + type: one_line + regex: + - "clock spec request released" +tests: + sample.boards.nrf.clock_control.fll16m: + filter: dt_nodelabel_enabled("fll16m") + extra_args: + - CONF_FILE="configs/fll16m.conf" + - DTC_OVERLAY_FILE="configs/fll16m.overlay" + sample.boards.nrf.clock_control.lfclk: + filter: dt_nodelabel_enabled("lfclk") + extra_args: + - CONF_FILE="configs/lfclk.conf" + - DTC_OVERLAY_FILE="configs/lfclk.overlay" + sample.boards.nrf.clock_control.uart135: + filter: dt_nodelabel_enabled("uart135") + extra_args: + - CONF_FILE="configs/uart135.conf" + - DTC_OVERLAY_FILE="configs/uart135.overlay" + sample.boards.nrf.clock_control.cpuapp_hsfll: + filter: dt_nodelabel_enabled("cpuapp_hsfll") + extra_args: + - CONF_FILE="configs/cpuapp_hsfll.conf" + - DTC_OVERLAY_FILE="configs/cpuapp_hsfll.overlay" diff --git a/samples/boards/nrf/clock_control/src/main.c b/samples/boards/nrf/clock_control/src/main.c new file mode 100644 index 00000000000..ebaaa0cecbd --- /dev/null +++ b/samples/boards/nrf/clock_control/src/main.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#if DT_NODE_EXISTS(DT_ALIAS(sample_device)) +#define SAMPLE_CLOCK_NODE DT_CLOCKS_CTLR(DT_ALIAS(sample_device)) +#elif DT_NODE_EXISTS(DT_ALIAS(sample_clock)) +#define SAMPLE_CLOCK_NODE DT_ALIAS(sample_clock) +#endif + +#define SAMPLE_CLOCK_NAME DT_NODE_FULL_NAME(SAMPLE_CLOCK_NODE) + +#define SAMPLE_NOTIFY_TIMEOUT K_SECONDS(2) +#define SAMPLE_PRE_REQUEST_TIMEOUT K_SECONDS(CONFIG_SAMPLE_PRE_REQUEST_TIMEOUT) +#define SAMPLE_KEEP_REQUEST_TIMEOUT K_SECONDS(CONFIG_SAMPLE_KEEP_REQUEST_TIMEOUT) + +const struct device *sample_clock_dev = DEVICE_DT_GET(SAMPLE_CLOCK_NODE); + +static K_SEM_DEFINE(sample_sem, 0, 1); + +static void sample_notify_cb(struct onoff_manager *mgr, + struct onoff_client *cli, + uint32_t state, + int res) +{ + ARG_UNUSED(mgr); + ARG_UNUSED(cli); + ARG_UNUSED(state); + ARG_UNUSED(res); + + k_sem_give(&sample_sem); +} + +int main(void) +{ + struct onoff_client cli; + int ret; + int res; + int64_t req_start_uptime; + int64_t req_stop_uptime; + + printk("\n"); + printk("clock name: %s\n", SAMPLE_CLOCK_NAME); + printk("minimum frequency request: %uHz\n", CONFIG_SAMPLE_CLOCK_FREQUENCY_HZ); + printk("minimum accuracy request: %uPPM\n", CONFIG_SAMPLE_CLOCK_ACCURACY_PPM); + printk("minimum precision request: %u\n", CONFIG_SAMPLE_CLOCK_PRECISION); + + const struct nrf_clock_spec spec = { + .frequency = CONFIG_SAMPLE_CLOCK_FREQUENCY_HZ, + .accuracy = CONFIG_SAMPLE_CLOCK_ACCURACY_PPM, + .precision = CONFIG_SAMPLE_CLOCK_PRECISION, + }; + + sys_notify_init_callback(&cli.notify, sample_notify_cb); + + k_sleep(SAMPLE_PRE_REQUEST_TIMEOUT); + + printk("\n"); + printk("requesting minimum clock specs\n"); + req_start_uptime = k_uptime_get(); + ret = nrf_clock_control_request(sample_clock_dev, &spec, &cli); + if (ret < 0) { + printk("minimum clock specs could not be met\n"); + return 0; + } + + ret = k_sem_take(&sample_sem, SAMPLE_NOTIFY_TIMEOUT); + if (ret < 0) { + printk("timed out waiting for clock to meet request\n"); + return 0; + } + + req_stop_uptime = k_uptime_get(); + + ret = sys_notify_fetch_result(&cli.notify, &res); + if (ret < 0) { + printk("sys notify fetch failed\n"); + return 0; + } + + if (res < 0) { + printk("failed to apply request to clock\n"); + return 0; + } + + printk("request applied to clock in %llims\n", req_stop_uptime - req_start_uptime); + k_sleep(SAMPLE_KEEP_REQUEST_TIMEOUT); + + printk("\n"); + printk("releasing requested clock specs\n"); + ret = nrf_clock_control_release(sample_clock_dev, &spec); + if (ret < 0) { + printk("failed to release requested clock specs\n"); + return 0; + } + + printk("clock spec request released\n"); + return 0; +}