关于AM335x上GPMC驱动程序的问题

dinghuiwpf 2015-02-04 09:36:23
你好,最精调试GPMC的时候出现了一个问题,想请教一下:
就是我写的FPGA_gpmc驱动程序,,加载后没有问题,但是当应用程序调用read函数的时候,就会出现系统碰亏的情况,终端显示如下:

驱动详细代码见附件

#include <linux/init.h>
....
#include "asm/atomic.h"

#define USER_BUFF_SIZE 128

struct fpga_dev {
dev_t devt;
struct cdev cdev;
struct semaphore sem;
struct class *class;
char *user_buff;
unsigned int addr;
unsigned int data;
};

static struct fpga_dev fpga_dev;

unsigned long mem_base;
static void __iomem *fpga_base;
static void __iomem *gpmc_base;

/* GPMC register offsets */
#define GPMC_REVISION 0x00
#define GPMC_SYSCONFIG 0x10
#define GPMC_SYSSTATUS 0x14
#define GPMC_IRQSTATUS 0x18
#define GPMC_IRQENABLE 0x1C
#define GPMC_TIMEOUT_CONTROL 0x40
#define GPMC_ERR_ADDRESS 0x44
#define GPMC_ERR_TYPE 0x48
#define GPMC_CONFIG 0x50
#define GPMC_STATUS 0x54
#define GPMC_PREFETCH_CONFIG1 0x1E0
#define GPMC_PREFETCH_CONFIG2 0x1E4
#define GPMC_PREFETCH_CONTROL 0x1EC
#define GPMC_PREFETCH_STATUS 0x1F0
#define GPMC_ECC_CONFIG 0x1F4
#define GPMC_ECC_CONTROL 0x1F8
#define GPMC_ECC_SIZE_CONFIG 0x1FC
#define GPMC_ECC1_RESULT 0x200
#define GPMC_ECC_BCH_RESULT_0 0x240

#define GPMC_BASE_ADDR 0x50000000

#define GPMC_CS 2
#define GPMC_CS0 0x60
#define GPMC_CS_SIZE 0x30
#define STNOR_GPMC_CONFIG1 0x28601000
#define STNOR_GPMC_CONFIG2 0x00011001
#define STNOR_GPMC_CONFIG3 0x00020201
#define STNOR_GPMC_CONFIG4 0x08031003
#define STNOR_GPMC_CONFIG5 0x000F1111
#define STNOR_GPMC_CONFIG6 0x0F030080

static const u32 gpmc_nor[7] = {
STNOR_GPMC_CONFIG1,
STNOR_GPMC_CONFIG2,
STNOR_GPMC_CONFIG3,
STNOR_GPMC_CONFIG4,
STNOR_GPMC_CONFIG5,
STNOR_GPMC_CONFIG6,
0

};

int fpga_ioctl(struct file *flip,unsigned int cmd,unsigned int arg)
{
ssize_t status;
char write_buff[]="the gpmc driver is OK!";
switch(cmd)
{
case 0:
if(down_interruptible(&fpga_dev.sem))
return -ERESTARTSYS;
fpga_dev.addr=arg;

printk("*******write address is 0x%x********\n",fpga_dev.addr);

//up(&fpga_dev.sem);
break;

case 1:
if(down_interruptible(&fpga_dev.sem))
return -ERESTARTSYS;

fpga_dev.data=arg;
printk("*******write data is 0x%x********\n",fpga_dev.data);
//up(&fpga_dev.sem);
break;

default:
return ENOTTY;

}

read_done_xd:
{
printk("ioctl done!\n\r");
up(&fpga_dev.sem);
}
return status;
}

static ssize_t fpga_write(struct file *flip,const char __user *buff,size_t count,loff_t *f_pos)
{
ssize_t status;
size_t len = USER_BUFF_SIZE - 1;
int i,tmp;

if(count == 0)
return 0;

if(down_interruptible(&fpga_dev.sem))
return -ERESTARTSYS;
if(len > count)
len = count;

memset(fpga_dev.user_buff,0,USER_BUFF_SIZE);

if(copy_from_user(fpga_dev.user_buff,buff,len))
{
status = -EFAULT;
goto fpga_write_done;
}

/* do something with the user data */
printk("fpga_write\n");
int address = 0;
address = fpga_base+fpga_dev.addr;
tmp = fpga_dev.data;
writew(tmp,address);

printk("address = 0x%x,data=0x%x\n ",address,tmp);



fpga_write_done:
up(&fpga_dev.sem);

return status;

}


static ssize_t fpga_read(struct file *flip,char __user *buff,size_t count,loff_t *offp)
{
ssize_t status;
size_t len = USER_BUFF_SIZE - 1;
int tmp;

if(count == 0)
return 0;

if(*offp > 0)
return 0;
if(down_interruptible(&fpga_dev.sem))
return -ERESTARTSYS;

// strcpy(fpga_dev.user_buff,"fpga driver data goes here\n");
// len = strlen(fpga_dev.user_buff);

if(len > count)
len = count;

memset(fpga_dev.user_buff,0,USER_BUFF_SIZE);
printk("**********before readb********\n");

tmp = readw(fpga_base+fpga_dev.addr);
printk("fpga_read_data = 0x%x\n",tmp);

if(copy_to_user(buff,fpga_dev.user_buff,len))
{
status = -EFAULT;
goto fpga_read_done;
}

fpga_read_done:
printk("fpga_read_done_xd\n");
up(&fpga_dev.sem);

return status;
}

static int fpga_open(struct inode *inode,struct file *flip)
{
int status = 0;
if(down_interruptible(&fpga_dev.sem))
return -ERESTARTSYS;

if(!fpga_dev.user_buff)
{
fpga_dev.user_buff = kmalloc(USER_BUFF_SIZE,GFP_KERNEL);
if(!fpga_dev.user_buff)
{
printk(KERN_ALERT "fpga_open:user_buff alloc failed\n");
status = -ENOMEM;
}
}

up(&fpga_dev.sem);

return status;
}
static const struct file_operations fpga_fops = {
.owner = THIS_MODULE,
.open = fpga_open,
.read = fpga_read,
.write = fpga_write,
.unlocked_ioctl = fpga_ioctl,
};
static int __init fpga_init_cdev(void)
{
int error;
u32 val;

fpga_dev.devt = MKDEV(251,0);

error = alloc_chrdev_region(&fpga_dev.devt,0,1,"fpga");
if(error){
printk(KERN_ALERT "alloc_chrdev_region() failed:%d\n",error);
return error;
}

cdev_init(&fpga_dev.cdev,&fpga_fops);
fpga_dev.cdev.owner = THIS_MODULE;

error = cdev_add(&fpga_dev.cdev,fpga_dev.devt,1);
if(error){
printk(KERN_ALERT "cdev_add() failed:%d\n",error);
unregister_chrdev_region(fpga_dev.devt,1);
return error;
}

printk("Getting Chip Select\n");
//close CS//////////////////////
val=gpmc_cs_read_reg(GPMC_CS,GPMC_CS_CONFIG7);
val &= ~GPMC_CONFIG7_CSVALID;
gpmc_cs_write_reg(GPMC_CS,GPMC_CS_CONFIG7,val);
////////////////////////////////
val = gpmc_read_reg(GPMC_REVISION);
printk(KERN_ALERT "GPMC revision %d.%d\n",(val>>4)&0x0f,val&0x0f);

gpmc_write_reg(GPMC_IRQENABLE,0);
gpmc_write_reg(GPMC_TIMEOUT_CONTROL,0);

gpmc_cs_write_reg(GPMC_CS,GPMC_CS_CONFIG1,gpmc_nor[0]);
gpmc_cs_write_reg(GPMC_CS,GPMC_CS_CONFIG2,gpmc_nor[1]);
gpmc_cs_write_reg(GPMC_CS,GPMC_CS_CONFIG3,gpmc_nor[2]);
gpmc_cs_write_reg(GPMC_CS,GPMC_CS_CONFIG4,gpmc_nor[3]);
gpmc_cs_write_reg(GPMC_CS,GPMC_CS_CONFIG5,gpmc_nor[4]);
gpmc_cs_write_reg(GPMC_CS,GPMC_CS_CONFIG6,gpmc_nor[5]);

val = gpmc_cs_read_reg(GPMC_CS,GPMC_CS_CONFIG7);
printk("GPMC_CS_CONFIG7 value 0x%x\n",val);

int base_val = 0;
base_val = gpmc_cs_request(GPMC_CS,SZ_2K,(unsigned long *)&mem_base);
printk("base_val = 0x%x\n",base_val);
if(base_val < 0)
{
printk(KERN_ALERT "Failed request for GPMC mem for userp_e\n");
return -1;
}
printk("Got CS%d,address=%lx\n",GPMC_CS,mem_base);

if(!request_mem_region(mem_base,SZ_2K,"mem_fpga"))
{
printk(KERN_ERR "Request_mem_region failed\n");
gpmc_cs_free(GPMC_CS);
return -1;
}

fpga_base = ioremap(mem_base,SZ_2K);
//open CS/////////////////////////
gpmc_cs_configure(GPMC_CS,GPMC_ENABLE_IRQ,1);

val=gpmc_cs_read_reg(GPMC_CS,GPMC_CS_CONFIG7);
val |= GPMC_CONFIG7_CSVALID;
val |= 0x03;
gpmc_cs_write_reg(GPMC_CS,GPMC_CS_CONFIG7,val);

printk("GPMC_CS_CONFIG7=%x\n",gpmc_cs_read_reg(GPMC_CS,GPMC_CS_CONFIG7));
printk("fpga_base=0x%x\n",fpga_base);
/////////////////////////////////
return 0;
}

static int __init fpga_init_class(void)
{
struct device *device;

fpga_dev.class = class_create(THIS_MODULE,"fpga");

if(IS_ERR(fpga_dev.class))
{
printk(KERN_ALERT "class_create(fpga) failed\n");
return PTR_ERR(fpga_dev.class);
}

device = device_create(fpga_dev.class,NULL,fpga_dev.devt,NULL,"fpga");

if(IS_ERR(device))
{
class_destroy(fpga_dev.class);
return PTR_ERR(device);
}

return 0;
}

static int __init fpga_init(void)
{
printk(KERN_INFO "fpga_init()\n");
memset(&fpga_dev,0,sizeof(struct fpga_dev));
sema_init(&fpga_dev.sem,1);
if(fpga_init_cdev())
goto init_failed_1;

if(fpga_init_class())
goto init_failed_2;

return 0;

init_failed_2:
cdev_del(&fpga_dev.cdev);
unregister_chrdev_region(fpga_dev.devt,1);

init_failed_1:
return -1;
}

module_init(fpga_init);

static void __exit fpga_exit(void)
{
printk(KERN_INFO "fpga_exit()\n");

device_destroy(fpga_dev.class,fpga_dev.devt);
class_destroy(fpga_dev.class);

cdev_del(&fpga_dev.cdev);
unregister_chrdev_region(fpga_dev.devt,1);

release_mem_region(mem_base,SZ_2K);
gpmc_cs_free(GPMC_CS);
iounmap(fpga_base);

if(fpga_dev.user_buff)
kfree(fpga_dev.user_buff);
}

module_exit(fpga_exit);

MODULE_AUTHOR("Afirstech");
MODULE_DESCRIPTION("fpga driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION("0.1");

应用程序代码:
#include <sys/types.h>
.....
#define PAGE_SIZE 10

#define ADDR_SET 0
#define DATA_SET 1

int main(void)
{
int fd,i,res;
unsigned char buff[PAGE_SIZE],read_buff[20];
printf("GPMC Test version 1.0 Build on %s %s\n\r",__DATE__,__TIME__);
printf("Hello Afirstech GPMC\n\r");
fd = open(FPGA_DEV,O_RDWR);
printf("Bye Afirstech GPMC\n\r");
if(fd<0)
{
printf("Can't Open %s !\n\r",FPGA_DEV);
return -1;
}
for(i=0;i<100000000;i++);
// ioctl(fd,DATA_SET,0xbb);//setup data
ioctl(fd,ADDR_SET,0xaa);//setup address offset
write(fd,&buff,PAGE_SIZE);//write
ioctl(fd,1,read_buff);
read(fd,&read_buff,2);//read
close(fd);
return 0;
}

驱动程序加载的时候并没有问题,但应用程序只要一执行read函数,程序就会跑飞
错误代码如下:
root@ok335x:/home/forlinx# insmod fpga_gpmc.ko
[ 129.265402] fpga_init()
[ 129.267977] Getting Chip Select
[ 129.271464] GPMC revision 6.0
[ 129.274655] GPMC_CS_CONFIG7 value 0xf00
[ 129.278658] base_val = 0x0
[ 129.281475] Got CS2,address=1000000
[ 129.285162] GPMC_CS_CONFIG7=f43
[ 129.288431] fpga_base=0xe09f4000
root@ok335x:/home/forlinx# chmod 777 gpmc
root@ok335x:/home/forlinx# ./gpmc
GPMC Test version 1.0 Build on Feb 3 2015 15:47:27
Hello Afirstech GPMC
Bye Afirstech GPMC
[ 139.769459] *******write address is 0xaa********
[ 139.774313] ioctl done!
fpga_write318]
[ 139.779934] address = 0xe09f40aa,data=0x0
[ 139.779941] ioctl done!
**********before read down sem********
[ 139.792340] **********after read down sem********
[ 139.797240] *******fpga_read_addr = 0xaa
[ 139.801335] Unhandled fault: external abort on non-linefetch (0x1008) at 0xe09f40aa
[ 139.809322] Internal error: : 1008 [#1]
[ 139.813316] Modules linked in: fpga_gpmc
[ 139.817416] CPU: 0 Not tainted (3.2.0 #33)
[ 139.822059] PC is at fpga_read+0xd0/0x138 [fpga_gpmc]
[ 139.827340] LR is at console_unlock+0x170/0x1f8
[ 139.832062] pc : [<bf000238>] lr : [<c003ed98>] psr: 60000013


能不能帮我分析一下是何原因造成?
...全文
2177 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
dahaiChang 2017-10-24
  • 打赏
  • 举报
回复
驱动附件没看到啊,请问解决了么
wangxun617 2017-06-27
  • 打赏
  • 举报
回复
请问 解决了吗
hexuyangguang 2017-05-25
  • 打赏
  • 举报
回复
楼主解决了吗?

val=gpmc_cs_read_reg(GPMC_CS,GPMC_CS_CONFIG7);
val |= GPMC_CONFIG7_CSVALID;
val |= 0x03;
gpmc_cs_write_reg(GPMC_CS,GPMC_CS_CONFIG7,val);

把val |= 0x03;去掉试试!
2016-09-01
  • 打赏
  • 举报
回复
谢谢,参考一下!
xxc21cn 2015-12-24
  • 打赏
  • 举报
回复
我也遇到了同样的问题
KnightXV 2015-04-09
  • 打赏
  • 举报
回复
请问楼主问题解决了没?

21,597

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧