前言

本次是第三篇。

第一篇,写一个通用框架,做到拿来就能用。

第二篇,实现mmap功能,内核中的read_buf和write_buf都映射到用户空间,然后呢。写read_buf和write_buf的最后一个字节为‘R’和'W',然后再release函数中打印这两个字节。更加复杂的验证,根据需要自行添加,写的太复杂,意义不大。

第三篇,通过测试app,控制复制src_buf到dst_buf,复制方式可以使用DMA引擎和memcpy,并计算复制过程中消耗的微秒数,并在测试app中验证复制是否准确,尽最大努力保证整个流程的准确无误。

一 dmaengine标准API

Linux内核目前推荐使用dmaengine的驱动架构来编写DMA控制器的驱动,同时外设的驱动使用标准的dmaengine API进行DMA的准备、发起和完成时的回调工作。和中断一样,在使用DMA之前,设备驱动程序需首先向dmaengine系统申请DMA通道,申请DMA通道的函数如下:

struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name);
struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,dma_filter_fn fn, void *fn_param);

使用完DMA通道后,应该利用如下函数释放该通道:

void dma_release_channel(struct dma_chan *chan);

之后,一般通过如代码清单11.15的方法初始化并发起一次DMA操作。它通过dmaengine_prep_slave_single()准备好一些DMA描述符,并填充其完成回调为xxx_dma_fini_callback(),之后通过dmaengine_submit()把这个描述符插入队列,再通过dma_async_issue_pending()发起这次DMA动作。DMA完成后,xxx_dma_fini_callback()函数会被dmaengine驱动自动调用。

  static void xxx_dma_fini_callback(void *data){struct completion *dma_complete = data;complete(dma_complete);}issue_xxx_dma(...){rx_desc = dmaengine_prep_slave_single(xxx->rx_chan,xxx->dst_start, t->len, DMA_DEV_TO_MEM,DMA_PREP_INTERRUPT | DMA_CTRL_ACK);rx_desc->callback = xxx_dma_fini_callback;rx_desc->callback_param = &xxx->rx_done;dmaengine_submit(rx_desc);dma_async_issue_pending(xxx->rx_chan);}

这点知识不够用啊(⊙o⊙)…。

二 开始写代码

头文件Dmaengine.h (include\linux)

dmaengine_prep_slave_single的函数原型

static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single(struct dma_chan *chan, dma_addr_t buf, size_t len,enum dma_transfer_direction dir, unsigned long flags)
{struct scatterlist sg;sg_init_table(&sg, 1);sg_dma_address(&sg) = buf;sg_dma_len(&sg) = len;return chan->device->device_prep_slave_sg(chan, &sg, 1,dir, flags, NULL);
}

为了让这个函数工作起来,我们要定义如下几个变量

struct dma_async_tx_descriptor *rx_desc;
struct dma_chan rx_chan;
dma_addr_t dst_start;
size_t len = CSS_DMA_IMAGE_SIZE;
enum dma_transfer_direction dir = DMA_MEM_TO_MEM;

大概写完的伪代码就是这样的

static void css_dma_fini_callback(void *data)
{struct _css_dev_ *css_dev = (struct _css_dev_ *)data;//struct completion *dma_complete = data;DEBUG_CSS("css_dev->name",css_dev->name);//complete(dma_complete);
}
static int css_dma_init(struct _css_dev_ *css_dev)
{struct dma_async_tx_descriptor *rx_desc;struct dma_chan rx_chan;dma_addr_t dst_start;size_t len = CSS_DMA_IMAGE_SIZE;enum dma_transfer_direction dir = DMA_DEV_TO_MEM;rx_desc = dmaengine_prep_slave_single(&rx_chan,dst_start, len, dir,DMA_PREP_INTERRUPT | DMA_CTRL_ACK);rx_desc->callback = xxx_dma_fini_callback;rx_desc->callback_param = css_dev;dmaengine_submit(rx_desc);dma_async_issue_pending(css_dev);
}

三 测试代码

应用代码:csi_single_mmap.c

#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <fcntl.h>#define DEBUG_INFO(format,...)  printf("%s:%d"format"\n",\__func__,__LINE__,##__VA_ARGS__);#define _CSS_DMA_DEV_NAME    "/dev/css_dma"#define CSS_DMA_IMAGE_SIZE      (1280*800)#define CSI_DMA_SET_CUR_MAP_BUF_TYPE_IOCTL 0x1001
#define CSI_DMA_FILL_CHAR_AND_RUN_DMAENGIEN_IOCTL   0x1002
#define CSI_DMA_FILL_CHAR_RUN_MEMCPY_IOCTL  0x1003enum _css_dev_buf_type{_CSS_DEV_READ_BUF = 0,_CSS_DEV_WRITE_BUF,_CSS_DEV_UNKNOWN_BUF_TYPE,_CSS_DEV_MAX_BUF_TYPE,
};struct __css_dev_ {char *read_buf;char *write_buf;
}_css_dev_;static int cycle_dmaengine_test(struct __css_dev_ *css_dev,int fd,int count){int i = 0,j = 0;char c = 'a' - 1;for(i = 0;i < count;i++){c = c + 1;if(ioctl(fd,CSI_DMA_FILL_CHAR_AND_RUN_DMAENGIEN_IOCTL,&c) < 0){perror("ioctl");DEBUG_INFO("ioctl CSI_DMA_FILL_CHAR_IOCTL fail");return -1;}for(j = 0;j < CSS_DMA_IMAGE_SIZE;j++){if(css_dev->read_buf[j] != c || css_dev->write_buf[j] != c){DEBUG_INFO("error:css_dev->read_buf[%d] = %c,css_dev->write_buf[%d] = %c",j,css_dev->read_buf[j],j,css_dev->write_buf[j]);return -1;}}DEBUG_INFO("set c = %c ok",c);if(c == 'z'){c = 'a' - 1;}}
}static int cycle_memcpy_test(struct __css_dev_ *css_dev,int fd,int count){int i = 0,j = 0;char c = 'a' - 1;for(i = 0;i < count;i++){c = c + 1;if(ioctl(fd,CSI_DMA_FILL_CHAR_RUN_MEMCPY_IOCTL,&c) < 0){perror("ioctl");DEBUG_INFO("ioctl CSI_DMA_FILL_CHAR_IOCTL fail");return -1;}for(j = 0;j < CSS_DMA_IMAGE_SIZE;j++){if(css_dev->read_buf[j] != c || css_dev->write_buf[j] != c){DEBUG_INFO("error:css_dev->read_buf[%d] = %c,css_dev->write_buf[%d] = %c",j,css_dev->read_buf[j],j,css_dev->write_buf[j]);return -1;}}DEBUG_INFO("set c = %c ok",c);if(c == 'z'){c = 'a' - 1;}}
}int main(int argc,char *argv[])
{struct __css_dev_ *css_dev = &_css_dev_;char *name = _CSS_DMA_DEV_NAME;int fd = open(name,O_RDWR);if(fd < 0){DEBUG_INFO("open %s",name);return -1;}DEBUG_INFO("open %s ok",name);if(ioctl(fd,CSI_DMA_SET_CUR_MAP_BUF_TYPE_IOCTL,_CSS_DEV_READ_BUF) < 0){perror("ioctl");DEBUG_INFO("ioctl fail");goto fail;}css_dev->read_buf = (char*)mmap(NULL,CSS_DMA_IMAGE_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if(css_dev->read_buf == NULL){perror("mmap");DEBUG_INFO("mmap fail");goto fail;}DEBUG_INFO("css_dev->read_buf = %p",css_dev->read_buf);if(ioctl(fd,CSI_DMA_SET_CUR_MAP_BUF_TYPE_IOCTL,_CSS_DEV_WRITE_BUF) < 0){perror("ioctl");DEBUG_INFO("ioctl fail");goto fail;}css_dev->write_buf = (char*)mmap(NULL,CSS_DMA_IMAGE_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if(css_dev->write_buf == NULL){perror("mmap");DEBUG_INFO("mmap fail");goto fail;}DEBUG_INFO("css_dev->write_buf = %p",css_dev->write_buf);cycle_dmaengine_test(css_dev,fd,10);cycle_memcpy_test(css_dev,fd,10);fail:close(fd);return 0;
}

驱动代码:csi_single.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/gfp.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/platform_device.h>
#include <linux/completion.h>
#include <linux/platform_data/dma-imx.h>
#include <linux/timer.h>#define DEBUG_CSS(format,...)\printk(KERN_INFO"info:%s:%s:%d: "format"\n",\__FILE__,__func__,__LINE__,\##__VA_ARGS__)
#define DEBUG_CSS_ERR(format,...)\printk("\001" "1""error:%s:%s:%d: "format"\n",\__FILE__,__func__,__LINE__,\##__VA_ARGS__)#define CSS_DMA_IMAGE_SIZE       (1280*800)#define CSI_DMA_SET_CUR_MAP_BUF_TYPE_IOCTL 0x1001
#define CSI_DMA_FILL_CHAR_AND_RUN_DMAENGIEN_IOCTL   0x1002
#define CSI_DMA_FILL_CHAR_RUN_MEMCPY_IOCTL  0x1003enum _css_dev_buf_type{_CSS_DEV_READ_BUF = 0,_CSS_DEV_WRITE_BUF,_CSS_DEV_UNKNOWN_BUF_TYPE,_CSS_DEV_MAX_BUF_TYPE,
};
struct _css_dev_{struct file_operations _css_fops;struct miscdevice misc;int buf_size;int buf_size_order;char *src_buf;char *dst_buf;char *user_src_buf_vaddr;char *user_dst_buf_vaddr;dma_addr_t src_addr;dma_addr_t dst_addr; struct spinlock slock;struct mutex open_lock;char name[10];enum _css_dev_buf_type buf_type; struct device *dev;struct dma_chan * dma_m2m_chan;struct completion dma_m2m_ok;struct imx_dma_data m2m_dma_data;struct timeval tv_start,tv_end;struct device *chan_dev;struct dma_device *dma_dev;struct dma_async_tx_descriptor *dma_m2m_desc;
};#define _to_css_dev_(file)    (struct _css_dev_ *)container_of(file->f_op,struct _css_dev_,_css_fops)
static int _css_open(struct inode *inode, struct file *file)
{struct _css_dev_ *css_dev = _to_css_dev_(file);DEBUG_CSS("css_dev->name = %s",css_dev->name);return 0;
}
static ssize_t _css_read(struct file *file, char __user *ubuf, size_t size, loff_t *ppos)
{struct _css_dev_ *css_dev = _to_css_dev_(file);DEBUG_CSS("css_dev->name = %s",css_dev->name);return 0;
}
static int _css_mmap (struct file *file, struct vm_area_struct *vma)
{struct _css_dev_ *css_dev = _to_css_dev_(file);char *p = NULL;char **user_addr;switch(css_dev->buf_type){case _CSS_DEV_READ_BUF:p = css_dev->src_buf;user_addr = (char**)&css_dev->user_src_buf_vaddr;break;case _CSS_DEV_WRITE_BUF:p = css_dev->dst_buf;user_addr = (char**)&css_dev->user_dst_buf_vaddr;break;default:p = NULL;return -EINVAL;break;           }if (remap_pfn_range(vma, vma->vm_start, virt_to_phys(p) >> PAGE_SHIFT,vma->vm_end-vma->vm_start, vma->vm_page_prot)) {DEBUG_CSS_ERR( "remap_pfn_range error\n"); return -EAGAIN;}css_dev->buf_type = _CSS_DEV_UNKNOWN_BUF_TYPE;*user_addr = (void*)vma->vm_start;  DEBUG_CSS("mmap ok user_addr = %p kernel addr = %p",*user_addr,p);return 0;
}
static ssize_t _css_write(struct file *file, const char __user *ubuf, size_t size, loff_t *ppos)
{struct _css_dev_ *css_dev = _to_css_dev_(file);DEBUG_CSS("css_dev->name = %s",css_dev->name);return size;
}static int _css_release (struct inode *inode, struct file *file)
{struct _css_dev_ *css_dev = _to_css_dev_(file);DEBUG_CSS("css_dev->name = %s",css_dev->name);DEBUG_CSS("css_dev->src_buf[%d] = %c",css_dev->buf_size - 1,((char*)css_dev->src_buf)[css_dev->buf_size - 1]);DEBUG_CSS("css_dev->dst_buf[%d] = %c",css_dev->buf_size - 1,((char*)css_dev->dst_buf)[css_dev->buf_size - 1]);return 0;
}static int _css_set_buf_type(struct file *file, enum _css_dev_buf_type buf_type)
{unsigned long flags;struct _css_dev_ *css_dev = _to_css_dev_(file);DEBUG_CSS("buf_type=%d",buf_type);if(buf_type >= _CSS_DEV_MAX_BUF_TYPE){DEBUG_CSS_ERR("invalid buf type");return -EINVAL;}spin_lock_irqsave(&css_dev->slock,flags);css_dev->buf_type = buf_type;   spin_unlock_irqrestore(&css_dev->slock,flags);return 0;
}
static void css_dma_async_tx_callback(void *dma_async_param)
{struct _css_dev_ *css_dev = (struct _css_dev_ *)dma_async_param;complete(&css_dev->dma_m2m_ok);
}
static int css_dmaengine_cpy(struct _css_dev_ *css_dev)
{   dma_cookie_t cookie;enum dma_status dma_status;do_gettimeofday(&css_dev->tv_start);css_dev->src_addr = dma_map_single(css_dev->chan_dev, css_dev->src_buf, css_dev->buf_size, DMA_TO_DEVICE);   css_dev->dst_addr = dma_map_single(css_dev->chan_dev, css_dev->dst_buf, css_dev->buf_size, DMA_FROM_DEVICE);   //DEBUG_CSS("32bit:css_dev->src_addr = %x,css_dev->dst_addr = %x",css_dev->src_addr,css_dev->dst_addr);css_dev->dma_m2m_desc = css_dev->dma_dev->device_prep_dma_memcpy(css_dev->dma_m2m_chan,css_dev->dst_addr,css_dev->src_addr,css_dev->buf_size,0);css_dev->dma_m2m_desc->callback = css_dma_async_tx_callback;css_dev->dma_m2m_desc->callback_param = css_dev;init_completion(&css_dev->dma_m2m_ok);cookie = dmaengine_submit(css_dev->dma_m2m_desc);if(dma_submit_error(cookie)){DEBUG_CSS("dmaengine_submit error");return -EINVAL;}dma_async_issue_pending(css_dev->dma_m2m_chan);wait_for_completion(&css_dev->dma_m2m_ok);dma_status = dma_async_is_tx_complete(css_dev->dma_m2m_chan,cookie,NULL,NULL);if(DMA_COMPLETE != dma_status){DEBUG_CSS("error:dma_status = %d",dma_status);}dma_unmap_single(css_dev->chan_dev,css_dev->src_addr,css_dev->buf_size,DMA_TO_DEVICE);dma_unmap_single(css_dev->chan_dev,css_dev->dst_addr,css_dev->buf_size,DMA_FROM_DEVICE);do_gettimeofday(&css_dev->tv_end);DEBUG_CSS("dma used time = %ld us",(css_dev->tv_end.tv_sec - css_dev->tv_start.tv_sec)*1000000 + (css_dev->tv_end.tv_usec - css_dev->tv_start.tv_usec));return 0;
}static long _css_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{int ret = 0;struct _css_dev_ *css_dev = _to_css_dev_(file);char *p;switch(cmd){case CSI_DMA_SET_CUR_MAP_BUF_TYPE_IOCTL:ret = _css_set_buf_type(file,(enum _css_dev_buf_type)arg);break;case CSI_DMA_FILL_CHAR_AND_RUN_DMAENGIEN_IOCTL:p = (char*)arg;memset(css_dev->src_buf,*p,css_dev->buf_size);      css_dmaengine_cpy(css_dev);break;case CSI_DMA_FILL_CHAR_RUN_MEMCPY_IOCTL:p = (char*)arg;do_gettimeofday(&css_dev->tv_start);memset(css_dev->src_buf,*p,css_dev->buf_size);    do_gettimeofday(&css_dev->tv_end);DEBUG_CSS("memset used time = %ld us",(css_dev->tv_end.tv_sec - css_dev->tv_start.tv_sec)*1000000 + (css_dev->tv_end.tv_usec - css_dev->tv_start.tv_usec));do_gettimeofday(&css_dev->tv_start);memcpy(css_dev->dst_buf,css_dev->src_buf,css_dev->buf_size);do_gettimeofday(&css_dev->tv_end);DEBUG_CSS("memcpy used time = %ld us",(css_dev->tv_end.tv_sec - css_dev->tv_start.tv_sec)*1000000 + (css_dev->tv_end.tv_usec - css_dev->tv_start.tv_usec));break;default:DEBUG_CSS_ERR("unknown cmd = %x",cmd);ret = -EINVAL;break;}return ret;
}static struct _css_dev_ _global_css_dev = {.name = "lkmao",._css_fops = {.owner = THIS_MODULE,.mmap = _css_mmap,.open = _css_open,.release = _css_release,.read = _css_read,.write = _css_write,.unlocked_ioctl = _css_unlocked_ioctl,},.misc = {.minor = MISC_DYNAMIC_MINOR,.name = "css_dma",},.buf_type = _CSS_DEV_UNKNOWN_BUF_TYPE,.user_src_buf_vaddr = NULL,.user_dst_buf_vaddr = NULL,.m2m_dma_data = {.peripheral_type = IMX_DMATYPE_MEMORY,.priority = DMA_PRIO_HIGH,},
};static int css_dev_get_dma_addr(struct _css_dev_ *css_dev,char **vaddr,dma_addr_t *phys, int direction)
{char *p;dma_addr_t dma_addr;p = (char*)__get_free_pages(GFP_KERNEL|GFP_DMA,css_dev->buf_size_order);if(p == NULL || IS_ERR(p)){DEBUG_CSS("devm_kmalloc error");return -ENOMEM;}dma_addr = dma_map_single(css_dev->dev, p, css_dev->buf_size, direction);    *vaddr = p;*phys = dma_addr;DEBUG_CSS("32bit:p = %p,dma_addr = %x",p,dma_addr);return 0;
}static bool css_dma_filter_fn(struct dma_chan *chan, void *filter_param)
{if(!imx_dma_is_general_purpose(chan)){DEBUG_CSS("css_dma_filter_fn error");return false;}chan->private = filter_param;return true;
}static int css_dmaengine_init(struct _css_dev_ *css_dev)
{dma_cap_mask_t dma_m2m_mask;struct dma_slave_config dma_m2m_config = {0};css_dev->m2m_dma_data.peripheral_type = IMX_DMATYPE_MEMORY;css_dev->m2m_dma_data.priority = DMA_PRIO_HIGH;dma_cap_zero(dma_m2m_mask);dma_cap_set(DMA_MEMCPY,dma_m2m_mask);css_dev->dma_m2m_chan = dma_request_channel(dma_m2m_mask,css_dma_filter_fn,&css_dev->m2m_dma_data);if(!css_dev->dma_m2m_chan){DEBUG_CSS("dma_request_channel error");return -EINVAL;}dma_m2m_config.direction = DMA_MEM_TO_MEM;dma_m2m_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;dmaengine_slave_config(css_dev->dma_m2m_chan,&dma_m2m_config);css_dev->dma_dev = css_dev->dma_m2m_chan->device;css_dev->chan_dev = css_dev->dma_m2m_chan->device->dev;return 0;
}static int css_dev_init(struct platform_device *pdev,struct _css_dev_ *css_dev)
{css_dev->misc.fops = &css_dev->_css_fops;pr_debug("css_init init ok");mutex_init(&css_dev->open_lock);spin_lock_init(&css_dev->slock);printk("KERN_ALERT = %s",KERN_ALERT);css_dev->dev = &pdev->dev;css_dev->buf_size = CSS_DMA_IMAGE_SIZE;css_dev->buf_size_order = get_order(css_dev->buf_size);if(css_dev_get_dma_addr(css_dev,&css_dev->src_buf,&css_dev->src_addr,DMA_TO_DEVICE)){return -ENOMEM;}css_dev->src_buf = (char*)__get_free_pages(GFP_KERNEL|GFP_DMA,css_dev->buf_size_order);if(css_dev->src_buf == NULL || IS_ERR(css_dev->src_buf)){DEBUG_CSS("devm_kmalloc error");return -ENOMEM;}css_dev->dst_buf = (char*)__get_free_pages(GFP_KERNEL|GFP_DMA,css_dev->buf_size_order);if(css_dev->dst_buf == NULL || IS_ERR(css_dev->dst_buf)){DEBUG_CSS("devm_kmalloc error");return -ENOMEM;}DEBUG_CSS("32bit:css_dev->src_buf = %p,css_dev->dst_buf = %p",css_dev->src_buf,css_dev->dst_buf);if(misc_register(&css_dev->misc) != 0){DEBUG_CSS("misc_register error");return -EINVAL;}platform_set_drvdata(pdev,css_dev);css_dmaengine_init(css_dev);return 0;
}static int css_probe(struct platform_device *pdev)
{struct _css_dev_ *css_dev = (struct _css_dev_ *)&_global_css_dev;if(css_dev_init(pdev,css_dev)){return -EINVAL;}  DEBUG_CSS("init ok");return 0;
}static int css_remove(struct platform_device *pdev)
{struct _css_dev_ *css_dev = &_global_css_dev;//dma_unmap_single(css_dev->dev,css_dev->src_addr,css_dev->buf_size,DMA_FROM_DEVICE);//dma_unmap_single(css_dev->dev,css_dev->dst_addr,css_dev->buf_size,DMA_FROM_DEVICE);free_page((unsigned long )css_dev->dst_buf);free_page((unsigned long )css_dev->src_buf);misc_deregister(&css_dev->misc);dma_release_channel(css_dev->dma_m2m_chan);DEBUG_CSS("exit ok");return 0;
}static const struct of_device_id css_of_ids[] = {{.compatible = "css_dma"},{},
};
MODULE_DEVICE_TABLE(of,css_of_ids);
static struct platform_driver css_platform_driver = {.probe =  css_probe,.remove = css_remove,.driver = {.name = "css_dma",.of_match_table = css_of_ids,.owner = THIS_MODULE,},
};static int __init css_init(void)
{int ret_val;ret_val = platform_driver_register(&css_platform_driver);if(ret_val != 0){DEBUG_CSS("platform_driver_register error");return ret_val;}DEBUG_CSS("platform_driver_register ok");return 0;
}static void __exit css_exit(void)
{platform_driver_unregister(&css_platform_driver);
}module_init(css_init);
module_exit(css_exit);
MODULE_LICENSE("GPL");

Makefile:

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
KERN_DIR = /home/lkmao/imx/linux/linux-imxFILE_NAME=csi_single
obj-m += $(FILE_NAME).o
APP_NAME=csi_single_mmapall:make -C $(KERN_DIR) M=$(shell pwd) modulessudo cp $(FILE_NAME).ko /big/nfsroot/jiaocheng_rootfs/home/root/sudo scp $(FILE_NAME).ko root@192.168.0.3:/home/root/arm-linux-gnueabihf-gcc -o $(APP_NAME) $(APP_NAME).csudo cp $(APP_NAME) /big/nfsroot/jiaocheng_rootfs/home/root/sudo scp $(APP_NAME) root@192.168.0.3:/home/root/.PHONY:clean
clean:make -C $(KERN_DIR) M=$(shell pwd) cleanrm $(APP_NAME) -rf

设备树配置

    sdma_m2m{compatible = "css_dma";};

测试过程和结果:

1 make编译Makefile

2 进入开发板加载模块:insmod csi_single.ko

root@ATK-IMX6U:~# insmod csi_single.ko
[   41.430795] KERN_ALERT = 1
[   41.433620] info:/big/csi_driver/css_dma/csi_single.c:css_dev_get_dma_addr:267: 32bit:p = 94c00000,dma_addr = 94c00000
[   41.447390] info:/big/csi_driver/css_dma/csi_single.c:css_dev_init:337: 32bit:css_dev->src_buf = 94d00000,css_dev->dst_buf = 94e00000
[   41.463653] info:/big/csi_driver/css_dma/csi_single.c:css_probe:355: init ok
[   41.474842] info:/big/csi_driver/css_dma/csi_single.c:css_init:398: platform_driver_register ok
root@ATK-IMX6U:~#

3 运行测试应用:./csi_single_mmap

执行结果如下图所示:

测试分两个部分,一个是dma引擎复制数据的部分,第二个是memcpy复制数据的部分

驱动中的调试信息

应用输出的调试信息:

小结

我对这个测试结果是表示怀疑的,DMA引擎20多毫秒,memcpy1.7毫秒,memset 0.7毫秒。我一度怀疑是代码出了问题。还得想办法做更多的测试才行。

DMA实践3:dmaengine的实验相关推荐

  1. TIT 数字图像处理 原理与实践(MATLAB) 入门教学 实验一 常用的MATLAB图像处理命令与图像基本操作

    文章目录 数字图像处理 原理与实践(MATLAB) 入门教学 实验一 常用的MATLAB图像处理命令与图像基本操作 实验要求 知识点 实验内容 1.读入一幅RGB图像,变换为灰度图像和二值图像,并在同 ...

  2. 《STM32从零开始学习历程》——DMA直接存储区访问实验例程

    <STM32从零开始学习历程>@EnzoReventon DMA-直接存储区访问实验例程 本章节为DMA直接存储区访问的实验例程讲解,以"正点原子"的例程为基础进行讲解 ...

  3. TIT 数字图像处理 原理与实践(MATLAB) 入门教学 实验三 图像平滑与图像锐化

    文章目录 数字图像处理 原理与实践(MATLAB) 入门教学 实验三 图像平滑与图像锐化 实验要求 知识点 实验内容 1.采用二维中值滤波函数medfilt2对受椒盐噪声干扰的图像滤波,窗口分别采用3 ...

  4. 北邮计算机网络实践第四次实验,北邮计算机网络技术实践实验四实验报告.doc...

    北邮计算机网络技术实践实验四实验报告 计算机网络技术实践实验报告 实验名称:基本交换机使用及VLAN设置 姓 名:胡春月 实验日期: 2015.05.05 学 号:2012211508 实验报告日期: ...

  5. Matlab实践课心得体会,实验心得体会4篇

    实践是检验真理唯一的标准,当想要检验自己的所学时一需要做实验来检验.下面是由出国留学网小编为大家整理的"实验心得体会四篇",仅供参考,欢迎大家阅读. 篇一:实验心得体会 大学数学实 ...

  6. 实践设计模拟计算机,个体化股骨假体的计算机辅助设计实践及模拟力学实验

    摘要: 背景:由于人体的绝对个性化特点,标准人工假体与患者骨骼之间的误差使二者难以很好匹配,不能确保人工关节的长期稳定.目的:利用已开发的计算机辅助设计和制造程序,建立个体化股骨假体的三维模型.并通过 ...

  7. 物流管理python实践报告_Python程序设计 实验报告6

    实验六 函数 安徽工程大学 Python程序设计 实验报告 班级   物流192   姓名 周海国  学号3190505228 成绩 日期     2020.5.5    指导老师       修宇 ...

  8. 视觉检测设计与实践答题卡检测实验报告

    一.实验目的 1.提取答题卡的信息 2.能够有效辨识答题卡的信息 二.实验内容 1.实验步骤 ①配置python在实现图像处理下的运行环境,配置opencv-python,opencv-contrib ...

  9. 【嵌入式12】DMA通信原理及编程实验,DMA方式向上位机连续发送数据

    本文介绍DMS通信原理,STM32采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据. 一.DMA介绍 什么是DMA? DMA介绍 DMA传输方式 DMA传输参数 DMA数据传输的 ...

最新文章

  1. TensorRT深度学习训练和部署图示
  2. MyEclipse2014配置Tomcat开发JavaWeb程序JSP以及Servlet
  3. 什么是textRNN?有什么用途?结构是什么样子的?
  4. html 出现的错误
  5. html怎么一段时间把网页背景更换_复盛螺杆压缩机故障怎么维修?
  6. html里面表格问题
  7. 手机网页播放器php,html5手机移动端视频播放代码插件
  8. 字节约翰斯·霍普金斯上交提出iBOT框架,基于MIM进行自监督训练,在ImageNet-1K上达到86.3%的微调精度!...
  9. AJAX全套(JSONP、CORS)
  10. python向数据库插入中文乱码问题
  11. pycharm OpenCV代码补全失效解决方法
  12. 永磁同步电机模型之坐标变换
  13. win10中谷歌浏览器安装插件的位置
  14. 金蝶K3案例教程总账后台配置
  15. GO语言安装(windows)
  16. 航空公司客户价值分析(python)
  17. 泡泡代码c语言,重发一次,带注释的泡泡模拟程序!
  18. svn clean up 特别慢
  19. java填空题_JAVA填空题复习(有答案).doc
  20. mybatis中的事务------我的笔记M11

热门文章

  1. 场景烘培分享——详情unity手册
  2. uniapp实现动态轨迹回放
  3. 使用Generator(小黑鸟)反向生成Java项目(IDEA + Maven)
  4. 黑鸟本周安全热点与分析/Vortex/IOTroop/CVE-2017-11292
  5. django后台设置
  6. 【效率特工队】记事本txt文本号码如何转换安卓苹果手机通讯录vCard(vcf)格式,最快的方法
  7. 图数据库在百度汉语中的应用
  8. C++贷款类(等额本金,等额本息)
  9. 去掉桌面图标文字蓝色阴影
  10. Linux系统用户与用户组管理