Skip to content

Commit aea1ff9

Browse files
talih0kartben
authored andcommitted
tests: drivers: dma: Add cyclic transfer test
Adds a test with the cyclic transfer bit set in the dma configuration. Signed-off-by: Andriy Gelman <[email protected]>
1 parent 00c3528 commit aea1ff9

File tree

8 files changed

+221
-0
lines changed

8 files changed

+221
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(cyclic)
6+
7+
FILE(GLOB app_sources src/*.c)
8+
target_sources(app PRIVATE ${app_sources})

tests/drivers/dma/cyclic/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright (c) 2025 Andriy Gelman
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
mainmenu "DMA Cyclic Test"
5+
6+
source "Kconfig.zephyr"
7+
8+
config DMA_CYCLIC_CHANNEL_NR
9+
int "DMA channel to use"
10+
default 0
11+
12+
config DMA_CYCLIC_XFER_SIZE
13+
int "Number of bytes to transfer"
14+
default 4096
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) 2025 Andriy Gelman <[email protected]>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
aliases {
9+
dma0 = &dma0;
10+
};
11+
};
12+
13+
&dma0 {
14+
status = "okay";
15+
};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) 2025 Andriy Gelman <[email protected]>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
aliases {
9+
dma0 = &dma0;
10+
};
11+
};
12+
13+
&dma0 {
14+
status = "okay";
15+
};

tests/drivers/dma/cyclic/prj.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CONFIG_ZTEST=y
2+
CONFIG_DMA=y
3+
CONFIG_LOG=y
4+
CONFIG_DMA_LOG_LEVEL_INF=y

tests/drivers/dma/cyclic/src/main.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* Copyright (c) 2025 Andriy Gelman
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
8+
#include <zephyr/kernel.h>
9+
#include <zephyr/ztest.h>
10+
11+
ZTEST_SUITE(dma_m2m_cyclic, NULL, NULL, NULL, NULL, NULL);
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Copyright (c) 2025 Andriy Gelman
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @file
9+
* @brief Verify zephyr dma memory to memory cyclic transfer
10+
* @details
11+
* - Test Steps
12+
* -# Set dma configuration for cyclic configuration
13+
* -# Start transfer tx -> rx
14+
* -# Wait for a block transfer to complete
15+
* -# Suspend transfer and check tx/rx contents match
16+
* -# Invalidate rx data and resume transfer
17+
* -# Wait for a block transfer to complete
18+
* -# Stop transfer and check tx/rx contents match
19+
*/
20+
21+
#include <zephyr/kernel.h>
22+
#include <zephyr/drivers/dma.h>
23+
#include <zephyr/ztest.h>
24+
25+
static __aligned(32) uint8_t tx_data[CONFIG_DMA_CYCLIC_XFER_SIZE];
26+
static __aligned(32) uint8_t rx_data[CONFIG_DMA_CYCLIC_XFER_SIZE];
27+
28+
K_SEM_DEFINE(xfer_sem, 0, 1);
29+
30+
static struct dma_config dma_cfg;
31+
static struct dma_block_config dma_block_cfgs;
32+
33+
static void dma_callback(const struct device *dma_dev, void *user_data,
34+
uint32_t channel, int status)
35+
{
36+
k_sem_give(&xfer_sem);
37+
}
38+
39+
40+
static int test_cyclic(void)
41+
{
42+
const struct device *dma;
43+
int chan_id;
44+
45+
TC_PRINT("Preparing DMA Controller\n");
46+
47+
for (int i = 0; i < CONFIG_DMA_CYCLIC_XFER_SIZE; i++) {
48+
tx_data[i] = i;
49+
}
50+
51+
dma = DEVICE_DT_GET(DT_ALIAS(dma0));
52+
if (!device_is_ready(dma)) {
53+
TC_PRINT("dma controller device is not ready\n");
54+
return TC_FAIL;
55+
}
56+
57+
dma_cfg.channel_direction = MEMORY_TO_MEMORY;
58+
dma_cfg.source_data_size = 4U;
59+
dma_cfg.dest_data_size = 4U;
60+
dma_cfg.source_burst_length = 4U;
61+
dma_cfg.dest_burst_length = 4U;
62+
dma_cfg.user_data = NULL;
63+
dma_cfg.dma_callback = dma_callback;
64+
dma_cfg.block_count = 1;
65+
dma_cfg.head_block = &dma_block_cfgs;
66+
dma_cfg.complete_callback_en = true; /* per block completion */
67+
dma_cfg.cyclic = 1;
68+
69+
chan_id = dma_request_channel(dma, NULL);
70+
if (chan_id < 0) {
71+
TC_PRINT("Platform does not support dma request channel,"
72+
" using Kconfig DMA_SG_CHANNEL_NR\n");
73+
chan_id = CONFIG_DMA_CYCLIC_CHANNEL_NR;
74+
}
75+
76+
dma_block_cfgs.block_size = CONFIG_DMA_CYCLIC_XFER_SIZE;
77+
78+
dma_block_cfgs.source_address = (uint32_t)(tx_data);
79+
dma_block_cfgs.dest_address = (uint32_t)(rx_data);
80+
81+
TC_PRINT("Configuring cyclic transfer on channel %d\n", chan_id);
82+
83+
if (dma_config(dma, chan_id, &dma_cfg)) {
84+
TC_PRINT("ERROR: transfer config (%d)\n", chan_id);
85+
return TC_FAIL;
86+
}
87+
88+
TC_PRINT("Starting cyclic transfer on channel %d and waiting for first block to complete\n",
89+
chan_id);
90+
91+
if (dma_start(dma, chan_id)) {
92+
TC_PRINT("ERROR: transfer start (%d)\n", chan_id);
93+
return TC_FAIL;
94+
}
95+
96+
if (k_sem_take(&xfer_sem, K_MSEC(10)) != 0) {
97+
TC_PRINT("Timed out waiting for xfers\n");
98+
return TC_FAIL;
99+
}
100+
101+
if (dma_suspend(dma, chan_id) != 0) {
102+
TC_PRINT("Failed to suspend transfer\n");
103+
return TC_FAIL;
104+
}
105+
106+
if (memcmp(tx_data, rx_data, CONFIG_DMA_CYCLIC_XFER_SIZE)) {
107+
TC_PRINT("Failed to verify tx/rx in the first cycle.\n");
108+
return TC_FAIL;
109+
}
110+
111+
k_sem_reset(&xfer_sem);
112+
113+
/* reset rx_data to validate that transfer cycles */
114+
memset(rx_data, 0, sizeof(rx_data));
115+
116+
if (dma_resume(dma, chan_id) != 0) {
117+
TC_PRINT("Failed to resume transfer\n");
118+
return TC_FAIL;
119+
}
120+
121+
if (k_sem_take(&xfer_sem, K_MSEC(10)) != 0) {
122+
TC_PRINT("Timed out waiting for xfers\n");
123+
return TC_FAIL;
124+
}
125+
126+
if (dma_stop(dma, chan_id) != 0) {
127+
TC_PRINT("Failed to stop dma\n");
128+
return TC_FAIL;
129+
}
130+
131+
if (memcmp(tx_data, rx_data, CONFIG_DMA_CYCLIC_XFER_SIZE)) {
132+
TC_PRINT("Failed to verify tx/rx in the second cycle.\n");
133+
return TC_FAIL;
134+
}
135+
136+
TC_PRINT("Finished: DMA Cyclic test\n");
137+
return TC_PASS;
138+
}
139+
140+
/* export test cases */
141+
ZTEST(dma_m2m_cyclic, test_dma_m2m_cyclic)
142+
{
143+
zassert_true((test_cyclic() == TC_PASS));
144+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
tests:
2+
drivers.dma.cyclic:
3+
depends_on: dma
4+
tags:
5+
- drivers
6+
- dma
7+
platform_allow:
8+
- xmc47_relax_kit
9+
- xmc45_relax_kit
10+
filter: dt_alias_exists("dma0")

0 commit comments

Comments
 (0)