1 /*
2 * Copyright (c) 2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/uart.h>
8 #include <zephyr/device.h>
9 #include <zephyr/pm/device.h>
10 #include <zephyr/ztest.h>
11
12 #define UART_NODE DT_NODELABEL(dut)
13 #define DISABLED_RX DT_PROP(UART_NODE, disable_rx)
14
polling_verify(const struct device * dev,bool is_async,bool active)15 static void polling_verify(const struct device *dev, bool is_async, bool active)
16 {
17 char c;
18 char outs[] = "abc";
19 int err;
20
21 if (DISABLED_RX || is_async) {
22 /* If no RX pin just run few poll outs to check that it does
23 * not hang.
24 */
25 for (int i = 0; i < ARRAY_SIZE(outs); i++) {
26 uart_poll_out(dev, outs[i]);
27 }
28
29 return;
30 }
31
32 err = uart_poll_in(dev, &c);
33 zassert_equal(err, -1);
34
35 for (int i = 0; i < ARRAY_SIZE(outs); i++) {
36 uart_poll_out(dev, outs[i]);
37 /* We need to wait until receiver gets the data. Receiver may have
38 * RX timeout so data is not received instantly.
39 */
40 k_busy_wait(5000);
41
42 if (active) {
43 err = uart_poll_in(dev, &c);
44 zassert_equal(err, 0, "Unexpected err: %d", err);
45 zassert_equal(c, outs[i]);
46 }
47
48 err = uart_poll_in(dev, &c);
49 zassert_equal(err, -1);
50 }
51 }
52
async_callback(const struct device * dev,struct uart_event * evt,void * ctx)53 static void async_callback(const struct device *dev, struct uart_event *evt, void *ctx)
54 {
55 bool *done = ctx;
56
57 switch (evt->type) {
58 case UART_TX_DONE:
59 *done = true;
60 break;
61 default:
62 break;
63 }
64 }
65
async_verify(const struct device * dev,bool active)66 static bool async_verify(const struct device *dev, bool active)
67 {
68 char txbuf[] = "test";
69 uint8_t rxbuf[32] = { 0 };
70 volatile bool tx_done = false;
71 int err;
72
73 err = uart_callback_set(dev, async_callback, (void *)&tx_done);
74 if (err == -ENOTSUP) {
75 return false;
76 }
77
78 if (!active) {
79 return true;
80 }
81
82 zassert_equal(err, 0, "Unexpected err: %d", err);
83
84 /* Wait a bit to ensure that polling transfer is already finished otherwise
85 * receiver might be enabled when there is an ongoing transfer and bytes
86 * will get corrupted.
87 */
88 k_busy_wait(1000);
89
90 if (!DISABLED_RX) {
91 err = uart_rx_enable(dev, rxbuf, sizeof(rxbuf), 1 * USEC_PER_MSEC);
92 zassert_equal(err, 0, "Unexpected err: %d", err);
93 }
94
95 err = uart_tx(dev, txbuf, sizeof(txbuf), 10 * USEC_PER_MSEC);
96 zassert_equal(err, 0, "Unexpected err: %d", err);
97
98 k_busy_wait(10000);
99
100 if (!DISABLED_RX) {
101 err = uart_rx_disable(dev);
102 zassert_true((err == 0) || (err == -EFAULT));
103
104 k_busy_wait(10000);
105
106 err = memcmp(txbuf, rxbuf, sizeof(txbuf));
107 zassert_equal(err, 0, "Unexpected err: %d", err);
108 }
109
110 zassert_true(tx_done);
111
112 return true;
113 }
114
communication_verify(const struct device * dev,bool active)115 static void communication_verify(const struct device *dev, bool active)
116 {
117 bool is_async = async_verify(dev, active);
118
119 polling_verify(dev, is_async, active);
120 }
121
122 #define state_verify(dev, exp_state) do {\
123 enum pm_device_state power_state; \
124 int error = pm_device_state_get(dev, &power_state); \
125 zassert_equal(error, 0, "Unexpected err: %d", error); \
126 zassert_equal(power_state, exp_state); \
127 } while (0)
128
action_run(const struct device * dev,enum pm_device_action action,int exp_err)129 static void action_run(const struct device *dev, enum pm_device_action action,
130 int exp_err)
131 {
132 int err;
133 enum pm_device_state prev_state, exp_state;
134
135 err = pm_device_state_get(dev, &prev_state);
136 zassert_equal(err, 0, "Unexpected err: %d", err);
137
138 err = pm_device_action_run(dev, action);
139 zassert_equal(err, exp_err, "Unexpected err: %d", err);
140
141 if (err == 0) {
142 switch (action) {
143 case PM_DEVICE_ACTION_SUSPEND:
144 exp_state = PM_DEVICE_STATE_SUSPENDED;
145 break;
146 case PM_DEVICE_ACTION_RESUME:
147 exp_state = PM_DEVICE_STATE_ACTIVE;
148 break;
149 default:
150 exp_state = prev_state;
151 break;
152 }
153 } else {
154 exp_state = prev_state;
155 }
156
157 state_verify(dev, exp_state);
158 }
159
ZTEST(uart_pm,test_uart_pm_in_idle)160 ZTEST(uart_pm, test_uart_pm_in_idle)
161 {
162 const struct device *dev;
163
164 dev = DEVICE_DT_GET(UART_NODE);
165 zassert_true(device_is_ready(dev), "uart device is not ready");
166
167 state_verify(dev, PM_DEVICE_STATE_ACTIVE);
168 communication_verify(dev, true);
169
170 action_run(dev, PM_DEVICE_ACTION_SUSPEND, 0);
171 communication_verify(dev, false);
172
173 action_run(dev, PM_DEVICE_ACTION_RESUME, 0);
174 communication_verify(dev, true);
175
176 action_run(dev, PM_DEVICE_ACTION_SUSPEND, 0);
177 communication_verify(dev, false);
178
179 action_run(dev, PM_DEVICE_ACTION_RESUME, 0);
180 communication_verify(dev, true);
181
182 /* Let's give enough time for the last byte to be transmitted out */
183 k_busy_wait(500);
184 }
185
ZTEST(uart_pm,test_uart_pm_poll_tx)186 ZTEST(uart_pm, test_uart_pm_poll_tx)
187 {
188 const struct device *dev;
189
190 dev = DEVICE_DT_GET(UART_NODE);
191 zassert_true(device_is_ready(dev), "uart device is not ready");
192
193 communication_verify(dev, true);
194
195 uart_poll_out(dev, 'a');
196 action_run(dev, PM_DEVICE_ACTION_SUSPEND, 0);
197
198 communication_verify(dev, false);
199
200 action_run(dev, PM_DEVICE_ACTION_RESUME, 0);
201
202 communication_verify(dev, true);
203
204 /* Now same thing but with callback */
205 uart_poll_out(dev, 'a');
206 action_run(dev, PM_DEVICE_ACTION_SUSPEND, 0);
207
208 communication_verify(dev, false);
209
210 action_run(dev, PM_DEVICE_ACTION_RESUME, 0);
211
212 communication_verify(dev, true);
213 }
214
work_handler(struct k_work * work)215 static void work_handler(struct k_work *work)
216 {
217 const struct device *dev = DEVICE_DT_GET(UART_NODE);
218
219 action_run(dev, PM_DEVICE_ACTION_SUSPEND, 0);
220 }
221
222 /* Test going into low power state after interrupting poll out. Use various
223 * delays to test interruption at multiple places.
224 */
ZTEST(uart_pm,test_uart_pm_poll_tx_interrupted)225 ZTEST(uart_pm, test_uart_pm_poll_tx_interrupted)
226 {
227 static struct k_work_delayable dwork;
228 static struct k_work_sync sync;
229 const struct device *dev;
230 char str[] = "test";
231
232 dev = DEVICE_DT_GET(UART_NODE);
233 zassert_true(device_is_ready(dev), "uart device is not ready");
234
235 k_work_init_delayable(&dwork, work_handler);
236
237 for (int i = 1; i < 100; i++) {
238 k_work_schedule(&dwork, K_USEC(i * 10));
239
240 for (int j = 0; j < sizeof(str); j++) {
241 uart_poll_out(dev, str[j]);
242 }
243
244 k_work_flush_delayable(&dwork, &sync);
245
246 action_run(dev, PM_DEVICE_ACTION_RESUME, 0);
247
248 communication_verify(dev, true);
249 }
250 }
251
uart_pm_setup(void)252 void *uart_pm_setup(void)
253 {
254 if (DISABLED_RX) {
255 PRINT("RX is disabled\n");
256 }
257
258 return NULL;
259 }
260
261 ZTEST_SUITE(uart_pm, NULL, uart_pm_setup, NULL, NULL, NULL);
262