4,465
社区成员




最近需要测试3588板子在操作系统下面的dma的传输速率。
在网上找到了dma测试代码,尝试将驱动层代码生成.ko加载到内核。通过insmod my-dma.ko成功加载模块,通过lsmod指令查看可以找到my-dma模块。但发现模块内部module_init(dma_init)并未执行(尝试在函数中加入printk函数,dmesg查看未打印,且调整打印级别也并未打印),且在/sys/路径下也未生成my-dma。
有没有懂的大佬,指点一下
在网上找到测试驱动层代码如下:(参考链接---->Linux DMA 内存拷贝与memcpy 速率比较_linux下dma读写内存速度-CSDN博客)
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/dmaengine.h>
#include <linux/wait.h>
#include <linux/string.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#define DEBUG_PRINT printk
#define MEMCPY_NO_DMA 0
#define MEMCPY_DMA 1
#define BUFF_SIZE (512*1024)
struct cdev my_cdev;
static int major_ret;
static struct class *pdma_class;
static struct device *pdma_device;
static dma_addr_t *src = NULL;
static dma_addr_t src_phys ;
static dma_addr_t *dst = NULL;
static dma_addr_t dst_phys ;
static volatile int dma_finished = 0;
static DECLARE_WAIT_QUEUE_HEAD(wq);
static void do_memcpy_no_dma(void)
{
unsigned long t1 , t2,diff,msec;
int i ;
t1 = jiffies;
for(i = 0;i < 1000;i++)
{
memcpy(dst,src,BUFF_SIZE);
}
t2 = jiffies;
diff = (long)t2 - (long)t1;
msec = diff *1000/HZ;
DEBUG_PRINT("used:%ld ms\n",msec);
}
static void tx_callback(void *dma_async_param)
{
//DEBUG_PRINT("callback here\n");
dma_finished = 1;
wake_up_interruptible(&wq);
}
static int do_memcpy_with_dma(void)
{
struct dma_chan *chan = NULL;
dma_cap_mask_t mask;
struct dma_async_tx_descriptor *tx = NULL;
dma_cookie_t dma_cookie;
memset(src,0xAA,BUFF_SIZE);
memset(dst,0x55,BUFF_SIZE);
dma_cap_zero(mask);
dma_cap_set(DMA_MEMCPY, mask);
chan = dma_request_channel(mask, NULL, NULL);
if(NULL == chan )
{
printk("err:%s:%d\n",__FILE__,__LINE__);
return -1;
}
unsigned long t1 , t2,diff,msec;
int i ;
t1 = jiffies;
for(i=0;i<1000;i++)
{
dma_finished = 0;
//tx = dmaengine_prep_dma_cyclic(chan, src_phys, BUFF_SIZE, 1024, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT|DMA_CTRL_ACK);
tx = dmaengine_prep_dma_memcpy(chan, dst_phys, src_phys, BUFF_SIZE, DMA_PREP_INTERRUPT|DMA_CTRL_ACK);
if(NULL == tx)
{
printk("err:%s:%d\n",__FILE__,__LINE__);
dma_release_channel(chan);
return -1;
}
tx->callback = tx_callback;
dma_cookie = dmaengine_submit(tx);
if (dma_submit_error(dma_cookie))
{
printk("Failed to do DMA tx_submit");
}
dma_async_issue_pending(chan);
wait_event_interruptible(wq, dma_finished);
}
t2 = jiffies;
diff = (long)t2 - (long)t1;
msec = diff *1000/HZ;
DEBUG_PRINT("used:%ld ms\n",msec);
printk("ok !\n");
if(memcmp(src, dst, BUFF_SIZE) == 0)
{
printk("memcpy succ !\n");
}
else
{
printk("memcpy failed !\n");
int i = 0;
for(i=0;i<8;i++)
{
printk("%x | %x\n",src[i],dst[i]);
}
}
dma_release_channel(chan);
}
static long dma_ioctl(struct file *file, unsigned int cmd, unsigned long data)
{
switch (cmd)
{
case MEMCPY_NO_DMA:
do_memcpy_no_dma();
break;
case MEMCPY_DMA:
do_memcpy_with_dma();
break;
}
return 0;
}
static const struct file_operations fops =
{
.owner = THIS_MODULE,
.unlocked_ioctl = dma_ioctl,
};
static int __init dma_init(void)
{
dev_t devno = 0;
alloc_chrdev_region(&devno, 0, 1, "my-dma");
major_ret = MAJOR(devno);
cdev_init(&my_cdev, &fops);
cdev_add(&my_cdev, devno, 1);
pdma_class = class_create(THIS_MODULE, "my-dma-class");
pdma_device = device_create(pdma_class, NULL, MKDEV(major_ret,0), NULL, "my-dma");
src = dma_alloc_coherent(NULL, BUFF_SIZE, &src_phys, GFP_KERNEL);
if(NULL == src)
{
printk("err:%s:%d\n",__FILE__,__LINE__);
goto _FAILED_ALLOC_SRC;
}
dst = dma_alloc_coherent(NULL, BUFF_SIZE, &dst_phys, GFP_KERNEL);
if(NULL == dst)
{
printk("err:%s:%d\n",__FILE__,__LINE__);
goto _FAILED_ALLOC_DST;
}
return 0;
_FAILED_ALLOC_DST:
dma_free_coherent(NULL, BUFF_SIZE, src, src_phys);
_FAILED_ALLOC_SRC:
device_destroy(pdma_class, MKDEV(major_ret,0));
class_destroy(pdma_class);
cdev_del(&my_cdev);
unregister_chrdev_region(MKDEV(major_ret, 0), 1);
return -1;
}
static void __exit dma_exit(void)
{
//printk("hello dma openwrt exit\n");
device_destroy(pdma_class, MKDEV(major_ret,0));
class_destroy(pdma_class);
dev_t devno = MKDEV(major_ret, 0);
cdev_del(&my_cdev);
unregister_chrdev_region(devno, 1);
dma_free_coherent(NULL, BUFF_SIZE, src, src_phys);
dma_free_coherent(NULL, BUFF_SIZE, dst, dst_phys);
}
module_init(dma_init);
module_exit(dma_exit);
MODULE_AUTHOR("hello world");
MODULE_DESCRIPTION("dma driver");
MODULE_LICENSE("GPL");
//MODULE_ALIAS("platform:" DRV_NAME);
应用层测试代码:
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#define MEMCPY_NO_DMA 0
#define MEMCPY_DMA 1
void print_usage(char *argv)
{
printf("usge:\n");
printf("%s <nodma|dma> \n");
}
int main(int argc ,char **argv)
{
if(argc < 2)
{
print_usage(argv[0]);
return -1;
}
int fd = open("/dev/my-dma",O_RDWR);
if(fd < 0)
{
printf("open /dev/my-dma failed!\n");
return -1;
}
if(strcmp("dma", argv[1]) == 0)
{
ioctl(fd,MEMCPY_DMA);
}
else
{
ioctl(fd,MEMCPY_NO_DMA);
}
close(fd);
}
现在问题
解决了吗,感觉是乌龙