From 167a5c24a17c054a7026be721da996a7c49c7065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Chru=C5=9Bci=C5=84ski?= Date: Mon, 12 May 2025 10:37:19 +0200 Subject: [PATCH 1/3] manifest: Update sdk-zephyr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update sdk-zephyr with fixes in PM policy events. Signed-off-by: Krzysztof Chruściński --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 9894b8e7106d..4daebc6eaddb 100644 --- a/west.yml +++ b/west.yml @@ -69,7 +69,7 @@ manifest: # https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/guides/modules.html - name: zephyr repo-path: sdk-zephyr - revision: eceea6b3b5d8a9eecd014d16478fe1c597e62b6d + revision: 75d015949c315b065dd808695ec1fb3f268a757b import: # In addition to the zephyr repository itself, NCS also # imports the contents of zephyr/west.yml at the above From 29e3f68d4fa56a2e6e917c32ca282b0c95c93884 Mon Sep 17 00:00:00 2001 From: Knut Eldhuset Date: Wed, 4 Dec 2024 12:32:23 +0100 Subject: [PATCH 2/3] pm: Use new MPSL PM API Use the new MPSL PM API where event registration and low latency request are handled separately. Signed-off-by: Knut Eldhuset (cherry picked from commit 233a9e7006af441e368a7ea947f33e5ddeb898e5) --- subsys/mpsl/pm/mpsl_pm_utils.c | 40 ++-- tests/subsys/mpsl/pm/pm_test.c | 333 ++++++++++++++------------------- 2 files changed, 167 insertions(+), 206 deletions(-) diff --git a/subsys/mpsl/pm/mpsl_pm_utils.c b/subsys/mpsl/pm/mpsl_pm_utils.c index 04a81bcfa4c9..0252c4207c41 100644 --- a/subsys/mpsl/pm/mpsl_pm_utils.c +++ b/subsys/mpsl/pm/mpsl_pm_utils.c @@ -41,7 +41,7 @@ static void m_update_latency_request(uint32_t lat_value_us) } } -void mpsl_pm_utils_work_handler(void) +void m_register_event(void) { mpsl_pm_params_t params = {0}; bool pm_param_valid = mpsl_pm_params_get(¶ms); @@ -58,8 +58,6 @@ void mpsl_pm_utils_work_handler(void) switch (params.event_state) { case MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT: { - /* No event scheduled, so set latency to restrict deepest sleep states*/ - m_update_latency_request(PM_MAX_LATENCY_HCI_COMMANDS_US); if (m_pm_event_is_registered) { pm_policy_event_unregister(&m_evt); m_pm_event_is_registered = false; @@ -68,9 +66,6 @@ void mpsl_pm_utils_work_handler(void) } case MPSL_PM_EVENT_STATE_BEFORE_EVENT: { - /* In case we missed a state and are in zero-latency, set low-latency.*/ - m_update_latency_request(PM_MAX_LATENCY_HCI_COMMANDS_US); - /* Note: Considering an overflow could only happen if the system runs many years, * it needen't be considered here. */ @@ -107,17 +102,40 @@ void mpsl_pm_utils_work_handler(void) } break; } - case MPSL_PM_EVENT_STATE_IN_EVENT: - { - m_update_latency_request(0); - break; - } default: __ASSERT(false, "MPSL PM is in an undefined state."); } m_pm_prev_flag_value = params.cnt_flag; } +static void m_register_latency(void) +{ + switch (mpsl_pm_low_latency_state_get()) { + case MPSL_PM_LOW_LATENCY_STATE_OFF: + if (mpsl_pm_low_latency_requested()) { + mpsl_pm_low_latency_state_set(MPSL_PM_LOW_LATENCY_STATE_REQUESTING); + m_update_latency_request(0); + mpsl_pm_low_latency_state_set(MPSL_PM_LOW_LATENCY_STATE_ON); + } + break; + case MPSL_PM_LOW_LATENCY_STATE_ON: + if (!mpsl_pm_low_latency_requested()) { + mpsl_pm_low_latency_state_set(MPSL_PM_LOW_LATENCY_STATE_RELEASING); + m_update_latency_request(PM_MAX_LATENCY_HCI_COMMANDS_US); + mpsl_pm_low_latency_state_set(MPSL_PM_LOW_LATENCY_STATE_OFF); + } + break; + default: + break; + } +} + +void mpsl_pm_utils_work_handler(void) +{ + m_register_event(); + m_register_latency(); +} + static void m_work_handler(struct k_work *work) { ARG_UNUSED(work); diff --git a/tests/subsys/mpsl/pm/pm_test.c b/tests/subsys/mpsl/pm/pm_test.c index 0c9339abc522..2aec0285ba1a 100644 --- a/tests/subsys/mpsl/pm/pm_test.c +++ b/tests/subsys/mpsl/pm/pm_test.c @@ -41,233 +41,187 @@ typedef enum { typedef enum { LATENCY_FUNC_NONE, - LATENCY_FUNC_REGISTER, LATENCY_FUNC_UPDATE, } latency_func_t; typedef struct { - bool new_test; bool pm_params_get_retval; mpsl_pm_params_t params; event_func_t event_func; uint64_t event_time_us; - latency_func_t latency_func; - uint64_t latency_us; int64_t curr_time_ms; -} test_vector_t; +} test_vector_event_t; + +typedef struct { + latency_func_t latency_func; + mpsl_pm_low_latency_state_t low_latency_state_prev; + bool low_latency_requested; + mpsl_pm_low_latency_state_t low_latency_state_transition; + mpsl_pm_low_latency_state_t low_latency_state_next; +} test_vector_latency_t; -void run_test(test_vector_t *p_test_vectors, int num_test_vctr) +void run_test(test_vector_event_t *p_test_vectors, int num_test_vctr) { + mpsl_pm_params_t pm_params_initial = {0}; + + resetTest(); /* Verify expectations until now. */ + __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(); + for (int i = 0; i < num_test_vctr; i++) { - test_vector_t v = p_test_vectors[i]; - - if (v.new_test) { - resetTest(); /* Verify expectations until now. */ - __cmock_pm_policy_latency_request_add_Expect(0, v.latency_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(&v.params); - - mpsl_pm_utils_init(); - } else { - __cmock_mpsl_pm_params_get_ExpectAnyArgsAndReturn(v.pm_params_get_retval); - __cmock_mpsl_pm_params_get_ReturnThruPtr_p_params(&v.params); - - switch (v.event_func) { - case EVENT_FUNC_REGISTER: - __cmock_k_uptime_get_ExpectAndReturn(v.curr_time_ms); - __cmock_pm_policy_event_register_Expect(0, v.event_time_us); - __cmock_pm_policy_event_register_IgnoreArg_evt(); - break; - case EVENT_FUNC_UPDATE: - __cmock_k_uptime_get_ExpectAndReturn(v.curr_time_ms); - __cmock_pm_policy_event_update_Expect(0, v.event_time_us); - __cmock_pm_policy_event_update_IgnoreArg_evt(); - break; - case EVENT_FUNC_UNREGISTER: - __cmock_pm_policy_event_unregister_ExpectAnyArgs(); - break; - case EVENT_FUNC_DELAY_SCHEDULING: - __cmock_k_uptime_get_ExpectAndReturn(v.curr_time_ms); - __cmock_K_USEC_ExpectAndReturn( - v.event_time_us, (k_timeout_t){v.event_time_us + 100}); - __cmock_mpsl_work_schedule_Expect( - 0, (k_timeout_t){v.event_time_us + 100}); - __cmock_mpsl_work_schedule_IgnoreArg_dwork(); - break; - case EVENT_FUNC_NONE: - break; - } - switch (v.latency_func) { - case LATENCY_FUNC_REGISTER: - __cmock_pm_policy_latency_request_add_Expect(0, v.latency_us); - __cmock_pm_policy_latency_request_add_IgnoreArg_req(); - break; - case LATENCY_FUNC_UPDATE: - __cmock_pm_policy_latency_request_update_Expect(0, v.latency_us); - __cmock_pm_policy_latency_request_update_IgnoreArg_req(); - break; - case LATENCY_FUNC_NONE: - break; - } - mpsl_pm_utils_work_handler(); + test_vector_event_t v = p_test_vectors[i]; + + __cmock_mpsl_pm_params_get_ExpectAnyArgsAndReturn(v.pm_params_get_retval); + __cmock_mpsl_pm_params_get_ReturnThruPtr_p_params(&v.params); + + __cmock_mpsl_pm_low_latency_state_get_IgnoreAndReturn( + MPSL_PM_LOW_LATENCY_STATE_OFF); + __cmock_mpsl_pm_low_latency_requested_IgnoreAndReturn(false); + + switch (v.event_func) { + case EVENT_FUNC_REGISTER: + __cmock_k_uptime_get_ExpectAndReturn(v.curr_time_ms); + __cmock_pm_policy_event_register_Expect(0, v.event_time_us); + __cmock_pm_policy_event_register_IgnoreArg_evt(); + break; + case EVENT_FUNC_UPDATE: + __cmock_k_uptime_get_ExpectAndReturn(v.curr_time_ms); + __cmock_pm_policy_event_update_Expect(0, v.event_time_us); + __cmock_pm_policy_event_update_IgnoreArg_evt(); + break; + case EVENT_FUNC_UNREGISTER: + __cmock_pm_policy_event_unregister_ExpectAnyArgs(); + break; + case EVENT_FUNC_DELAY_SCHEDULING: + __cmock_k_uptime_get_ExpectAndReturn(v.curr_time_ms); + __cmock_K_USEC_ExpectAndReturn( + v.event_time_us, (k_timeout_t){v.event_time_us + 100}); + __cmock_mpsl_work_schedule_Expect( + 0, (k_timeout_t){v.event_time_us + 100}); + __cmock_mpsl_work_schedule_IgnoreArg_dwork(); + break; + case EVENT_FUNC_NONE: + break; } + mpsl_pm_utils_work_handler(); + } +} + +void run_test_latency(test_vector_latency_t *p_test_vectors, int num_test_vctr) +{ + mpsl_pm_params_t pm_params = {0}; + + resetTest(); /* Verify expectations until now. */ + __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); + + mpsl_pm_utils_init(); + + for (int i = 0; i < num_test_vctr; i++) { + test_vector_latency_t v = p_test_vectors[i]; + + __cmock_mpsl_pm_params_get_ExpectAnyArgsAndReturn(true); + __cmock_mpsl_pm_params_get_ReturnThruPtr_p_params(&pm_params); + + __cmock_mpsl_pm_low_latency_state_get_ExpectAndReturn(v.low_latency_state_prev); + + switch (v.latency_func) { + case LATENCY_FUNC_UPDATE: + __cmock_mpsl_pm_low_latency_requested_ExpectAndReturn( + v.low_latency_requested); + __cmock_pm_policy_latency_request_update_Expect( + 0, v.low_latency_requested ? 0 : PM_MAX_LATENCY_HCI_COMMANDS_US); + __cmock_pm_policy_latency_request_update_IgnoreArg_req(); + __cmock_mpsl_pm_low_latency_state_set_Expect( + v.low_latency_state_transition); + __cmock_mpsl_pm_low_latency_state_set_Expect(v.low_latency_state_next); + break; + case LATENCY_FUNC_NONE: + __cmock_mpsl_pm_low_latency_requested_ExpectAndReturn( + v.low_latency_requested); + break; + } + mpsl_pm_utils_work_handler(); } } void test_init_only(void) { - test_vector_t test_vectors[] = { - {true, false, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 0}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_REGISTER, PM_MAX_LATENCY_HCI_COMMANDS_US, 0}, - }; - run_test(&test_vectors[0], ARRAY_SIZE(test_vectors)); + run_test(NULL, 0); } void test_no_events(void) { - test_vector_t test_vectors[] = { + test_vector_event_t test_vectors[] = { /* Init then no events*/ - {true, false, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 0}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_REGISTER, PM_MAX_LATENCY_HCI_COMMANDS_US, 0}, - {false, false, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 0}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_NONE, 0, 0}, + {false, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 0}, + EVENT_FUNC_NONE, 0, 0}, }; run_test(&test_vectors[0], ARRAY_SIZE(test_vectors)); } void test_high_prio_changed_params(void) { - test_vector_t test_vectors[] = { - /* Init. */ - {true, false, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 0}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_REGISTER, PM_MAX_LATENCY_HCI_COMMANDS_US, 0}, + test_vector_event_t test_vectors[] = { /* Pretend high prio changed parameters while we read them. */ - {false, false, {10000, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 1}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_NONE, 0, 0}, + {false, {10000, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 1}, + EVENT_FUNC_NONE, 0, 0}, }; run_test(&test_vectors[0], ARRAY_SIZE(test_vectors)); } void test_latency_request(void) { - test_vector_t test_vectors[] = { - /* Init. */ - {true, false, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 0}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_REGISTER, PM_MAX_LATENCY_HCI_COMMANDS_US, 0}, - /* Check low-latency is set. */ - {false, true, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 1}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_NONE, 0, 0}, - /* Set zero-latency. */ - {false, true, {0, MPSL_PM_EVENT_STATE_IN_EVENT, 2}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_UPDATE, 0, 0}, - /* Set low-latency. */ - {false, true, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 3}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_UPDATE, PM_MAX_LATENCY_HCI_COMMANDS_US, 0}, + test_vector_latency_t test_vectors[] = { + {LATENCY_FUNC_NONE, MPSL_PM_LOW_LATENCY_STATE_OFF, false, + MPSL_PM_LOW_LATENCY_STATE_OFF, MPSL_PM_LOW_LATENCY_STATE_OFF}, + {LATENCY_FUNC_UPDATE, MPSL_PM_LOW_LATENCY_STATE_OFF, true, + MPSL_PM_LOW_LATENCY_STATE_REQUESTING, MPSL_PM_LOW_LATENCY_STATE_ON}, + {LATENCY_FUNC_NONE, MPSL_PM_LOW_LATENCY_STATE_ON, true, + MPSL_PM_LOW_LATENCY_STATE_ON, MPSL_PM_LOW_LATENCY_STATE_ON}, + {LATENCY_FUNC_UPDATE, MPSL_PM_LOW_LATENCY_STATE_ON, false, + MPSL_PM_LOW_LATENCY_STATE_RELEASING, MPSL_PM_LOW_LATENCY_STATE_OFF}, }; - run_test(&test_vectors[0], ARRAY_SIZE(test_vectors)); + run_test_latency(&test_vectors[0], ARRAY_SIZE(test_vectors)); } -void test_register_and_derigster_event(void) +void test_register_and_deregister_event(void) { - test_vector_t test_vectors[] = { - /* Init. */ - {true, false, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 0}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_REGISTER, PM_MAX_LATENCY_HCI_COMMANDS_US, 0}, + test_vector_event_t test_vectors[] = { /* Register event. */ - {false, true, {10000, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 1}, - EVENT_FUNC_REGISTER, 10000, - LATENCY_FUNC_NONE, 0, 0}, - /* Deregister event. */ - {false, true, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 2}, - EVENT_FUNC_UNREGISTER, 0, - LATENCY_FUNC_NONE, 0, 0}, - }; - run_test(&test_vectors[0], ARRAY_SIZE(test_vectors)); -} - -void test_register_enter_and_derigster_event(void) -{ - test_vector_t test_vectors[] = { - /* Init. */ - {true, false, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 0}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_REGISTER, PM_MAX_LATENCY_HCI_COMMANDS_US, 0}, - /* Register event. */ - {false, true, {10000, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 1}, - EVENT_FUNC_REGISTER, 10000, - LATENCY_FUNC_NONE, 0, 0}, - /* Pretend to be in event */ - {false, true, {0, MPSL_PM_EVENT_STATE_IN_EVENT, 2}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_UPDATE, 0, 0}, + {true, {10000, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 1}, + EVENT_FUNC_REGISTER, 10000, 0}, /* Deregister event. */ - {false, true, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 3}, - EVENT_FUNC_UNREGISTER, 0, - LATENCY_FUNC_UPDATE, PM_MAX_LATENCY_HCI_COMMANDS_US, 0}, + {true, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 2}, + EVENT_FUNC_UNREGISTER, 0, 0}, }; run_test(&test_vectors[0], ARRAY_SIZE(test_vectors)); } -void test_register_update_enter_and_deregister_event(void) +void test_register_update_and_deregister_event(void) { - test_vector_t test_vectors[] = { - /* Init. */ - {true, false, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 0}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_REGISTER, PM_MAX_LATENCY_HCI_COMMANDS_US, 0}, + test_vector_event_t test_vectors[] = { /* Register event. */ - {false, true, {10000, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 1}, - EVENT_FUNC_REGISTER, 10000, - LATENCY_FUNC_NONE, 0, 0}, + {true, {10000, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 1}, + EVENT_FUNC_REGISTER, 10000, 0}, /* Update event. */ - {false, true, {15000, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 2}, - EVENT_FUNC_UPDATE, 15000, - LATENCY_FUNC_NONE, 0, 0}, - /* Pretend to be in event */ - {false, true, {0, MPSL_PM_EVENT_STATE_IN_EVENT, 3}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_UPDATE, 0, 0}, + {true, {15000, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 2}, + EVENT_FUNC_UPDATE, 15000, 0}, /* Deregister event. */ - {false, true, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 4}, - EVENT_FUNC_UNREGISTER, 0, - LATENCY_FUNC_UPDATE, PM_MAX_LATENCY_HCI_COMMANDS_US, 0}, - }; - run_test(&test_vectors[0], ARRAY_SIZE(test_vectors)); -} - -void test_register_enter_and_update_event(void) -{ - test_vector_t test_vectors[] = { - /* Init. */ - {true, false, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 0}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_REGISTER, PM_MAX_LATENCY_HCI_COMMANDS_US, 0}, - /* Register event. */ - {false, true, {10000, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 1}, - EVENT_FUNC_REGISTER, 10000, - LATENCY_FUNC_NONE, 0, 0}, - /* Pretend to be in event */ - {false, true, {0, MPSL_PM_EVENT_STATE_IN_EVENT, 2}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_UPDATE, 0, 0}, - /* Update event (before we get the state no events left). */ - {false, true, {15000, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 3}, - EVENT_FUNC_UPDATE, 15000, - LATENCY_FUNC_UPDATE, PM_MAX_LATENCY_HCI_COMMANDS_US, 0}, + {true, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 3}, + EVENT_FUNC_UNREGISTER, 0, 0}, }; run_test(&test_vectors[0], ARRAY_SIZE(test_vectors)); } @@ -278,29 +232,18 @@ void test_event_delayed_work(void) /* Make sure time until event will be more than UINT32_MAX cycles away. */ TEST_ASSERT_GREATER_THAN_INT64(UINT32_MAX, k_us_to_cyc_floor64(event_time_us)); - test_vector_t test_vectors[] = { - /* Init. */ - {true, false, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 0}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_REGISTER, PM_MAX_LATENCY_HCI_COMMANDS_US}, + test_vector_event_t test_vectors[] = { /* Event time after 32 bit cycles have wrapped, so schedule retry. */ - {false, true, {event_time_us, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 1}, - EVENT_FUNC_DELAY_SCHEDULING, event_time_us - 1000, - LATENCY_FUNC_NONE, 0, 0}, + {true, {event_time_us, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 1}, + EVENT_FUNC_DELAY_SCHEDULING, event_time_us - 1000, 0}, /* Time has progressed until cycles will no longer wrap, * so register latency normally. */ - {false, true, {event_time_us, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 2}, - EVENT_FUNC_REGISTER, event_time_us, - LATENCY_FUNC_NONE, 0, 100}, - /* Pretend to be in event */ - {false, true, {0, MPSL_PM_EVENT_STATE_IN_EVENT, 3}, - EVENT_FUNC_NONE, 0, - LATENCY_FUNC_UPDATE, 0, 0}, + {true, {event_time_us, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 2}, + EVENT_FUNC_REGISTER, event_time_us, 100}, /* Deregister event. */ - {false, true, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 4}, - EVENT_FUNC_UNREGISTER, 0, - LATENCY_FUNC_UPDATE, PM_MAX_LATENCY_HCI_COMMANDS_US, 0}, + {true, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 3}, + EVENT_FUNC_UNREGISTER, 0, 0}, }; run_test(&test_vectors[0], ARRAY_SIZE(test_vectors)); } From f6f0fbd8fbb88b13dbf2986d14ebc09b765fd96d Mon Sep 17 00:00:00 2001 From: Knut Eldhuset Date: Tue, 4 Feb 2025 09:13:22 +0100 Subject: [PATCH 3/3] pm: Fix to use abs time with policy event funcs Update pm policy event usage after API was changed from using relative time in cycles to absolute time in ticks. Signed-off-by: Knut Eldhuset (cherry picked from commit f320b75e93ccb71ecc8da188fb88420af748421b) --- subsys/mpsl/pm/mpsl_pm_utils.c | 39 ++------------------- tests/subsys/mpsl/pm/CMakeLists.txt | 6 ---- tests/subsys/mpsl/pm/kernel_minimal_mock.h | 25 -------------- tests/subsys/mpsl/pm/pm_test.c | 40 ---------------------- tests/subsys/mpsl/pm/prj.conf | 1 + 5 files changed, 3 insertions(+), 108 deletions(-) delete mode 100644 tests/subsys/mpsl/pm/kernel_minimal_mock.h diff --git a/subsys/mpsl/pm/mpsl_pm_utils.c b/subsys/mpsl/pm/mpsl_pm_utils.c index 0252c4207c41..b6f39ec8d165 100644 --- a/subsys/mpsl/pm/mpsl_pm_utils.c +++ b/subsys/mpsl/pm/mpsl_pm_utils.c @@ -10,7 +10,6 @@ #include #include -#include #include LOG_MODULE_REGISTER(mpsl_pm_utils, CONFIG_MPSL_LOG_LEVEL); @@ -23,9 +22,6 @@ 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(pm_work, m_work_handler); - static uint8_t m_pm_prev_flag_value; static bool m_pm_event_is_registered; static uint32_t m_prev_lat_value_us; @@ -66,38 +62,13 @@ void m_register_event(void) } case MPSL_PM_EVENT_STATE_BEFORE_EVENT: { - /* Note: Considering an overflow could only happen if the system runs many years, - * it needen't be considered here. - */ - int64_t current_time_us = k_uptime_get() * 1000; - uint64_t relative_time_us = params.event_time_abs_us - current_time_us; - uint64_t max_cycles_until_event = k_us_to_cyc_floor64(relative_time_us); - - if (max_cycles_until_event > UINT32_MAX) { - /* The event is too far in the future and would - * exceed the 32-bit cycle limit. - */ - uint64_t event_delay_us = params.event_time_abs_us - current_time_us - - TIME_TO_REGISTER_EVENT_IN_ZEPHYR_US; -#ifdef CONFIG_TIMEOUT_64BIT - mpsl_work_schedule(&pm_work, K_USEC(event_delay_us)); -#else - if (event_delay_us > UINT32_MAX) { - mpsl_work_schedule(&pm_work, K_USEC(UINT32_MAX)); - } else { - mpsl_work_schedule(&pm_work, K_USEC((uint32_t)event_delay_us)); - } -#endif - return; - } - /* Event scheduled */ if (m_pm_event_is_registered) { pm_policy_event_update(&m_evt, - k_us_to_cyc_floor32(params.event_time_abs_us)); + k_us_to_ticks_floor64(params.event_time_abs_us)); } else { pm_policy_event_register(&m_evt, - k_us_to_cyc_floor32(params.event_time_abs_us)); + k_us_to_ticks_floor64(params.event_time_abs_us)); m_pm_event_is_registered = true; } break; @@ -136,12 +107,6 @@ void mpsl_pm_utils_work_handler(void) m_register_latency(); } -static void m_work_handler(struct k_work *work) -{ - ARG_UNUSED(work); - mpsl_pm_utils_work_handler(); -} - void mpsl_pm_utils_init(void) { mpsl_pm_params_t params = {0}; diff --git a/tests/subsys/mpsl/pm/CMakeLists.txt b/tests/subsys/mpsl/pm/CMakeLists.txt index 3820538a402b..1903f9f8c715 100644 --- a/tests/subsys/mpsl/pm/CMakeLists.txt +++ b/tests/subsys/mpsl/pm/CMakeLists.txt @@ -13,11 +13,9 @@ 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) @@ -28,10 +26,6 @@ target_sources(app PRIVATE pm_test.c) # Include paths target_include_directories(app PRIVATE src) -# Preinclude file to the UUT to redefine mpsl_work_schedule(). -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 -DCONFIG_PM=y diff --git a/tests/subsys/mpsl/pm/kernel_minimal_mock.h b/tests/subsys/mpsl/pm/kernel_minimal_mock.h deleted file mode 100644 index 9377de21d5ae..000000000000 --- a/tests/subsys/mpsl/pm/kernel_minimal_mock.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 -struct k_work { -}; -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) -k_timeout_t K_USEC(uint64_t d); -int64_t k_uptime_get(void); -#endif diff --git a/tests/subsys/mpsl/pm/pm_test.c b/tests/subsys/mpsl/pm/pm_test.c index 2aec0285ba1a..fda2c50846c5 100644 --- a/tests/subsys/mpsl/pm/pm_test.c +++ b/tests/subsys/mpsl/pm/pm_test.c @@ -13,18 +13,11 @@ #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 #define PM_MAX_LATENCY_HCI_COMMANDS_US 499999 -#define TIME_TO_REGISTER_EVENT_IN_ZEPHYR_US 1000 - -/* Mock implementation for mpsl_work_q*/ -struct k_work_q mpsl_work_q; - /* The unity_main is not declared in any header file. It is only defined in the generated test * runner because of ncs' unity configuration. It is therefore declared here to avoid a compiler * warning. @@ -36,7 +29,6 @@ typedef enum { EVENT_FUNC_REGISTER, EVENT_FUNC_UPDATE, EVENT_FUNC_UNREGISTER, - EVENT_FUNC_DELAY_SCHEDULING, } event_func_t; typedef enum { @@ -87,26 +79,16 @@ void run_test(test_vector_event_t *p_test_vectors, int num_test_vctr) switch (v.event_func) { case EVENT_FUNC_REGISTER: - __cmock_k_uptime_get_ExpectAndReturn(v.curr_time_ms); __cmock_pm_policy_event_register_Expect(0, v.event_time_us); __cmock_pm_policy_event_register_IgnoreArg_evt(); break; case EVENT_FUNC_UPDATE: - __cmock_k_uptime_get_ExpectAndReturn(v.curr_time_ms); __cmock_pm_policy_event_update_Expect(0, v.event_time_us); __cmock_pm_policy_event_update_IgnoreArg_evt(); break; case EVENT_FUNC_UNREGISTER: __cmock_pm_policy_event_unregister_ExpectAnyArgs(); break; - case EVENT_FUNC_DELAY_SCHEDULING: - __cmock_k_uptime_get_ExpectAndReturn(v.curr_time_ms); - __cmock_K_USEC_ExpectAndReturn( - v.event_time_us, (k_timeout_t){v.event_time_us + 100}); - __cmock_mpsl_work_schedule_Expect( - 0, (k_timeout_t){v.event_time_us + 100}); - __cmock_mpsl_work_schedule_IgnoreArg_dwork(); - break; case EVENT_FUNC_NONE: break; } @@ -226,28 +208,6 @@ void test_register_update_and_deregister_event(void) run_test(&test_vectors[0], ARRAY_SIZE(test_vectors)); } -void test_event_delayed_work(void) -{ - uint64_t event_time_us = (uint64_t)UINT32_MAX + 50000; - /* Make sure time until event will be more than UINT32_MAX cycles away. */ - TEST_ASSERT_GREATER_THAN_INT64(UINT32_MAX, k_us_to_cyc_floor64(event_time_us)); - - test_vector_event_t test_vectors[] = { - /* Event time after 32 bit cycles have wrapped, so schedule retry. */ - {true, {event_time_us, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 1}, - EVENT_FUNC_DELAY_SCHEDULING, event_time_us - 1000, 0}, - /* Time has progressed until cycles will no longer wrap, - * so register latency normally. - */ - {true, {event_time_us, MPSL_PM_EVENT_STATE_BEFORE_EVENT, 2}, - EVENT_FUNC_REGISTER, event_time_us, 100}, - /* Deregister event. */ - {true, {0, MPSL_PM_EVENT_STATE_NO_EVENTS_LEFT, 3}, - EVENT_FUNC_UNREGISTER, 0, 0}, - }; - run_test(&test_vectors[0], ARRAY_SIZE(test_vectors)); -} - int main(void) { (void)unity_main(); diff --git a/tests/subsys/mpsl/pm/prj.conf b/tests/subsys/mpsl/pm/prj.conf index c4750ff9ae70..a9e2ef112386 100644 --- a/tests/subsys/mpsl/pm/prj.conf +++ b/tests/subsys/mpsl/pm/prj.conf @@ -5,3 +5,4 @@ # CONFIG_UNITY=y +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000000