Skip to content

Commit

Permalink
tests: drivers: uart: async_dual: Add test cases with runtime PM
Browse files Browse the repository at this point in the history
Add configurations in which runtime PM is enabled. There are 2
configurations:
- Test does not call PM API for getting and putting the device.
 In that configuration UART device shall be suspended whenever
 not active.
- Test is calling PM API which should keep device active as
 long as requested (e.g. during packet reception which consists
 of multiple chunks).

Signed-off-by: Krzysztof Chruściński <[email protected]>
  • Loading branch information
nordic-krch committed Sep 23, 2024
1 parent 4d45745 commit c86ba9f
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 0 deletions.
5 changes: 5 additions & 0 deletions tests/drivers/uart/uart_async_dual/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,10 @@ config UART_ASYNC_DUAL_TEST_TIMEOUT
For how many loops will the stress test run. The higher this number the longer the
test and therefore the higher likelihood an unlikely race/event will be triggered.

config PM_RUNTIME_IN_TEST
bool "Use runtime PM in the test"
select PM_DEVICE
select PM_DEVICE_RUNTIME

# Include Zephyr's Kconfig
source "Kconfig"
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dut: &uart0 {
pinctrl-1 = <&uart0_sleep>;
pinctrl-names = "default", "sleep";
hw-flow-control;
zephyr,pm-device-runtime-auto;
};

&timer0 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ dut: &uart134 {
pinctrl-1 = <&uart134_alt_sleep>;
pinctrl-names = "default", "sleep";
hw-flow-control;
zephyr,pm-device-runtime-auto;
};

dut_aux: &uart137 {
Expand All @@ -76,6 +77,7 @@ dut_aux: &uart137 {
pinctrl-1 = <&uart137_alt_sleep>;
pinctrl-names = "default", "sleep";
hw-flow-control;
zephyr,pm-device-runtime-auto;
};

dut2: &uart120 {
Expand All @@ -85,6 +87,7 @@ dut2: &uart120 {
pinctrl-names = "default", "sleep";
current-speed = <115200>;
hw-flow-control;
zephyr,pm-device-runtime-auto;
};

&timer137 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ dut: &uart21 {
pinctrl-1 = <&uart21_sleep>;
pinctrl-names = "default", "sleep";
hw-flow-control;
zephyr,pm-device-runtime-auto;
};

dut_aux: &uart22 {
Expand All @@ -54,6 +55,7 @@ dut_aux: &uart22 {
pinctrl-1 = <&uart22_sleep>;
pinctrl-names = "default", "sleep";
hw-flow-control;
zephyr,pm-device-runtime-auto;
};

&timer20 {
Expand Down
83 changes: 83 additions & 0 deletions tests/drivers/uart/uart_async_dual/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*/

#include <zephyr/drivers/uart.h>
#include <zephyr/pm/device.h>
#include <zephyr/pm/device_runtime.h>
#include <zephyr/random/random.h>
#include <zephyr/sys/ring_buffer.h>
#include <zephyr/ztest.h>
Expand Down Expand Up @@ -57,6 +59,40 @@ ZTEST_DMEM struct dut_data duts[] = {
#endif
};

static void pm_check(const struct device *dev, const struct device *second_dev, bool exp_on,
int line)
{
if (!IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
return;
}

if (dev == second_dev) {
return;
}

enum pm_device_state state;
int err;
int cnt;

cnt = pm_device_runtime_usage(dev);
err = pm_device_state_get(dev, &state);
zassert_equal(err, 0);

if (exp_on) {
zassert_not_equal(cnt, 0, "Wrong PM cnt:%d, line:%d", cnt, line);
zassert_equal(state, PM_DEVICE_STATE_ACTIVE,
"Wrong PM state %s, line:%d", pm_device_state_str(state), line);
return;
}

/* Expect device to be off. */
zassert_equal(cnt, 0, "Wrong PM count:%d, line:%d", cnt, line);
zassert_equal(state, PM_DEVICE_STATE_SUSPENDED,
"Wrong PM state %s, line:%d", pm_device_state_str(state), line);
}

#define PM_CHECK(dev, second_dev, exp_on) pm_check(dev, second_dev, exp_on, __LINE__)

static const struct device *rx_dev;
static const struct device *tx_dev;

Expand Down Expand Up @@ -452,11 +488,20 @@ static void hci_like_callback(const struct device *dev, struct uart_event *evt,
{
switch (evt->type) {
case UART_TX_DONE:

zassert_true(dev == tx_dev);
if (IS_ENABLED(CONFIG_PM_RUNTIME_IN_TEST)) {
PM_CHECK(tx_dev, rx_dev, true);
pm_device_runtime_put(tx_dev);
}
PM_CHECK(tx_dev, rx_dev, false);
k_sem_give(&tx_data.sem);
break;
case UART_TX_ABORTED:
zassert_true(dev == tx_dev);
if (IS_ENABLED(CONFIG_PM_RUNTIME_IN_TEST)) {
pm_device_runtime_put(tx_dev);
}
zassert_false(tx_data.cont,
"Unexpected TX abort, receiver not reading data on time");
break;
Expand Down Expand Up @@ -568,6 +613,10 @@ static void hci_like_tx(struct test_tx_data *tx_data)
uint8_t len = buf[4] + 5;
int err;

if (IS_ENABLED(CONFIG_PM_RUNTIME_IN_TEST)) {
pm_device_runtime_get(tx_dev);
}

err = uart_tx(tx_dev, buf, len, TX_TIMEOUT);
zassert_equal(err, 0, "Unexpected err:%d", err);
}
Expand Down Expand Up @@ -595,25 +644,57 @@ static void hci_like_rx(void)
uint8_t last_hdr = 0xff;
uint8_t len;
bool cont;
bool explicit_pm = IS_ENABLED(CONFIG_PM_RUNTIME_IN_TEST);

while (1) {
if (explicit_pm) {
pm_device_runtime_get(rx_dev);
}

cont = rx(rx_data.buf, 1);
if (!cont) {
if (explicit_pm) {
pm_device_runtime_put(rx_dev);
}
break;
}
check_pre_hdr(rx_data.buf, last_hdr);
last_hdr = rx_data.buf[0];

/* If explicitly requested device to stay on in should be on.
* If application did not touch PM, device should be off.
*/
PM_CHECK(rx_dev, tx_dev, explicit_pm);

cont = rx(rx_data.buf, 4);
if (!cont) {
if (explicit_pm) {
pm_device_runtime_put(rx_dev);
}
break;
}
len = get_len(rx_data.buf);

/* If explicitly requested device to stay on in should be on.
* If application did not touch PM, device should be off.
*/
PM_CHECK(rx_dev, tx_dev, explicit_pm);

cont = rx(rx_data.buf, len);
if (!cont) {
if (explicit_pm) {
pm_device_runtime_put(rx_dev);
}
break;
}

if (explicit_pm) {
pm_device_runtime_put(rx_dev);
}

/* Device shall be released and off. */
PM_CHECK(rx_dev, tx_dev, false);

check_payload(rx_data.buf, len);
}
}
Expand Down Expand Up @@ -677,6 +758,8 @@ static void hci_like_test(uint32_t baudrate)
/* Flush data. */
(void)uart_tx_abort(tx_dev);
k_msleep(10);
PM_CHECK(tx_dev, rx_dev, false);

(void)uart_rx_enable(rx_dev, rx_data.buf, sizeof(rx_data.buf), RX_TIMEOUT);
k_msleep(1);
(void)uart_rx_disable(rx_dev);
Expand Down
29 changes: 29 additions & 0 deletions tests/drivers/uart/uart_async_dual/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,32 @@ tests:
- nrf52_bsim
extra_configs:
- CONFIG_TEST_BUSY_SIM=y
drivers.uart.async_dual.pm_runtime:
harness: ztest
harness_config:
fixture: uart_loopback
depends_on: gpio
platform_allow:
- nrf54l15pdk/nrf54l15/cpuapp
- nrf54h20dk/nrf54h20/cpuapp
- nrf54h20dk/nrf54h20/cpurad
- nrf54h20dk/nrf54h20/cpuppr
- nrf9160dk/nrf9160
- nrf52_bsim
extra_configs:
- CONFIG_PM_DEVICE_RUNTIME=y
- CONFIG_PM_DEVICE=y
drivers.uart.async_dual.pm_runtime.explicit:
harness: ztest
harness_config:
fixture: uart_loopback
depends_on: gpio
platform_allow:
- nrf54l15pdk/nrf54l15/cpuapp
- nrf54h20dk/nrf54h20/cpuapp
- nrf54h20dk/nrf54h20/cpurad
- nrf54h20dk/nrf54h20/cpuppr
- nrf9160dk/nrf9160
- nrf52_bsim
extra_configs:
- CONFIG_PM_RUNTIME_IN_TEST=y

0 comments on commit c86ba9f

Please sign in to comment.