dma传输与memcpy传输对比测试程序

/*
 * DMA test module
 *
 * Copyright (C) 2007 KEDACOM Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/highmem.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/async_tx.h>
#include <linux/jiffies.h>

#define XFER_TIMES 4000
#define XFER_LEN  1<<20

void *dma_src,*dma_dest;
struct dma_chan *chan = NULL;

static int __init dmatest_init(void)
{

    int xfer_order = get_order(XFER_LEN);
    int i,ret ;
    dma_cap_mask_t mask;
    dma_cookie_t cookie;
    enum dma_status status;
    u64 j1,j2;

    dma_src = __get_free_pages(GFP_KERNEL | GFP_DMA, xfer_order);
    if (!dma_src) {
        printk(KERN_ALERT "dma_src :alloc memory fail.\n");
        ret = -ENOMEM;
        goto CLEAN;

    }
    
    dma_dest = __get_free_pages(GFP_KERNEL | GFP_DMA, xfer_order);
    if (!dma_dest) {
        printk(KERN_ALERT "dma_dest :alloc memory fail.\n");
        ret = -ENOMEM;
        goto CLEAN;
    }
    printk(KERN_NOTICE"dma_src=%#x,dma_dest=%#x\n",dma_src,dma_dest);    
    dma_cap_zero(mask);
    dma_cap_set(DMA_MEMCPY, mask);
    chan = dma_request_channel(mask, NULL, NULL);
    
    if (chan) {
        printk(KERN_NOTICE "dma_request_channel ok,current channel is : %s\n",dma_chan_name(chan));
    }else {
        printk(KERN_NOTICE "dma_request_channel fail,no dma channel available.\n");
        ret = -1;
        goto CLEAN;
    }
    
    j1 = get_jiffies_64();
    for(i =0;i<XFER_TIMES;i++) {
        cookie = dma_async_memcpy_buf_to_buf(chan, dma_dest, dma_src, XFER_LEN);
        if (dma_submit_error(cookie)) {
            printk(KERN_NOTICE"submit error\n");
            ret = -1;
            goto CLEAN;
        }
    }
    
    dma_async_memcpy_issue_pending(chan);
    do {
        status = dma_async_memcpy_complete(chan, cookie, NULL, NULL);
    
    } while (status == DMA_IN_PROGRESS);

    if (status != DMA_SUCCESS)
        printk(KERN_NOTICE "dma xfer dont accomplish,status=%d\n",status);
    j2 = get_jiffies_64();
    printk(KERN_NOTICE"dma xfer time cost:%d ms.\n",jiffies_to_msecs(j2-j1));

    j1 = get_jiffies_64();
    for(i =0;i<XFER_TIMES;i++){
        memcpy(dma_dest, dma_src, XFER_LEN);
    }
    j2 = get_jiffies_64();
    printk(KERN_NOTICE"memcpy time cost:%d ms.\n",jiffies_to_msecs(j2-j1));
    return 0;

CLEAN:
    if (chan)
        dma_release_channel(chan);

    if (dma_src)
        free_pages(dma_src,xfer_order);

    if (dma_dest)
        free_pages(dma_dest,xfer_order);

    return ret;

}
/* when compiled-in wait for drivers to load first */
module_init(dmatest_init);

static void __exit dmatest_exit(void)
{
    if (chan)
        dma_release_channel(chan);

    if (dma_src)
        free_pages(dma_src,get_order(XFER_LEN));

    if (dma_dest)
        free_pages(dma_dest,get_order(XFER_LEN));

}
module_exit(dmatest_exit);

MODULE_AUTHOR("ZhangZhuan <zhangzhuan@kedacom.com>");
MODULE_LICENSE("GPL v2");
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RK3399支持通过DMA-BUF将网卡数据传输到应用程序中。具体实现步骤如下: 1. 创建DMA-BUF 在应用程序中,需要先创建一个DMA-BUF,用于存储从网卡接收到的数据。创建DMA-BUF的方法可以参考上面的例程,具体实现可以使用Rockchip提供的DMA-BUF驱动和相关API。 2. 网卡数据传输 接下来,需要将网卡接收到的数据传输DMA-BUF中。可以使用Linux内核提供的网络套接字API实现。具体步骤如下: - 创建一个网卡套接字,用于接收网络数据: ```c int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sock < 0) { perror("socket"); return -1; } ``` - 绑定网卡套接字,指定接收网络数据的网卡和协议: ```c struct sockaddr_ll sll; memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_ifindex = if_nametoindex("eth0"); // 网卡名称 sll.sll_protocol = htons(ETH_P_ALL); // 协议类型 if (bind(sock, (struct sockaddr *)&sll, sizeof(sll)) < 0) { perror("bind"); close(sock); return -1; } ``` - 接收网络数据,并将数据写入DMA-BUF中: ```c while (1) { char buf[4096]; int len = recv(sock, buf, sizeof(buf), 0); if (len < 0) { perror("recv"); close(sock); return -1; } memcpy(addr, buf, len); // 将数据写入DMA-BUF } ``` 3. 应用程序读取数据 最后,应用程序可以使用DMA-BUF的fd读取从网卡接收到的数据。具体实现可以参考上面的例程,读取DMA-BUF中的数据即可。 需要注意的是,RK3399的硬件配置和系统版本也会影响DMA-BUF数据传输的实现方式,需要根据具体情况进行调整。同时,为了保证代码的正确性和可靠性,建议在实际应用中使用更完善的错误处理和数据校验机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值