Skip to content

Commit 9985bb4

Browse files
henrikbrixandersenaescolar
authored andcommitted
tests: drivers: can: api: add power management test suite
Add test suite for verifying CAN controller power management behavior. The test suite verifies the behavior currently implemented in the TCAN4x5x CAN controller driver. The test suite serves only as a baseline. It is subject to change as power management support is implemented across a wider range of CAN controller/transceiver drivers. Signed-off-by: Henrik Brix Andersen <henrik@brixandersen.dk>
1 parent 9c2a081 commit 9985bb4

File tree

3 files changed

+138
-7
lines changed

3 files changed

+138
-7
lines changed

‎tests/drivers/can/api/CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ target_sources(app PRIVATE src/transceiver.c)
1010
target_sources(app PRIVATE src/utilities.c)
1111
target_sources_ifdef(CONFIG_CAN_FD_MODE app PRIVATE src/canfd.c)
1212
target_sources_ifdef(CONFIG_CAN_STATS app PRIVATE src/stats.c)
13+
target_sources_ifdef(CONFIG_PM_DEVICE app PRIVATE src/powermgmt.c)

‎tests/drivers/can/api/prj.conf‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@ CONFIG_CAN_MANUAL_RECOVERY_MODE=y
44
CONFIG_STATS=y
55
CONFIG_CAN_STATS=y
66
CONFIG_CAN_RX_TIMESTAMP=y
7+
CONFIG_PM_DEVICE=y
78
CONFIG_TEST_USERSPACE=y
89
CONFIG_ZTEST=y
9-
# Global default settings assign both the ZTest thread and the
10-
# system worker queue to the same cooperative priority. Relying
11-
# solely on the system worker queue for concurrency management
12-
# can lead to unwanted interference between the two threads,
13-
# causing the test to report its expected sequence of system
14-
# events as an error. This situation will be avoided by moving
15-
# the ZTest thread to the highest priority preemptive thread.
10+
# Global default settings assign both the ZTest thread and the system worker queue to the same
11+
# cooperative priority. Relying solely on the system worker queue for concurrency management can
12+
# lead to unwanted interference between the two threads, causing the test to report its expected
13+
# sequence of system events as an error. This situation will be avoided by moving the ZTest thread
14+
# to the highest priority preemptive thread.
1615
CONFIG_ZTEST_THREAD_PRIORITY=0
1716
# The canfd test suite may be skipped
1817
CONFIG_ZTEST_VERIFY_RUN_ALL=n
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright (c) 2026 Henrik Brix Andersen <henrik@brixandersen.dk>
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include <zephyr/drivers/can.h>
7+
#include <zephyr/pm/device.h>
8+
#include <zephyr/ztest.h>
9+
10+
#include "common.h"
11+
12+
/**
13+
* @addtogroup t_can_driver
14+
* @{
15+
* @defgroup t_can_powermgmt test_can_powermgmt
16+
* @}
17+
*/
18+
19+
/**
20+
* @brief Test suspending and resuming the CAN controller device.
21+
*/
22+
ZTEST(can_powermgmt, test_suspend_resume)
23+
{
24+
enum pm_device_state pm_state;
25+
struct can_frame frame;
26+
int filter_id;
27+
int err;
28+
29+
err = can_stop(can_dev);
30+
zassert_ok(err, "failed to stop CAN controller (err %d)", err);
31+
32+
err = pm_device_action_run(can_dev, PM_DEVICE_ACTION_SUSPEND);
33+
zassert_ok(err, "failed to suspend CAN controller (err %d)", err);
34+
35+
err = pm_device_state_get(can_dev, &pm_state);
36+
zassert_ok(err, "failed to get CAN controller power management state (err %d)", err);
37+
zassert_equal(pm_state, PM_DEVICE_STATE_SUSPENDED, "CAN controller not suspended (%s)",
38+
pm_device_state_str(pm_state));
39+
40+
err = pm_device_action_run(can_dev, PM_DEVICE_ACTION_RESUME);
41+
zassert_ok(err, "failed to resume CAN controller (err %d)", err);
42+
43+
err = pm_device_state_get(can_dev, &pm_state);
44+
zassert_ok(err, "failed to get CAN controller power management state (err %d)", err);
45+
zassert_equal(pm_state, PM_DEVICE_STATE_ACTIVE, "CAN controller not active (%s)",
46+
pm_device_state_str(pm_state));
47+
48+
err = can_set_mode(can_dev, CAN_MODE_LOOPBACK);
49+
zassert_ok(err, "failed to set loopback mode (err %d)", err);
50+
zassert_equal(CAN_MODE_LOOPBACK, can_get_mode(can_dev));
51+
52+
err = can_start(can_dev);
53+
zassert_ok(err, "failed to start CAN controller (err %d)", err);
54+
55+
filter_id = can_common_add_rx_msgq(can_dev, &test_std_filter_1);
56+
57+
err = can_send(can_dev, &test_std_frame_1, TEST_SEND_TIMEOUT, NULL, NULL);
58+
zassert_ok(err, "failed to send frame without data (err %d)", err);
59+
60+
err = k_msgq_get(&can_msgq, &frame, TEST_RECEIVE_TIMEOUT);
61+
zassert_ok(err, "receive timeout");
62+
63+
assert_frame_equal(&test_std_frame_1, &frame, 0);
64+
65+
can_remove_rx_filter(can_dev, filter_id);
66+
}
67+
68+
/**
69+
* @brief Test suspending the CAN controller device while started.
70+
*/
71+
ZTEST(can_powermgmt, test_suspend_while_started)
72+
{
73+
int err;
74+
75+
err = pm_device_action_run(can_dev, PM_DEVICE_ACTION_SUSPEND);
76+
zassert_equal(err, -EBUSY, "suspended CAN controller while started");
77+
}
78+
79+
/**
80+
* @brief Test suspending the CAN controller device while RX filters are added.
81+
*/
82+
ZTEST(can_powermgmt, test_suspend_while_filters_added)
83+
{
84+
int filter_id;
85+
int err;
86+
87+
err = can_stop(can_dev);
88+
zassert_ok(err, "failed to stop CAN controller (err %d)", err);
89+
90+
filter_id = can_add_rx_filter_msgq(can_dev, &can_msgq, &test_std_filter_1);
91+
zassert_not_equal(filter_id, -ENOSPC, "no filters available");
92+
zassert_true(filter_id >= 0, "negative filter number");
93+
94+
err = pm_device_action_run(can_dev, PM_DEVICE_ACTION_SUSPEND);
95+
zassert_equal(err, -EBUSY, "suspended CAN controller while RX filters added");
96+
97+
can_remove_rx_filter(can_dev, filter_id);
98+
99+
err = can_start(can_dev);
100+
zassert_ok(err, "failed to start CAN controller (err %d)", err);
101+
}
102+
103+
static bool can_powermgmt_predicate(const void *state)
104+
{
105+
enum pm_device_state pm_state;
106+
int err;
107+
108+
ARG_UNUSED(state);
109+
110+
if (!device_is_ready(can_dev)) {
111+
TC_PRINT("CAN device not ready");
112+
return false;
113+
}
114+
115+
err = pm_device_state_get(can_dev, &pm_state);
116+
if (err == -ENOSYS) {
117+
TC_PRINT("CAN controller does not support device power management");
118+
return false;
119+
}
120+
121+
return true;
122+
}
123+
124+
void *can_powermgmt_setup(void)
125+
{
126+
can_common_test_setup(CAN_MODE_LOOPBACK);
127+
128+
return NULL;
129+
}
130+
131+
ZTEST_SUITE(can_powermgmt, can_powermgmt_predicate, can_powermgmt_setup, NULL, NULL, NULL);

0 commit comments

Comments
 (0)