tests: pm: device_runtime_api: Extend with synchronous device
Extended test to support case when PM device is defined as synchronous. Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
25173f71cd
commit
5ce4348311
8
tests/subsys/pm/device_runtime_api/Kconfig
Normal file
8
tests/subsys/pm/device_runtime_api/Kconfig
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright 2024 Nordic Semiconductor ASA
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
source "Kconfig.zephyr"
|
||||
|
||||
config TEST_PM_DEVICE_ISR_SAFE
|
||||
bool "Use ISR safe PM for the test"
|
|
@ -141,105 +141,111 @@ ZTEST(device_runtime_api, test_api)
|
|||
ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
|
||||
zassert_equal(ret, 0);
|
||||
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
|
||||
if (IS_ENABLED(CONFIG_TEST_PM_DEVICE_ISR_SAFE)) {
|
||||
/* In sync mode async put is equivalent as normal put. */
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);
|
||||
} else {
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
|
||||
|
||||
/* usage: 0, -1, suspend: no (unbalanced call) */
|
||||
ret = pm_device_runtime_put(test_dev);
|
||||
zassert_equal(ret, -EALREADY);
|
||||
/* usage: 0, -1, suspend: no (unbalanced call) */
|
||||
ret = pm_device_runtime_put(test_dev);
|
||||
zassert_equal(ret, -EALREADY);
|
||||
|
||||
/* usage: 0, -1, suspend: no (unbalanced call) */
|
||||
ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
|
||||
zassert_equal(ret, -EALREADY);
|
||||
/* usage: 0, -1, suspend: no (unbalanced call) */
|
||||
ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
|
||||
zassert_equal(ret, -EALREADY);
|
||||
|
||||
/* unblock test driver and let it finish */
|
||||
test_driver_pm_done(test_dev);
|
||||
k_yield();
|
||||
/* unblock test driver and let it finish */
|
||||
test_driver_pm_done(test_dev);
|
||||
k_yield();
|
||||
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);
|
||||
|
||||
/*** get + asynchronous put + get (while suspend still ongoing) ***/
|
||||
/*** get + asynchronous put + get (while suspend still ongoing) ***/
|
||||
|
||||
/* usage: 0, +1, resume: yes */
|
||||
ret = pm_device_runtime_get(test_dev);
|
||||
zassert_equal(ret, 0);
|
||||
/* usage: 0, +1, resume: yes */
|
||||
ret = pm_device_runtime_get(test_dev);
|
||||
zassert_equal(ret, 0);
|
||||
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_ACTIVE);
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_ACTIVE);
|
||||
|
||||
test_driver_pm_async(test_dev);
|
||||
test_driver_pm_async(test_dev);
|
||||
|
||||
/* usage: 1, -1, suspend: yes (queued) */
|
||||
ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
|
||||
zassert_equal(ret, 0);
|
||||
/* usage: 1, -1, suspend: yes (queued) */
|
||||
ret = pm_device_runtime_put_async(test_dev, K_NO_WAIT);
|
||||
zassert_equal(ret, 0);
|
||||
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
|
||||
|
||||
/* let suspension start */
|
||||
k_yield();
|
||||
/* let suspension start */
|
||||
k_yield();
|
||||
|
||||
/* create and start get_runner thread
|
||||
* get_runner thread is used to test synchronous path while asynchronous
|
||||
* is ongoing. It is important to set its priority >= to the system work
|
||||
* queue to make sure sync path run by the thread is forced to wait.
|
||||
*/
|
||||
k_thread_create(&get_runner_td, get_runner_stack,
|
||||
K_THREAD_STACK_SIZEOF(get_runner_stack), get_runner,
|
||||
NULL, NULL, NULL, CONFIG_SYSTEM_WORKQUEUE_PRIORITY, 0,
|
||||
K_NO_WAIT);
|
||||
k_yield();
|
||||
/* create and start get_runner thread
|
||||
* get_runner thread is used to test synchronous path while asynchronous
|
||||
* is ongoing. It is important to set its priority >= to the system work
|
||||
* queue to make sure sync path run by the thread is forced to wait.
|
||||
*/
|
||||
k_thread_create(&get_runner_td, get_runner_stack,
|
||||
K_THREAD_STACK_SIZEOF(get_runner_stack), get_runner,
|
||||
NULL, NULL, NULL, CONFIG_SYSTEM_WORKQUEUE_PRIORITY, 0,
|
||||
K_NO_WAIT);
|
||||
k_yield();
|
||||
|
||||
/* let driver suspend to finish and wait until get_runner finishes
|
||||
* resuming the driver
|
||||
*/
|
||||
test_driver_pm_done(test_dev);
|
||||
k_thread_join(&get_runner_td, K_FOREVER);
|
||||
/* let driver suspend to finish and wait until get_runner finishes
|
||||
* resuming the driver
|
||||
*/
|
||||
test_driver_pm_done(test_dev);
|
||||
k_thread_join(&get_runner_td, K_FOREVER);
|
||||
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_ACTIVE);
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_ACTIVE);
|
||||
|
||||
/* Test if getting a device before an async operation starts does
|
||||
* not trigger any device pm action.
|
||||
*/
|
||||
size_t count = test_driver_pm_count(test_dev);
|
||||
/* Test if getting a device before an async operation starts does
|
||||
* not trigger any device pm action.
|
||||
*/
|
||||
size_t count = test_driver_pm_count(test_dev);
|
||||
|
||||
ret = pm_device_runtime_put_async(test_dev, K_MSEC(10));
|
||||
zassert_equal(ret, 0);
|
||||
ret = pm_device_runtime_put_async(test_dev, K_MSEC(10));
|
||||
zassert_equal(ret, 0);
|
||||
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
|
||||
|
||||
ret = pm_device_runtime_get(test_dev);
|
||||
zassert_equal(ret, 0);
|
||||
ret = pm_device_runtime_get(test_dev);
|
||||
zassert_equal(ret, 0);
|
||||
|
||||
/* Now lets check if the calls above have triggered a device
|
||||
* pm action
|
||||
*/
|
||||
zassert_equal(count, test_driver_pm_count(test_dev));
|
||||
/* Now lets check if the calls above have triggered a device
|
||||
* pm action
|
||||
*/
|
||||
zassert_equal(count, test_driver_pm_count(test_dev));
|
||||
|
||||
/*
|
||||
* test if async put with a delay respects the given time.
|
||||
*/
|
||||
ret = pm_device_runtime_put_async(test_dev, K_MSEC(100));
|
||||
/*
|
||||
* test if async put with a delay respects the given time.
|
||||
*/
|
||||
ret = pm_device_runtime_put_async(test_dev, K_MSEC(100));
|
||||
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
|
||||
|
||||
k_sleep(K_MSEC(80));
|
||||
k_sleep(K_MSEC(80));
|
||||
|
||||
/* It should still be suspending since we have waited less than
|
||||
* the delay we've set.
|
||||
*/
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
|
||||
/* It should still be suspending since we have waited less than
|
||||
* the delay we've set.
|
||||
*/
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDING);
|
||||
|
||||
k_sleep(K_MSEC(30));
|
||||
k_sleep(K_MSEC(30));
|
||||
|
||||
/* Now it should be already suspended */
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);
|
||||
/* Now it should be already suspended */
|
||||
(void)pm_device_state_get(test_dev, &state);
|
||||
zassert_equal(state, PM_DEVICE_STATE_SUSPENDED);
|
||||
}
|
||||
|
||||
/* Put operation should fail due the state be locked. */
|
||||
ret = pm_device_runtime_disable(test_dev);
|
||||
|
|
|
@ -21,15 +21,17 @@ static int test_driver_action(const struct device *dev,
|
|||
{
|
||||
struct test_driver_data *data = dev->data;
|
||||
|
||||
data->ongoing = true;
|
||||
if (!IS_ENABLED(CONFIG_TEST_PM_DEVICE_ISR_SAFE)) {
|
||||
data->ongoing = true;
|
||||
|
||||
if (data->async) {
|
||||
k_sem_take(&data->sync, K_FOREVER);
|
||||
data->async = false;
|
||||
if (data->async) {
|
||||
k_sem_take(&data->sync, K_FOREVER);
|
||||
data->async = false;
|
||||
}
|
||||
|
||||
data->ongoing = false;
|
||||
}
|
||||
|
||||
data->ongoing = false;
|
||||
|
||||
data->count++;
|
||||
|
||||
return 0;
|
||||
|
@ -72,7 +74,11 @@ int test_driver_init(const struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_TEST_PM_DEVICE_ISR_SAFE
|
||||
PM_DEVICE_ISR_SAFE_DEFINE(test_driver, test_driver_action);
|
||||
#else
|
||||
PM_DEVICE_DEFINE(test_driver, test_driver_action);
|
||||
#endif
|
||||
|
||||
static struct test_driver_data data;
|
||||
|
||||
|
|
|
@ -3,3 +3,9 @@ tests:
|
|||
tags: pm
|
||||
integration_platforms:
|
||||
- native_sim
|
||||
pm.device_runtime.isr_safe.api:
|
||||
tags: pm
|
||||
integration_platforms:
|
||||
- native_sim
|
||||
extra_configs:
|
||||
- CONFIG_TEST_PM_DEVICE_ISR_SAFE=y
|
||||
|
|
Loading…
Reference in a new issue