From 37ebaa0de5913cce8ab0545a9e30e976156679c5 Mon Sep 17 00:00:00 2001 From: Piotr Koziar Date: Fri, 10 Jan 2025 16:42:28 +0100 Subject: [PATCH] modules: nrfxlib: nrf_802154: add lptimer pm utils module Adds pm utils module that updates the Power Management module upon the request from the 802.15.4 lptimer module. Signed-off-by: Piotr Koziar --- modules/nrfxlib/nrf_802154/CMakeLists.txt | 1 + .../nrf_802154_platform_sl_lptimer_grtc.c | 5 ++ ...802154_platform_sl_lptimer_grtc_pm_utils.c | 68 +++++++++++++++++++ ...802154_platform_sl_lptimer_grtc_pm_utils.h | 43 ++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 modules/nrfxlib/nrf_802154/sl/platform/nrf_802154_platform_sl_lptimer_grtc_pm_utils.c create mode 100644 modules/nrfxlib/nrf_802154/sl/platform/nrf_802154_platform_sl_lptimer_grtc_pm_utils.h diff --git a/modules/nrfxlib/nrf_802154/CMakeLists.txt b/modules/nrfxlib/nrf_802154/CMakeLists.txt index 98a68bfbf428..fd6016ae195e 100644 --- a/modules/nrfxlib/nrf_802154/CMakeLists.txt +++ b/modules/nrfxlib/nrf_802154/CMakeLists.txt @@ -18,6 +18,7 @@ if (CONFIG_NRF_802154_RADIO_DRIVER OR CONFIG_NRF_802154_SERIALIZATION) ${CMAKE_CURRENT_SOURCE_DIR}/sl/platform/nrf_802154_platform_timestamper.c ${CMAKE_CURRENT_SOURCE_DIR}/sl/platform/nrf_802154_platform_sl_lptimer_grtc.c ${CMAKE_CURRENT_SOURCE_DIR}/sl/platform/nrf_802154_platform_sl_lptimer_grtc_hw_task.c + ${CMAKE_CURRENT_SOURCE_DIR}/sl/platform/nrf_802154_platform_sl_lptimer_grtc_pm_utils.c ) endif() endif () diff --git a/modules/nrfxlib/nrf_802154/sl/platform/nrf_802154_platform_sl_lptimer_grtc.c b/modules/nrfxlib/nrf_802154/sl/platform/nrf_802154_platform_sl_lptimer_grtc.c index 94b46b864e55..74ab248fdad0 100644 --- a/modules/nrfxlib/nrf_802154/sl/platform/nrf_802154_platform_sl_lptimer_grtc.c +++ b/modules/nrfxlib/nrf_802154/sl/platform/nrf_802154_platform_sl_lptimer_grtc.c @@ -6,6 +6,7 @@ #include "platform/nrf_802154_platform_sl_lptimer.h" #include "nrf_802154_platform_sl_lptimer_grtc_hw_task.h" +#include "nrf_802154_platform_sl_lptimer_grtc_pm_utils.h" #include #include @@ -95,6 +96,8 @@ void nrf_802154_platform_sl_lptimer_schedule_at(uint64_t fire_lpticks) fire_lpticks, timer_compare_handler, NULL); + + nrf_802154_platform_sl_lptimer_pm_utils_event_update(fire_lpticks); } void nrf_802154_platform_sl_lptimer_disable(void) @@ -102,6 +105,8 @@ void nrf_802154_platform_sl_lptimer_disable(void) atomic_clear_bit(&m_enabled, 0); z_nrf_grtc_timer_abort(m_callbacks_cc_channel); + + nrf_802154_platform_sl_lptimer_pm_utils_event_unregister(); } void nrf_802154_platform_sl_lptimer_critical_section_enter(void) diff --git a/modules/nrfxlib/nrf_802154/sl/platform/nrf_802154_platform_sl_lptimer_grtc_pm_utils.c b/modules/nrfxlib/nrf_802154/sl/platform/nrf_802154_platform_sl_lptimer_grtc_pm_utils.c new file mode 100644 index 000000000000..115834becd73 --- /dev/null +++ b/modules/nrfxlib/nrf_802154/sl/platform/nrf_802154_platform_sl_lptimer_grtc_pm_utils.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "nrf_802154_platform_sl_lptimer_grtc_pm_utils.h" + +#include +#include + +#define LPTIMER_PM_UTILS_STACK_SIZE 1024 + +static K_SEM_DEFINE(m_lptimer_pm_utils_sem, 0, 1); + +static struct pm_policy_event m_pm_event; +static int64_t m_trigger_time; +static bool m_event_registered; + +#define SYS_TICK_PER_GRTC_CYC \ + ((uint64_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC / (uint64_t)sys_clock_hw_cycles_per_sec()) + +static int64_t grtc_ticks_to_system_ticks(uint64_t abs_grtc) +{ + int64_t curr_sys = k_uptime_ticks(); + uint64_t curr_grtc = z_nrf_grtc_timer_read(); + + uint64_t result = (abs_grtc > curr_grtc) ? (abs_grtc - curr_grtc) : 0; + + return curr_sys + result * SYS_TICK_PER_GRTC_CYC; +} + +void nrf_802154_platform_sl_lptimer_pm_utils_event_update(uint64_t grtc_ticks) +{ + int64_t event_time = (grtc_ticks > 0) ? grtc_ticks_to_system_ticks(grtc_ticks) : 0; + + if (m_trigger_time != event_time) { + m_trigger_time = event_time; + + k_sem_give(&m_lptimer_pm_utils_sem); + } +} + +static void lptimer_pm_utils_thread_func(void *dummy1, void *dummy2, void *dummy3) +{ + ARG_UNUSED(dummy1); + ARG_UNUSED(dummy2); + ARG_UNUSED(dummy3); + + while (true) { + k_sem_take(&m_lptimer_pm_utils_sem, K_FOREVER); + + if (m_trigger_time == 0) { + if (m_event_registered) { + pm_policy_event_unregister(&m_pm_event); + } + m_event_registered = false; + } else if (!m_event_registered) { + pm_policy_event_register(&m_pm_event, m_trigger_time); + m_event_registered = true; + } else { + pm_policy_event_update(&m_pm_event, m_trigger_time); + } + } +} + +K_THREAD_DEFINE(lptimer_pm_utils_thread, LPTIMER_PM_UTILS_STACK_SIZE, + lptimer_pm_utils_thread_func, NULL, NULL, NULL, K_LOWEST_APPLICATION_THREAD_PRIO, 0, 0); diff --git a/modules/nrfxlib/nrf_802154/sl/platform/nrf_802154_platform_sl_lptimer_grtc_pm_utils.h b/modules/nrfxlib/nrf_802154/sl/platform/nrf_802154_platform_sl_lptimer_grtc_pm_utils.h new file mode 100644 index 000000000000..883b13d35f92 --- /dev/null +++ b/modules/nrfxlib/nrf_802154/sl/platform/nrf_802154_platform_sl_lptimer_grtc_pm_utils.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef NRF_802154_PLATFORM_SL_LPTIMER_GRTC_PM_UTILS_H_ +#define NRF_802154_PLATFORM_SL_LPTIMER_GRTC_PM_UTILS_H_ + +#include + +/** + * @brief Updates the trigger time of an upcoming event, allowing forwarding it to + * the Power Management module. + * + * After some delay, the event's trigger time is sent to the Power Management module + * via @ref pm_policy_event_register or @ref pm_policy_event_update. + * + * This function opens a sequence that should be closed + * by @ref nrf_802154_platform_sl_lptimer_pm_utils_event_unregister call. + * In the meantime, the @ref nrf_802154_platform_sl_lptimer_pm_utils_event_update can be called + * multiple times. + * + * @note There is no guarantee, that the aforementioned pm_policy methods will be called before + * the event's trigger time. + * + * @param grtc_ticks When the event will occur, in absolute GRTC ticks. + */ +void nrf_802154_platform_sl_lptimer_pm_utils_event_update(uint64_t grtc_ticks); + +/** + * @brief Informs that there are no events planned and the Power Management event + * registered by @ref nrf_802154_platform_sl_lptimer_pm_utils_event_update requires unregistration. + * + * Unless already called and if the @ref nrf_802154_platform_sl_lptimer_pm_utils_event_update + * precedes this function, the function will call @ref pm_policy_event_unregister with some delay. + */ +static inline void nrf_802154_platform_sl_lptimer_pm_utils_event_unregister(void) +{ + return nrf_802154_platform_sl_lptimer_pm_utils_event_update(0); +} + +#endif /* NRF_802154_PLATFORM_SL_LPTIMER_GRTC_PM_UTILS_H_ */