1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 GuEe-GUI the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#if defined(RT_USING_DMA) && defined(RT_USING_FINSH)
#include <stdlib.h>
static void test_dma_callback(struct rt_dma_chan *chan, rt_size_t size)
{
rt_bool_t *done_ptr = chan->priv;
*done_ptr = RT_TRUE;
rt_hw_wmb();
}
static int dma_memcpy_test(int argc, char**argv)
{
rt_bool_t done;
int dma_sz = 64;
rt_ubase_t dma_addr;
char *src_addr, *dst_addr;
struct rt_device dev = {};
struct rt_dma_slave_config config;
struct rt_dma_slave_transfer transfer;
struct rt_dma_chan *chn = rt_dma_chan_request(&dev, RT_NULL);
if (rt_is_err_or_null(chn))
{
rt_kputs("Alloc DMA channel fail");
return 0;
}
if (argc > 1)
{
dma_sz = atoi(argv[1]);
}
if (dma_sz % sizeof(rt_uint32_t))
{
dma_sz = RT_ALIGN_DOWN(dma_sz, sizeof(rt_uint32_t));
rt_kprintf("DMA size align to %d\n", dma_sz);
}
if (!(src_addr = rt_dma_alloc_coherent(&dev, dma_sz, &dma_addr)))
{
rt_kprintf("Alloc DMA %s buffer(size = %d) fail\n", "SRC", dma_sz);
goto _free_dma_chan;
}
config.src_addr = dma_addr;
if (!(dst_addr = rt_dma_alloc_coherent(&dev, dma_sz, &dma_addr)))
{
rt_kprintf("Alloc DMA %s buffer(size = %d) fail\n", "DST", dma_sz);
goto _free_src_addr;
}
config.dst_addr = dma_addr;
config.direction = RT_DMA_MEM_TO_MEM;
config.src_addr_width = sizeof(rt_uint32_t);
config.src_maxburst = sizeof(rt_uint32_t);
config.dst_addr_width = sizeof(rt_uint32_t);
config.dst_maxburst = sizeof(rt_uint32_t);
chn->callback = test_dma_callback;
chn->priv = &done;
if (rt_dma_chan_config(chn, &config))
{
rt_kprintf("DMA channel %s fail\n", "config");
goto _free_dst_addr;
}
rt_memset(&transfer, 0, sizeof(transfer));
transfer.src_addr = config.src_addr;
transfer.dst_addr = config.dst_addr;
transfer.buffer_len = dma_sz;
if (rt_dma_prep_memcpy(chn, &transfer))
{
rt_kprintf("DMA channel %s fail\n", "prep");
goto _free_dst_addr;
}
rt_memset(src_addr, 0xff, dma_sz);
rt_memset(dst_addr, 0, dma_sz);
rt_kprintf("%s %s:\n", "SRC", "start");
for (int i = 0; i < dma_sz; ++i)
{
rt_kprintf("%02x ", src_addr[i]);
}
rt_kputs("\n");
rt_kprintf("%s %s:\n", "DST", "start");
for (int i = 0; i < dma_sz; ++i)
{
rt_kprintf("%02x ", dst_addr[i]);
}
rt_kputs("\n");
done = RT_FALSE;
if (rt_dma_chan_start(chn))
{
rt_kprintf("DMA channel %s fail\n", "start");
goto _free_dst_addr;
}
while (!done)
{
rt_hw_cpu_relax();
}
rt_kprintf("%s %s:\n", "SRC", "end");
for (int i = 0; i < dma_sz; ++i)
{
rt_kprintf("%02x ", src_addr[i]);
}
rt_kputs("\n");
rt_kprintf("%s %s:\n", "DST", "end");
for (int i = 0; i < dma_sz; ++i)
{
rt_kprintf("%02x ", dst_addr[i]);
}
rt_kputs("\n");
_free_dst_addr:
rt_dma_free_coherent(&dev, dma_sz, dst_addr, config.dst_addr);
_free_src_addr:
rt_dma_free_coherent(&dev, dma_sz, src_addr, config.src_addr);
_free_dma_chan:
rt_dma_chan_release(chn);
return 0;
}
MSH_CMD_EXPORT(dma_memcpy_test, test dma memcpy e.g: dma_memcpy_test(64));
#endif /* RT_USING_DMA && RT_USING_FINSH */
|