天嵌 ARM开发社区

 找回密码
 注册
查看: 2461|回复: 1

请教2440+FPGA采集图像数据的问题,help me!!

[复制链接]
快意人生 发表于 2012-8-1 16:38:04 | 显示全部楼层 |阅读模式
2440核心板+自制地板+外挂FPGA。
FPGA片选使用nGCS1,OE和WE挂在2440的OE和WE上,中断采用EINT4. FPGA数据准备好后发中断通知ARM读取。
现在的问题是:
    1、在驱动中能检测到中断,在驱动中用ioremap进行了内存映射,然后copy_to_user但感觉数据不对,显示出来的图像是乱的(可以说不成其为图)
    2、不知道FPGA接在nGCS1上,是不是使用0x08000000起始的这段地址?
    3、如果采用中断方式该如何实现?我使用
            dmabuf = dma_alloc_coherent(NULL, PIC_DATA_SIZE, dmaphys, GFP_KERNEL)函数时老是报错
驱动源码如下:
/*======================================================================
    A fpgadrv driver as a char device drivers  
   
    The initial developer of the original code is wangxpin
    <wangxpin_cq@126.cn>. qq:468077776 . All Rights Reserved.
======================================================================*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>   //readb readw
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <mach/regs-gpio.h>


#define  irq_num            IRQ_EINT4  //(外部中断4)
#define EXT_FALLING_EDGE    2   

#define fpgadrv_SIZE        0x100000    /*全局内存最大0x100000字节*/
#define MEM_CLEAR 0x1  /*清0全局内存*/
#define fpgadrv_MAJOR 260    /*预设的fpgadrv的主设备号*/

//
#define FPGA_BASE_PHY_ADDR   0x08000000  //nGCS1
#define FPGA_MAXADDR         0x080FFFFE  //20 bit addr
#define PIC_OFFSET           0xE0000     //
#define PIC_DATA_SIZE        384*288*2


/*fpgadrv设备结构体*/
struct fpgadrv_dev                                    
{                                                        
  struct cdev cdev; /*cdev结构体*/                       
  unsigned char mem[fpgadrv_SIZE]; /*全局内存*/        
};



static char drv_name[] = "fpgadrv";
static struct resource *fpga_mem;
static void __iomem     *fpga_base;   //FPGA线性地址
static int fpgadrv_major = fpgadrv_MAJOR;
struct fpgadrv_dev *fpgadrv_devp; /*设备结构体指针*/
spinlock_t pgd_lock = SPIN_LOCK_UNLOCKED;


wait_queue_head_t wq; /* global variable */
DECLARE_WAIT_QUEUE_HEAD (wq);
static int flag=0;



//设置中断处理程序*/
static  irqreturn_t  irq_handle(int irq, void *devid)
{
         
        if(flag == 0)
          {
            flag = 1;
            wake_up_interruptible(&wq);
          }
        
        return IRQ_HANDLED;
}


/*EINT4中断模式设置*/
static void init_interrupt(void)
{   
     int ret;   
    // printk(KERN_INFO "init_interrupt::interrupt!\n");
       s3c2410_gpio_cfgpin(S3C2410_GPF4,S3C2410_GPF4_EINT4);  
       set_irq_type(IRQ_EINT4,EXT_FALLING_EDGE);//设置中断4 触发方式
        disable_irq(IRQ_EINT4);  
             enable_irq(IRQ_EINT4);  
   ret=request_irq(IRQ_EINT4,irq_handle,IRQF_SHARED,drv_name,1);//注册中断4   
  if(ret<0)  
   {  
       printk(KERN_INFO "init_interrupt::IRQ %d can not request\n",IRQ_EINT4);  
        return ;  
   }  
     
      init_waitqueue_head(&wq);
}

/*文件打开函数*/
int fpgadrv_open(struct inode *inode, struct file *filp)
{

  /*将设备结构体指针赋值给文件私有数据指针*/
  filp->private_data = fpgadrv_devp;
  fpga_base =ioremap_nocache(FPGA_BASE_PHY_ADDR+PIC_OFFSET,PIC_DATA_SIZE*2);//verify  mmap corrected
  if(fpga_base == NULL)
   {
    printk(KERN_INFO  "fpgadrv_open::remapped FPGA address error\n");
    return -1;
   }
  else
   printk(KERN_INFO  "remapped FPGA address= 0x%8x\n", (int)fpga_base);
   init_interrupt();
   //////
  
  return 0;
}
/*文件释放函数*/
int fpgadrv_release(struct inode *inode, struct file *filp)
{
  iounmap(fpga_base);
  return 0;
}

/* ioctl设备控制函数 */
static int fpgadrv_ioctl(struct inode *inodep, struct file *filp, unsigned
  int cmd, unsigned long arg)
{
  struct fpgadrv_dev *dev = filp->private_data;/*获得设备结构体指针*/

  switch (cmd)
  {
    case MEM_CLEAR:
      memset(dev->mem, 0, fpgadrv_SIZE);      
      printk(KERN_INFO "fpgadrv is set to zero\n");
      break;

    default:
      return  - EINVAL;
  }
  return 0;
}

/*读函数*/
static ssize_t fpgadrv_read(struct file *filp, char __user *buf, size_t size,
  loff_t *ppos)
{
    unsigned long flags; //能从中断上下文中被调用
    //printk(KERN_ALERT  "FPGA line address= 0x%8x\n", (int)fpga_base);
    wait_event_interruptible(wq,flag==1);
    flag = 0;
    spin_lock_irqsave(&pgd_lock, flags);//加锁
    copy_to_user(buf,(char *)fpga_base,size);
    spin_unlock_irqrestore(&pgd_lock, flags);//解锁
   
return size;
}

/*写函数*/
static ssize_t fpgadrv_write(struct file *filp, const char __user *buf,
  size_t size, loff_t *ppos)
{
  
  return ret;
}

static loff_t fpgadrv_llseek(struct file *filp, loff_t offset, int orig)
{
    return 0;
}


static const struct file_operations fpgadrv_fops =
{
  .owner = THIS_MODULE,
  .llseek = fpgadrv_llseek,
  .read = fpgadrv_read,
  .write = fpgadrv_write,
  .ioctl = fpgadrv_ioctl,
  .open = fpgadrv_open,
  .release = fpgadrv_release,
};


static void fpgadrv_setup_cdev(struct fpgadrv_dev *dev, int index)
{
  int err, devno = MKDEV(fpgadrv_major, index);

  cdev_init(&dev->cdev, &fpgadrv_fops);
  dev->cdev.owner = THIS_MODULE;
  dev->cdev.ops = &fpgadrv_fops;
  err = cdev_add(&dev->cdev, devno, 1);
  if (err)
    printk(KERN_NOTICE "Error %d adding LED%d", err, index);
  else
    printk(KERN_NOTICE "fpgadrv_setup_cdev success--cdev_add");
}



/*设备驱动模块加载函数*/
int fpgadrv_init(void)
{
  int result;
  dev_t devno = MKDEV(fpgadrv_major, 0);

  /* 申请设备号*/
  if (fpgadrv_major)
    result = register_chrdev_region(devno, 1, drv_name);
  else  /* 动态申请设备号 */
  {
    result = alloc_chrdev_region(&devno, 0, 1, drv_name);
    fpgadrv_major = MAJOR(devno);
  }  
  if (result < 0)
   {
    printk(KERN_NOTICE "alloc_chrdev_region error");
    return result;
    }
  /* 动态申请设备结构体的内存*/
  fpgadrv_devp = kmalloc(sizeof(struct fpgadrv_dev), GFP_KERNEL);
  if (!fpgadrv_devp)    /*申请失败*/
  {
    result =  - ENOMEM;
    printk(KERN_NOTICE "kmalloc(sizeof(struct fpgadrv_dev), GFP_KERNEL)  error");
    goto fail_malloc;
  }
  memset(fpgadrv_devp, 0, sizeof(struct fpgadrv_dev));
  
  fpgadrv_setup_cdev(fpgadrv_devp, 0);
       
fpga_mem=request_mem_region(FPGA_BASE_PHY_ADDR, fpgadrv_SIZE, "FPGAMEM");//向内核申请内存资源   
     if (fpga_mem == NULL) {   
        printk("failed to get fpga_mem memory region\n");   
        return -ENOENT;   
    }   
    printk("request_mem_region success\n");  
  

   return 0;
  fail_malloc: unregister_chrdev_region(devno, 1);
  return result;
}

/*模块卸载函数*/
void fpgadrv_exit(void)
{
  cdev_del(&fpgadrv_devp->cdev);   /*注销cdev*/
  kfree(fpgadrv_devp);     /*释放设备结构体内存*/
  release_resource(fpga_mem);  
  kfree(fpga_mem) ;  
  disable_irq(IRQ_EINT4);

  free_irq(IRQ_EINT4,NULL);

  unregister_chrdev_region(MKDEV(fpgadrv_major, 0), 1); /*释放设备号*/
}

MODULE_AUTHOR("wangxpin");
MODULE_LICENSE("Dual BSD/GPL");

module_param(fpgadrv_major, int, S_IRUGO);

module_init(fpgadrv_init);
module_exit(fpgadrv_exit);

Rick.w 发表于 2012-8-1 20:29:47 | 显示全部楼层
哥们厉害啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号-2 )

GMT+8, 2024-10-2 06:03 , Processed in 1.023372 second(s), 18 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表