From 3d4273d0aaeb43fd0545bdfb76c9e3c19ef78e21 Mon Sep 17 00:00:00 2001 From: Knut Eldhuset Date: Wed, 4 Dec 2024 12:32:23 +0100 Subject: [PATCH] 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 --- subsys/mpsl/pm/mpsl_pm_utils.c | 39 ++-- tests/subsys/mpsl/pm/pm_test.c | 315 ++++++++++++++------------------- 2 files changed, 157 insertions(+), 197 deletions(-) diff --git a/subsys/mpsl/pm/mpsl_pm_utils.c b/subsys/mpsl/pm/mpsl_pm_utils.c index 04a81bcfa4c9..532db063ccf0 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,15 +102,37 @@ 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; + mpsl_pm_event_registered_ack(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()) { + 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()) { + 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) diff --git a/tests/subsys/mpsl/pm/pm_test.c b/tests/subsys/mpsl/pm/pm_test.c index 0c9339abc522..a5f8a6d97d5d 100644 --- a/tests/subsys/mpsl/pm/pm_test.c +++ b/tests/subsys/mpsl/pm/pm_test.c @@ -41,103 +41,133 @@ 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; +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_next; +} test_vector_latency_t; + void run_test(test_vector_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(); + __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(); + __cmock_mpsl_pm_event_registered_ack_Expect(v.params.cnt_flag); + 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(); + __cmock_mpsl_pm_event_registered_ack_Expect(v.params.cnt_flag); + break; + case EVENT_FUNC_UNREGISTER: + __cmock_pm_policy_event_unregister_ExpectAnyArgs(); + __cmock_mpsl_pm_event_registered_ack_Expect(v.params.cnt_flag); + 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_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[] = { /* 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)); } @@ -145,129 +175,53 @@ void test_no_events(void) 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}, /* 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}, + {LATENCY_FUNC_UPDATE, MPSL_PM_LOW_LATENCY_STATE_OFF, true, + MPSL_PM_LOW_LATENCY_STATE_ON}, + {LATENCY_FUNC_NONE, MPSL_PM_LOW_LATENCY_STATE_ON, true, + MPSL_PM_LOW_LATENCY_STATE_ON}, + {LATENCY_FUNC_UPDATE, MPSL_PM_LOW_LATENCY_STATE_ON, false, + 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}, /* 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}, /* 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)); } @@ -279,28 +233,17 @@ void test_event_delayed_work(void) 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}, /* 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)); }