From 8975f194332961c26232dccf3b24baac4d0bfa5f Mon Sep 17 00:00:00 2001 From: Felix Wang Date: Tue, 26 Aug 2025 17:13:32 +0800 Subject: [PATCH 1/3] samples: drivers: counter: alarm: Add top function for alarm feature For peripherals which does not support alarm function, we can use counter_set_top_value to simulate alarm feature, and the callback will be executed after the timer expired. The alarm time can be changed by setting different top value. In this code, the original alarm function has higher priority. The top function are only be used when alarm function is unsupported. Signed-off-by: Felix Wang --- samples/drivers/counter/alarm/src/main.c | 97 ++++++++++++++++++++---- 1 file changed, 83 insertions(+), 14 deletions(-) diff --git a/samples/drivers/counter/alarm/src/main.c b/samples/drivers/counter/alarm/src/main.c index fae92eb86eded..ebd4fc5311d2d 100644 --- a/samples/drivers/counter/alarm/src/main.c +++ b/samples/drivers/counter/alarm/src/main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 Linaro Limited + * Copyright 2025 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +15,7 @@ #define ALARM_CHANNEL_ID 0 struct counter_alarm_cfg alarm_cfg; +struct counter_top_cfg top_cfg; #if defined(CONFIG_BOARD_SAMD20_XPRO) #define TIMER DT_NODELABEL(tc4) @@ -72,6 +74,11 @@ struct counter_alarm_cfg alarm_cfg; #define TIMER DT_INST(0, renesas_rz_gtm_counter) #elif defined(CONFIG_COUNTER_CC23X0_RTC) #define TIMER DT_NODELABEL(rtc0) +#elif defined(CONFIG_COUNTER_MCUX_LPIT) +/* Index may start from 1 or 0 depends on name convention from RM */ +#define TIMER \ + COND_CODE_1(DT_NODE_EXISTS(DT_NODELABEL(lpit0_channel0)), \ + (DT_NODELABEL(lpit0_channel0)), (DT_NODELABEL(lpit1_channel0))) #else #error Unable to find a counter device node in devicetree #endif @@ -117,40 +124,102 @@ static void test_counter_interrupt_fn(const struct device *counter_dev, } } -int main(void) +static void test_counter_top_interrupt_fn(const struct device *counter_dev, void *user_data) { - const struct device *const counter_dev = DEVICE_DT_GET(TIMER); + struct counter_top_cfg *config = user_data; + uint32_t now_ticks; + uint64_t now_usec; + int now_sec; int err; - printk("Counter alarm sample\n\n"); + now_ticks = counter_get_top_value(counter_dev); + now_usec = counter_ticks_to_us(counter_dev, now_ticks); + now_sec = (int)(now_usec / USEC_PER_SEC); - if (!device_is_ready(counter_dev)) { - printk("device not ready.\n"); - return 0; + printk("!!! Alarm !!!\n"); + printk("Now: %u\n", now_sec); + + /* Set a new alarm with a double length duration */ + config->ticks = config->ticks * 2U; + + printk("Set alarm in %u sec (%u ticks)\n", + (uint32_t)(counter_ticks_to_us(counter_dev, config->ticks) / USEC_PER_SEC), + config->ticks); + + err = counter_set_top_value(counter_dev, user_data); + if (err != 0) { + printk("Alarm could not be set\n"); } +} - counter_start(counter_dev); +static int alarm_setup(const struct device *counter_dev, uint32_t ticks) +{ + int err; alarm_cfg.flags = 0; - alarm_cfg.ticks = counter_us_to_ticks(counter_dev, DELAY); + alarm_cfg.ticks = ticks; alarm_cfg.callback = test_counter_interrupt_fn; alarm_cfg.user_data = &alarm_cfg; err = counter_set_channel_alarm(counter_dev, ALARM_CHANNEL_ID, &alarm_cfg); - printk("Set alarm in %u sec (%u ticks)\n", - (uint32_t)(counter_ticks_to_us(counter_dev, - alarm_cfg.ticks) / USEC_PER_SEC), - alarm_cfg.ticks); if (-EINVAL == err) { printk("Alarm settings invalid\n"); } else if (-ENOTSUP == err) { printk("Alarm setting request not supported\n"); - } else if (err != 0) { - printk("Error\n"); } + return err; +} + +static int top_setup(const struct device *counter_dev, uint32_t ticks) +{ + int err; + + top_cfg.flags = 0; + top_cfg.ticks = ticks; + top_cfg.callback = test_counter_top_interrupt_fn; + top_cfg.user_data = &top_cfg; + + err = counter_set_top_value(counter_dev, &top_cfg); + + if (-EINVAL == err) { + printk("Top settings invalid\n"); + } else if (-ENOTSUP == err) { + printk("Top setting request not supported\n"); + } + + return err; +} + +int main(void) +{ + const struct device *const counter_dev = DEVICE_DT_GET(TIMER); + uint32_t ticks = counter_us_to_ticks(counter_dev, DELAY); + int err; + + printk("Counter alarm sample\n\n"); + + if (!device_is_ready(counter_dev)) { + printk("device not ready.\n"); + return 0; + } + + counter_start(counter_dev); + + err = alarm_setup(counter_dev, ticks); + if (err != 0) { + /* If alarm setup fails, try top setup */ + err = top_setup(counter_dev, ticks); + if (err != 0) { + printk("Error\n"); + } + } + + printk("Set alarm in %u sec (%u ticks)\n", + (uint32_t)(counter_ticks_to_us(counter_dev, ticks) / USEC_PER_SEC), ticks); + while (1) { k_sleep(K_FOREVER); } From 10ae8cda9e614bf8a4ae481caede8a10d4181520 Mon Sep 17 00:00:00 2001 From: Felix Wang Date: Tue, 26 Aug 2025 17:30:37 +0800 Subject: [PATCH 2/3] drivers: Counter: Change parameter in LPIT ISR callback In mcux_lpit_isr, the first parameter in top_callback is LPIT counter device, however, in this driver, we create channel devices for each channel, and mcux_lpit_driver_api is for channel devices, not for counter device. To use mcux_lpit_driver_api in callback function, for example, update period by set_top_value function, we need to pass channel device as the first parameter of top_callback. Signed-off-by: Felix Wang --- drivers/counter/counter_mcux_lpit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/counter/counter_mcux_lpit.c b/drivers/counter/counter_mcux_lpit.c index 697a4e1efe4e2..3c0500fa84b75 100644 --- a/drivers/counter/counter_mcux_lpit.c +++ b/drivers/counter/counter_mcux_lpit.c @@ -161,7 +161,7 @@ static void mcux_lpit_isr(const struct device *dev) LPIT_CHANNEL_DATA(config->channels[channel_index]); if (data->top_callback != NULL) { - data->top_callback(dev, data->top_user_data); + data->top_callback(config->channels[channel_index], data->top_user_data); } } } From 76351e3beda55ec24f11177d19e982437e61899f Mon Sep 17 00:00:00 2001 From: Felix Wang Date: Tue, 26 Aug 2025 17:39:23 +0800 Subject: [PATCH 3/3] samples: drivers: counter: alarm: Enable alarm examples for boards Enable the alarm samples for frdm_ke17z and mimxrt1180_evk/cm33. Signed-off-by: Felix Wang --- .../drivers/counter/alarm/boards/frdm_ke17z.conf | 7 +++++++ .../drivers/counter/alarm/boards/frdm_ke17z.overlay | 13 +++++++++++++ .../boards/mimxrt1180_evk_mimxrt1189_cm33.conf | 7 +++++++ .../boards/mimxrt1180_evk_mimxrt1189_cm33.overlay | 13 +++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 samples/drivers/counter/alarm/boards/frdm_ke17z.conf create mode 100644 samples/drivers/counter/alarm/boards/frdm_ke17z.overlay create mode 100644 samples/drivers/counter/alarm/boards/mimxrt1180_evk_mimxrt1189_cm33.conf create mode 100644 samples/drivers/counter/alarm/boards/mimxrt1180_evk_mimxrt1189_cm33.overlay diff --git a/samples/drivers/counter/alarm/boards/frdm_ke17z.conf b/samples/drivers/counter/alarm/boards/frdm_ke17z.conf new file mode 100644 index 0000000000000..e196cda4baee9 --- /dev/null +++ b/samples/drivers/counter/alarm/boards/frdm_ke17z.conf @@ -0,0 +1,7 @@ +# +# Copyright 2025 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_COUNTER_MCUX_LPIT=y diff --git a/samples/drivers/counter/alarm/boards/frdm_ke17z.overlay b/samples/drivers/counter/alarm/boards/frdm_ke17z.overlay new file mode 100644 index 0000000000000..33fddcf26846d --- /dev/null +++ b/samples/drivers/counter/alarm/boards/frdm_ke17z.overlay @@ -0,0 +1,13 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&lpit0 { + status = "okay"; +}; + +&lpit0_channel0 { + status = "okay"; +}; diff --git a/samples/drivers/counter/alarm/boards/mimxrt1180_evk_mimxrt1189_cm33.conf b/samples/drivers/counter/alarm/boards/mimxrt1180_evk_mimxrt1189_cm33.conf new file mode 100644 index 0000000000000..2c596e280bba2 --- /dev/null +++ b/samples/drivers/counter/alarm/boards/mimxrt1180_evk_mimxrt1189_cm33.conf @@ -0,0 +1,7 @@ +# +# Copyright 2024-2025 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_COUNTER_MCUX_LPIT=y diff --git a/samples/drivers/counter/alarm/boards/mimxrt1180_evk_mimxrt1189_cm33.overlay b/samples/drivers/counter/alarm/boards/mimxrt1180_evk_mimxrt1189_cm33.overlay new file mode 100644 index 0000000000000..12b40aac87193 --- /dev/null +++ b/samples/drivers/counter/alarm/boards/mimxrt1180_evk_mimxrt1189_cm33.overlay @@ -0,0 +1,13 @@ +/* + * Copyright 2024-2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&lpit1 { + status = "okay"; +}; + +&lpit1_channel0 { + status = "okay"; +};