当前位置: 代码迷 >> 驱动开发 >> 请问:linux下DMA操作,死机
  详细解决方案

请问:linux下DMA操作,死机

热度:112   发布时间:2016-04-28 10:59:52.0
请教:linux下DMA操作,死机
简介:采用DMA控制器实现s3c2440与外部FPGA通信,以FIFO为桥梁。
以字符型设备的方式编写DMA驱动程序(驱动程序如下),驱动成功挂载,应用程序也能成功运行,但是执行应用程序后ARM会死机,无法进行任何操作(现象如下);
问题:请问为什么会死机,一般linux开发时导致死机的原因有哪些?小弟比较急,谢谢回复!
现象:
[[email protected] plg]# ./dma_app

。(省略)

hello buff
[[email protected] plg]# (在此处死机,无法进行任何操作)

驱动程序:#include <linux/module.h>  
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h> //copy_to_use, copy_from_user  
#include <linux/serial_core.h>  
//#include <asm/plat-s3c/regs-serial.h>  
#include <asm/io.h> //readl, readb, writel, writeb 
#include <asm-arm/s3c2440-dma.h>
//#include <plat/dma-plat.h>
#include <mach/map.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/sysdev.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <plat/regs-dma.h>
#include <linux/device.h>

#define XDREQ0_MAJOR 239
#define XDREQ0_MINOR 0
#define dma_base S3C2410_VA_DMA
#define DMA_DISRC0 (dma_base+S3C2410_DMA_DISRC)
#define DMA_DISRCC0 (dma_base+S3C2410_DMA_DISRCC)
#define DMA_DIDST0 (dma_base+S3C2410_DMA_DIDST)
#define DMA_DIDSTC0 (dma_base+S3C2410_DMA_DIDSTC)
#define DMA_DCON0 (dma_base+S3C2410_DMA_DCON)
#define DMA_DSTAT0 (dma_base+S3C2410_DMA_DSTAT)
#define DMA_DCSRC0 (dma_base+S3C2410_DMA_DCSRC)
#define DMA_DCDST0 (dma_base+S3C2410_DMA_DCDST)
#define DMA_DMASKTRIG (dma_base+S3C2410_DMA_DMASKTRIG)

#define mydma_channel 0
#define dma_devaddr 0x55000010

MODULE_AUTHOR("hankle");  
MODULE_DESCRIPTION("s3c2440 dma driver");  
MODULE_LICENSE("GPL"); 
struct device *my_cdev;
struct class *my_class;
/*open*/
int fifo_dma_open(struct inode * inode,struct file * filp)
{
  printk("dma is open\n");
  //MOD_INC_USE_COUNT;
  return 0;
}
int fifo_dma_release(struct inode * inode,struct file * filp)
{
  printk("dma is released!\n");
  //MOD_DEC_USE_COUNT;
  //s3c2410_free_dma(mydma_channel);
  //writel(((0<<1)+0),DMA_DMASKTRIG);
  return 0;
}
/*interrupt */
/*static void dma_irq_handler(int irq, void *dev_id,struct pt_regs *regs)
{
  printk(KERN_ALERT"interrupt generated!\n");
  dma_done = 1;
}
*/

void regs_init(unsigned int dstaddr,unsigned int srcaddr)
{
  unsigned int a,b,c,d;
  writel(srcaddr,DMA_DISRC0);
  writel(((1<<1)+0),DMA_DISRCC0);
  writel(dstaddr,DMA_DIDST0);
  writel( 0 ,DMA_DIDSTC0);
  writel(((0<<31)|(0<<30)|(0<<29)|(0<<28)|(0<<27)|(0<<24)|(1<<23)|(1<<22)|(1<<20)|(640)),DMA_DCON0);  
  a = readl(DMA_DISRC0);
  b = readl(DMA_DISRCC0);
  c = readl(DMA_DIDST0);
  d = readl(DMA_DIDSTC0);
  //printk(KERN_ALERT"DISRC0 is %x,DISRCC0 is %x,DIDIST0 is %x,DIDSTC0 is %x \n",a,b,c,d);
}

ssize_t fifo_dma_read(struct file *filp, char *buff,size_t count,loff_t *f_ops)
{
  printk("fifo_dma_read start\n");
  dma_addr_t *dma_buf_virt;
  unsigned int dma_buf_phy;
  dma_buf_virt = kmalloc(count,GFP_DMA);
  dma_buf_phy = virt_to_bus(dma_buf_virt);
  printk(KERN_ALERT"distbuf address is %lx \n",dma_buf_phy);
  regs_init(dma_buf_phy,0);