在参考网友(天使之猜)的例程(https://blog.csdn.net/hello_jinjin/article/details/102058119)中遇到了一些问题,导致内核崩溃。
在英勇无比的网友(兜兜里么糖√º)帮助下,成功解决了这一问题。 现将解决方法整理如下:
1.天使之猜网友的DMA驱动源码中第126行有误,应修改为static void dma_exit(void)并将“return 0”注释掉,注意第84行函数的声明也应一起修改。
2.第179行应改为copy_from_user(axidma_addr,buf,count);
3.第220行应改为copy_to_user(buf, axidma_addr, size);
其他部分如常,无特别需要更正的。
修改后的DMA驱动源码如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/io.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/ioport.h>
#include <linux/of.h>
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <linux/dma-mapping.h>
/***DMA驱动程序*******`** **/
//DMA 基地址
#define DMA_BASE_ADDR       0X40400000//DMA MM2S控制寄存器
volatile unsigned int  * mm2s_cr;
#define MM2S_DMACR      0X00000000//DMA MM2S状态控制寄存器
volatile unsigned int * mm2s_sr;
#define MM2S_DMASR      0X00000004//DMA MM2S源地址低32位
volatile unsigned int * mm2s_sa;
#define MM2S_SA         0X00000018//DMA MM2S传输长度(字节)
volatile unsigned int * mm2s_len;
#define MM2S_LENGTH     0X00000028//DMA S2MM控制寄存器
volatile unsigned int  * s2mm_cr;
#define S2MM_DMACR      0X00000030//DMA S2MM状态控制寄存器
volatile unsigned int  * s2mm_sr;
#define S2MM_DMASR      0X00000034//DMA S2MM目标地址低32位
volatile unsigned int  * s2mm_da;
#define S2MM_DA         0X00000048//DMA S2MM传输长度(字节)
volatile unsigned int  * s2mm_len;
#define S2MM_LENGTH     0X00000058#define DMA_LENGTH        16384dma_addr_t axidma_handle;
volatile unsigned int * axidma_addr;
int major;static struct class *dma_class   = NULL;
static int dmadev_init(void);
static void dmadev_exit(void);
static int dma_open(struct inode *inode,struct file *file);
static int dma_write(struct file *file,const char __user *buf, size_t count,loff_t *ppos);
static int dma_read(struct file *file,char __user *buf,size_t size,loff_t *ppos);/**file_operations 结构数据,沟通内核与操作系统桥梁** */
static struct file_operations dma_lops=
{.owner = THIS_MODULE,
.read  = dma_read,
.open  = dma_open,
.write = dma_write,
};
//DMA interrupt functions
static irqreturn_t dma_mm2s_irq(int irq,void *dev_id)
{printk(KERN_ERR"irq=%d\n",irq);iowrite32(0x00001000,mm2s_sr);return IRQ_HANDLED;
}
static irqreturn_t dma_s2mm_irq(int irq,void *dev_id)
{printk(KERN_ERR"irq=%d\n",irq);iowrite32(0x00001000,s2mm_sr);return IRQ_HANDLED;
}
/**open 接口函数** */
static int dma_open(struct inode *inode,struct file *file)
{int err;printk(KERN_ERR"DMA open\n");//申请一大块空间axidma_addr = dma_alloc_coherent(NULL,DMA_LENGTH,&axidma_handle,GFP_KERNEL);//申请中断err = request_irq(61,dma_mm2s_irq,IRQF_TRIGGER_RISING,"dmadev",NULL);printk(KERN_ERR"request_irq err=%d\n",err);err = request_irq(62,dma_s2mm_irq,IRQF_TRIGGER_RISING,"dmadev",NULL);printk(KERN_ERR"request_irq err=%d\n",err);return 0;
}
/** write 接口函数** */
static int dma_write(struct file *file,const char __user *buf, size_t count,loff_t *ppos)
{int err=0;printk(KERN_ERR"dma write start !\n");if(count>DMA_LENGTH){printk(KERN_ERR"the number of data is too large!\n");return 0;}copy_from_user(axidma_addr,buf,count);iowrite32(0x00001001,mm2s_cr);//open int & enable DMAiowrite32(axidma_handle,mm2s_sa);iowrite32(count,mm2s_len);//write transmission length and DMA start transmissionprintk(KERN_ERR"dma write is over!\n");return 0;
}
/** read 接口函数** */
static int dma_read(struct file *file,char __user *buf,size_t size,loff_t *ppos)
{int err=0;printk(KERN_ERR"dma read start!\n");if(size>DMA_LENGTH){printk("the number of data is not enough!\n");return 0;}iowrite32(0x00001001,s2mm_cr);//open int & enable DMAiowrite32(axidma_handle,s2mm_da);iowrite32(size,s2mm_len);//write transmission length and DMA start transmissionprintk(KERN_ERR"dma kernel read is begin!\n");// memcpy(buf, axidma_addr, size);   copy_to_user(buf, axidma_addr, size);return 0;
}
/** 初始化,用于module init** */
static int __init dmadev_init(void)
{major=register_chrdev(0,"dmadev",&dma_lops);dma_class    = class_create(THIS_MODULE,"dmadev");device_create(dma_class,NULL,MKDEV(major,0),NULL,"dmadev");printk(KERN_ERR"major dev number= %d",major);mm2s_cr  =  ioremap(DMA_BASE_ADDR+MM2S_DMACR, 4);mm2s_sr  =  ioremap(DMA_BASE_ADDR+MM2S_DMASR, 4);mm2s_sa  =  ioremap(DMA_BASE_ADDR+MM2S_SA,    4);mm2s_len =  ioremap(DMA_BASE_ADDR+MM2S_LENGTH,4);s2mm_cr  =  ioremap(DMA_BASE_ADDR+S2MM_DMACR, 4);s2mm_sr  =  ioremap(DMA_BASE_ADDR+S2MM_DMASR, 4);s2mm_da  =  ioremap(DMA_BASE_ADDR+S2MM_DA,    4);s2mm_len =  ioremap(DMA_BASE_ADDR+S2MM_LENGTH,4);printk(KERN_ERR"dma init ok!\n");return 0;
}
/**退出 用于 module exit** */
static void __exit dmadev_exit(void)
{unregister_chrdev(major,"dmadev");device_destroy(dma_class,MKDEV(major,0));class_destroy(dma_class);free_irq(dma_mm2s_irq,NULL);dma_free_coherent(NULL,DMA_LENGTH,axidma_addr,axidma_handle);iounmap(mm2s_cr);iounmap(mm2s_sr);iounmap(mm2s_sa);iounmap(mm2s_len);iounmap(s2mm_cr);iounmap(s2mm_sr);iounmap(s2mm_da);iounmap(s2mm_len);
}module_init(dmadev_init);
module_exit(dmadev_exit);MODULE_AUTHOR("TEST@dma");
MODULE_DESCRIPTION("dma driver");
MODULE_ALIAS("dma linux driver");
MODULE_LICENSE("GPL");

应用程序如下:

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>short readarray[4096];
int main(int argc , char ** argv)
{int fd; int i;int val=0;fd = open("/dev/dmadev",O_RDWR);if(fd<0) {printf("can not open file\n");}else printf("open file sucuss\n");sleep(1);read(fd,(void *)readarray,2048);sleep(1);for(i=0;i<16;i++){printf("  %hu=%hu\n",i,readarray[i]);}printf("now  exit\n");close(fd); return 0;
}

以上~

2021-08-16Zynq linux系统下的AXI DMA驱动与应用程序简单Demo实现相关推荐

  1. linux 无线网卡 免驱动,Linux系统下安装USB无线网卡驱动方法

    Linux系统下安装USB无线网卡驱动方法 具体安装过程分了如下步骤进行:确认 usb-wifi 设施型号 , 根据确认结果选择驱动信息. 安装驱动 mt7601u , 假如已经自带跳过此步骤 配置驱 ...

  2. linux系统添加打印机失败,怎么在Linux 系统下安装打印机的驱动 - 驱动管家

    关于Linux 系统相信经常使用电脑的朋友一定不陌生,它作为免费使用和自由传播的类Unix操作系统,同时也是一个性能稳定的多用户网络操作系统.关于这个免费的系统,它的版本也是非常得多.所以这个操作系统 ...

  3. linux 服务器 安装网卡驱动,Linux系统下安装Intel千兆网卡驱动

    在Intel网站直接下载的Linux驱动是e1000-5.2.52.tar.gz(版本可能会有改变),这个压缩包里面没有编译好的.o的文件,需要在Linux系统下编译之后才能使用, 因为网卡需要编译, ...

  4. linux 网卡驱动编译,在linux系统下安装编译网卡驱动的方法

    安装linux操作系统后发现没有网卡驱动,表现为 system → Administration → Network下Hardware列表为空. 以下为安装编译网卡驱动的过程,本人是菜鸟,以下是我从网 ...

  5. linux系统声卡安装教程,Linux系统下如何安装声卡驱动?

    装了几次Linux OS,当然也装了几次声卡驱动,一般来说都是安装ALSA(Adcance Linux Sound Architecture)驱动,多装几次以后就会发现非常的简单的. 首先,先决条件, ...

  6. linux怎么找网卡驱动,linux系统下如何安装网卡驱动

    首先根据网卡的型号到主板的官方或是主板的驱动盘上找一下,应该可以找到对应的linux驱动. 1 确认系统的内核版本 [root@localhost ~]# uname -r 2.6.18-8.el5P ...

  7. Kali Linux系统下无线网卡MW310UH的驱动安装教程

    Kali驱动安装教程以MW310UH无线网卡为例 本次实验使用的操作系统为:kali-linux-2022.4-vmware-amd64,运行于VMware虚拟机环境. 1. 安装必要的系统软件包 编 ...

  8. linux安装显卡驱动的run文件,Linux系统下安装NVIDIA显卡驱动(run格式文件)

    1.查看显卡是否装好 (1)运行glxinfo | grep rendering (2)如果显示"direct rendering: Yes",则已安装 2.下载驱动 我下载的就是 ...

  9. 双显卡笔记本在Linux系统下安装N卡驱动重启丢失驱动【已解决】

    PS: !!!个人测试过程所遇问题,仅供参考!!! 问题: 双显卡的笔记本电脑,为了提升电池的使用寿命,往往默认首选核心显卡,从而导致安装完成且测试通过的N卡驱动,在重启后出现驱动丢失的情况. 我个人 ...

最新文章

  1. 图片镂空算法集合[图](转)
  2. Android - 网络基础
  3. 刘志勇:微博短视频百万级高并发架构
  4. ecshop程序设置伪静态简单三步骤
  5. dubbo:reference、dubbo:service和@Service、@Reference使用情况
  6. pandas dataframe按行或列求和
  7. 【Java数据结构与算法】第二十章 Dijkstra算法和Floyd算法
  8. C语言实例:三个数从小到大排序
  9. Hadoop大数据原理与应用
  10. Ann Rheum Dis | 华科韩金祥/宁康等发现微生物失调和代谢紊乱在类风湿关节炎中的作用...
  11. 方舟生存进化怎么自建服务器?方舟生存进化自建服务器教程
  12. 如何把两个表格合并到一起
  13. java微信分享朋友圈_Java实现微信公众平台朋友圈分享功能详细代码
  14. 阿里天池大数据竞赛(一)用ODPS提取特征
  15. linux 下动手实现bash -lR 命令
  16. JAVA模拟电影票房,Neo4j入门之中国电影票房排行浅析
  17. 【HTPC】第一期jellyfin windows版使用显卡硬件转码
  18. 软件的MSDN版、OEM版、RTM版有什么不同?
  19. android root 的作用,手机ROOT和非ROOT有什么区别?ROOT后有什么好处?
  20. linux下基于ipmsg协议的飞鸽传书(一)

热门文章

  1. c语言运行后tecplot云图,tecplot执行fluent后处理截面云图显示.pdf
  2. 【三维点云】CC教程1(Context Capture)
  3. 前端架构师的相关体系内容
  4. Smart-Link配置
  5. ORACLE 表空间扩展方法,ORACLE 表空间扩展方法
  6. cics for linux,cics 5.1 for AIX 故障ERZ080035E的分析
  7. 四位二进制、十进制、四位十六进制相互转换(高位补零)python
  8. Python-断点续传
  9. Win 7 下制作 mac 系统启动U盘
  10. Moviepy时间变换time_mirror再遇‘OSError: MoviePy error: failed to read the first frame of video file‘解决示例代码