Skip to content

Commit

Permalink
pm: Adds uninit for MPSL PM
Browse files Browse the repository at this point in the history
Adds uninit for MPSL PM integration.
Unregisters pm policy latency requests and events.

Signed-off-by: Knut Eldhuset <knut.eldhuset@nordicsemi.no>
  • Loading branch information
knutel-nordic committed Feb 14, 2025
1 parent 5b43696 commit 64fb0eb
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 5 deletions.
27 changes: 26 additions & 1 deletion include/mpsl/mpsl_work.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ static inline void mpsl_work_submit(struct k_work *work)
* processing other work items in a timely manner.
*
* @note This is a no-op if the work item is already scheduled or submitted,
* even if @p delay is @c K_NO_WAIT.
* even if @p delay is @c K_NO_WAIT. See @ref mpsl_work_reschedule().
*
* @param dwork Address of delayable work item.
*
Expand All @@ -74,6 +74,31 @@ static inline void mpsl_work_schedule(struct k_work_delayable *dwork, k_timeout_
}
}

/** @brief Reschedule a work item to the MPSL workqueue after a delay.
*
* @note Can be called by ISRs.
*
* @note
* Work items submitted to the MPSL workqueue should avoid using handlers
* that block or yield since this may prevent the MPSL workqueue from
* processing other work items in a timely manner.
*
* @note If the work item has not been scheduled before, this behaves the same
* as @ref mpsl_work_schedule().
*
* @param dwork Address of delayable work item.
*
* @param delay the time to wait before submitting the work item. If @c
* K_NO_WAIT and the work is not pending this is equivalent to
* mpsl_work_submit().
*/
static inline void mpsl_work_reschedule(struct k_work_delayable *dwork, k_timeout_t delay)
{
if (k_work_reschedule_for_queue(&mpsl_work_q, dwork, delay) < 0) {
__ASSERT(false, "k_work_reschedule_for_queue() failed.");
}
}

#ifdef __cplusplus
}
#endif
Expand Down
6 changes: 5 additions & 1 deletion subsys/mpsl/init/mpsl_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#endif

#if IS_ENABLED(CONFIG_MPSL_USE_ZEPHYR_PM)
#include <mpsl/mpsl_pm_utils.h>
#include "../pm/mpsl_pm_utils.h>
#endif

#if IS_ENABLED(CONFIG_MPSL_USE_EXTERNAL_CLOCK_CONTROL)
Expand Down Expand Up @@ -524,6 +524,10 @@ int32_t mpsl_lib_uninit(void)

mpsl_lib_irq_disable();

#if IS_ENABLED(CONFIG_MPSL_USE_ZEPHYR_PM)
mpsl_pm_utils_uninit();
#endif

mpsl_uninit();

#if defined(CONFIG_MPSL_USE_EXTERNAL_CLOCK_CONTROL)
Expand Down
27 changes: 26 additions & 1 deletion subsys/mpsl/pm/mpsl_pm_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
#include <zephyr/pm/policy.h>
#include <zephyr/logging/log.h>

#include <mpsl/mpsl_pm_utils.h>
#include <mpsl/mpsl_work.h>
#include "mpsl_pm_utils.h"

LOG_MODULE_REGISTER(mpsl_pm_utils, CONFIG_MPSL_LOG_LEVEL);

Expand All @@ -22,6 +23,10 @@ LOG_MODULE_REGISTER(mpsl_pm_utils, CONFIG_MPSL_LOG_LEVEL);
#define TIME_TO_REGISTER_EVENT_IN_ZEPHYR_US 1000
#define PM_MAX_LATENCY_HCI_COMMANDS_US 499999

static void m_work_handler(struct k_work *work);
static K_WORK_DELAYABLE_DEFINE(m_pm_uninit_work, m_work_handler);
static atomic_t m_pm_enabled;

static uint8_t m_pm_prev_flag_value;
static bool m_pm_event_is_registered;
static uint32_t m_prev_lat_value_us;
Expand Down Expand Up @@ -101,8 +106,19 @@ static void m_register_latency(void)
}
}

static void m_work_handler(struct k_work *work)
{
ARG_UNUSED(work);
mpsl_pm_utils_work_handler();
}

void mpsl_pm_utils_work_handler(void)
{
if (!atomic_get(&m_pm_enabled)) {
pm_policy_latency_request_remove(&m_latency_req);
pm_policy_event_unregister(&m_evt);
return;
}
m_register_event();
m_register_latency();
}
Expand All @@ -111,6 +127,8 @@ void mpsl_pm_utils_init(void)
{
mpsl_pm_params_t params = {0};

atomic_set(&m_pm_enabled, 1);

pm_policy_latency_request_add(&m_latency_req, PM_MAX_LATENCY_HCI_COMMANDS_US);
m_prev_lat_value_us = PM_MAX_LATENCY_HCI_COMMANDS_US;

Expand All @@ -119,3 +137,10 @@ void mpsl_pm_utils_init(void)
m_pm_prev_flag_value = params.cnt_flag;
m_pm_event_is_registered = false;
}

void mpsl_pm_utils_uninit(void)
{
mpsl_pm_uninit();
atomic_set(&m_pm_enabled, 0);
mpsl_work_reschedule(&m_pm_uninit_work, K_NO_WAIT);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ extern "C" {
*/
void mpsl_pm_utils_init(void);

/** @brief Unitialize MPSL Power Management
*
* This routine uninitializes MPSL PM (via `mpsl_pm_uninit`).
*/
void mpsl_pm_utils_uninit(void);

/** @brief Handles MPSL Power Management work
*
* This calls Zephyr Power Management policy functions according
Expand Down
10 changes: 9 additions & 1 deletion tests/subsys/mpsl/pm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ project(pm_test)
test_runner_generate(pm_test.c)

# Create mocks for pm module.
cmock_handle(${CMAKE_CURRENT_SOURCE_DIR}/kernel_minimal_mock.h)
cmock_handle(${ZEPHYR_BASE}/include/zephyr/pm/policy.h)
cmock_handle(${ZEPHYR_NRFXLIB_MODULE_DIR}/mpsl/include/mpsl_pm.h)
cmock_handle(${ZEPHYR_NRFXLIB_MODULE_DIR}/mpsl/include/mpsl_pm_config.h)
cmock_handle(${ZEPHYR_NRF_MODULE_DIR}/include/mpsl/mpsl_work.h)

# Add Unit Under Test source files
target_sources(app PRIVATE ${ZEPHYR_NRF_MODULE_DIR}/subsys/mpsl/pm/mpsl_pm_utils.c)
Expand All @@ -24,7 +26,13 @@ target_sources(app PRIVATE ${ZEPHYR_NRF_MODULE_DIR}/subsys/mpsl/pm/mpsl_pm_utils
target_sources(app PRIVATE pm_test.c)

# Include paths
target_include_directories(app PRIVATE src)
target_include_directories(app PRIVATE
src
${ZEPHYR_NRF_MODULE_DIR}/subsys/mpsl/pm)

# Preinclude file to the UUT to redefine kernel and mpsl_work functions.
set_property(SOURCE ${ZEPHYR_NRF_MODULE_DIR}/subsys/mpsl/pm/mpsl_pm_utils.c
PROPERTY COMPILE_FLAGS "-include mocks/kernel_minimal_mock.h -include mocks/mpsl_work.h")

# Options that cannot be passed through Kconfig fragments.
target_compile_options(app PRIVATE
Expand Down
42 changes: 42 additions & 0 deletions tests/subsys/mpsl/pm/kernel_minimal_mock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#ifndef ZEPHYR_INCLUDE_KERNEL_H_
#define ZEPHYR_INCLUDE_KERNEL_H_

/* CMock chokes on zephyr/kernel.h, so we define the minimum required to build
* mpsl_pm and tests, then let CMock generate mocks from this file instead.
*/

#include <stdint.h>

struct k_work {
void *handler;
};

typedef struct k_timeout {
uint64_t value;
} k_timeout_t;

struct k_work_delayable {
void *handler;
};

#define Z_WORK_DELAYABLE_INITIALIZER(work_handler) {work_handler}
#define K_WORK_DELAYABLE_DEFINE(work, work_handler) \
struct k_work_delayable work = Z_WORK_DELAYABLE_INITIALIZER(work_handler)

#define Z_WORK_INITIALIZER(work_handler) {work_handler}
#define K_WORK_DEFINE(work, work_handler) \
struct k_work_delayable work = Z_WORK_INITIALIZER(work_handler)

k_timeout_t K_USEC(uint64_t d);

#define K_NO_WAIT (k_timeout_t) {0}

int64_t k_uptime_get(void);

#endif /* ZEPHYR_INCLUDE_KERNEL_H_ */
33 changes: 32 additions & 1 deletion tests/subsys/mpsl/pm/pm_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
#include "cmock_policy.h"
#include "cmock_mpsl_pm.h"
#include "cmock_mpsl_pm_config.h"
#include "cmock_mpsl_work.h"
#include "cmock_kernel_minimal_mock.h"

#include <mpsl/mpsl_pm_utils.h>
#include "mpsl_pm_utils.h"

#define PM_MAX_LATENCY_HCI_COMMANDS_US 499999

Expand Down Expand Up @@ -208,6 +210,35 @@ void test_register_update_and_deregister_event(void)
run_test(&test_vectors[0], ARRAY_SIZE(test_vectors));
}

void test_uninit(void)
{
mpsl_pm_params_t pm_params_initial = {0};

__cmock_pm_policy_latency_request_add_Expect(0, PM_MAX_LATENCY_HCI_COMMANDS_US);
__cmock_pm_policy_latency_request_add_IgnoreArg_req();

__cmock_mpsl_pm_init_Expect();

__cmock_mpsl_pm_params_get_ExpectAnyArgsAndReturn(true);
__cmock_mpsl_pm_params_get_ReturnThruPtr_p_params(&pm_params_initial);

mpsl_pm_utils_init();

__cmock_mpsl_work_reschedule_Expect(
0, (k_timeout_t) { 0 });
__cmock_mpsl_work_reschedule_IgnoreArg_dwork();
__cmock_mpsl_pm_uninit_Expect();

mpsl_pm_utils_uninit();

__cmock_pm_policy_latency_request_remove_Expect(0);
__cmock_pm_policy_latency_request_remove_IgnoreArg_req();
__cmock_pm_policy_event_unregister_Expect(0);
__cmock_pm_policy_event_unregister_IgnoreArg_evt();

Check failure on line 238 in tests/subsys/mpsl/pm/pm_test.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

TRAILING_WHITESPACE

tests/subsys/mpsl/pm/pm_test.c:238 trailing whitespace
mpsl_pm_utils_work_handler();
}

int main(void)
{
(void)unity_main();
Expand Down

0 comments on commit 64fb0eb

Please sign in to comment.