linux ---------驱动开发遇到的问题及解决方法
来源:互联网 发布:淘宝女装软文 编辑:程序博客网 时间:2024/06/18 17:24
(1)今天有写了下设备驱动,当然首先是自己建立一个IP核,功能很简单,就是控制8个LED灯的,所以设置了一个寄存器,添加IP核,编译,XPS下载BIT文件测试了,一切正常。
(2) 自然就是编写linux驱动了,通过生成的.ko文件,一切正常,/dev/led_ctrl_dev有了,sys/class下面也有了led_ctrl_dev。总之,insmod ,rmmod 都没问题。
(3) 上层驱动代码的编写,read()读取LED灯的状态,没问题,write()函数感觉没得效果,根本没有执行驱动代码中的 led_write()函数,因为我每次实际写入的值为上层代中传递过来的,可是每次都是FFFFFFFFFF。。。打开文件的时候用的也是O_RDWR 啊
#include <linux/platform_device.h>#include <linux/module.h>#include <linux/cdev.h>#include <linux/ioport.h>#include <linux/of.h>#include <linux/fs.h>#include <asm/io.h>#include <linux/slab.h>#include <linux/device.h>#include <linux/kernel.h>#define LED_PHY_ADDR 0x79c00000#define DEVICE_NAME "led_ctrl_dev"struct led_dev{ struct cdev cdev;/*字符设备*/ unsigned char value;};struct led_dev *led_devp;static void __iomem *LED_Regs;int led_major=0;struct class *my_class;struct device *my_device;MODULE_AUTHOR("xiao gaogao");MODULE_LICENSE("Dual BSD/GPL");static int led_open(struct inode *inode,struct file * filp){ return 0;}
static int led_release(struct inode *inode,struct file *filp){ return 0;}
static ssize_t led_read(struct file *filp,char *buffer,size_t length,loff_t *offset){/* int i=0; for (i=0;i<4;i++) { *(buffer+i) = (char) ioread8(LED_Regs+i); }*/ int i=0; unsigned long value=0; value= ioread32(LED_Regs); for(i=0;i<4;i++) { buffer[i]=value>>(i*8); } return value;}
static ssize_t led_write(struct file *filp,char *buffer,size_t length,loff_t *offset){/* int i=0; for (i=0;i<4;i++) { iowrite8(*(buffer+i),LED_Regs+i); } */ int i=0; unsigned long value=0; value=(buffer[3]<<24) | (buffer[2]<<16) |( buffer[1]<<8) | (buffer[0]); iowrite32(55,LED_Regs); return value;}
static int led_ioctl(struct file *filp,unsigned int reg_num,unsigned long args){ return 0;}
static const struct file_operations led_fops ={ .owner =THIS_MODULE, .open =led_open, .release =led_release, .read =led_read, .write =led_write, //.ioctl =led_ioctl,};
static void led_setup_cdev(struct led_dev *dev,int index){ int err,devno =MKDEV(led_major,index); cdev_init(&dev->cdev,&led_fops); dev->cdev.owner = THIS_MODULE; dev->cdev.ops=&led_fops; err =cdev_add(&dev->cdev,devno,1); if(err) { printk("cdev_add ERROR\n"); }//for udev my_class = class_create(THIS_MODULE,DEVICE_NAME); if(IS_ERR(my_class)) { printk("Err: failed in creating class:\n"); return ; } my_device=device_create(my_class,NULL,devno,NULL,DEVICE_NAME); if(IS_ERR(my_device)) { printk("Err:failed in device_create fucntion\n"); }}
static int led_init(void){ dev_t dev; int result; LED_Regs = ioremap(LED_PHY_ADDR,1); printk("led_ctrl: Access addresss to device is :0x%x\n",(unsigned int)LED_Regs); if(LED_Regs ==NULL) { printk("led_ctrl Access addresss is NULL\n"); return -EIO; } dev=MKDEV(led_major,0); alloc_chrdev_region(&dev,0,1,"LED"); led_major=MAJOR(dev); led_devp = kmalloc(sizeof(struct led_dev),GFP_KERNEL); if(!led_devp) { result = -ENOMEM; return 0; } memset(led_devp,0,sizeof(struct led_dev)); led_setup_cdev(led_devp,0); iowrite32(55,LED_Regs); return 0; }
static int led_exit(void){ cdev_del(&led_devp->cdev); kfree(led_devp); device_destroy(my_class,MKDEV(led_major,0)); class_unregister(my_class); class_destroy(my_class); unregister_chrdev_region(MKDEV(led_major,0),1); printk("rm seucessfull\n");}
module_init(led_init);module_exit(led_exit);
------------------------------------------------------------------------------------------------------------------------------#include <stdio.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>int main(){ int led_fp; int i=0,j=0; unsigned char write_buff[4]={0}; unsigned char read_buff[4]={0}; unsigned long write_value=0; led_fp=open("/dev/led_ctrl_dev",O_RDWR); if(led_fp<0) { printf("open err\n"); return 0; }else { printf("open sucess\n"); } for(i=0;i<5;i++) { read(led_fp,read_buff,sizeof(read_buff)); printf("read from led =0x"); for(j=0;j<4;j++) { printf("%x",read_buff[j]); } printf("\n"); printf("input the led_value\n"); scanf("%x",&write_buff[0]); printf("writer to led =0x"); for(j=0;j<4;j++) { printf("%x",write_buff[j]); } printf("\n"); write_value=write(led_fp,write_buff,4); printf("write_value=%x\n",write_value); } close(led_fp); return 0;}
今天又仔细研究了下,终于搞定了,看来还是得自己研究代码和原理才是关键:
问题也很简单,就是只能读设备,却不能写设备,从执行的结果页看的出来,当上层应用程序调用write()(led_ctrl_app.c 文件中)数的时候,根本没有调用驱动层的write ()在 led_ctrl.c中)。所以找为什么,首先就是那个file_operations这个结构体了,因为这两个函数是靠这个结构体里面的指针进行关联的。所以我去查了下包含file_operations的头文件linux/fs.h文件。大家可不要以为这个文件在你的PC机上的linux系统里的哦,确切的说应在Digilent-linux-3.3这个内核下面的/inlcude/linux/fs.h中的。找到它的定义如下:
truct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, loff_t, loff_t, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
long (*fallocate)(struct file *file, int mode, loff_t offset,
loff_t len);
};
这个write函数的参数(struct file *, const char __user *, size_t, loff_t *);,于是修改了led_ctrl.c文件中的write函数的参数。在我的文件中,我也写了iotcl函数的,可是这个函数连make的是都过不了,原因也在于此,人家结构体里面定义的是 long (*unlocked_ioctl),所以写的函数也得相应的改改,至于我之前为什么写的是iotcl,很简单,我抄的<linux设备驱动开发详解》的,它用的内核和我们这里的Digilent-linuxXXX内核不一样哇,所以源码有些小不一样也是很正常。
- linux ---------驱动开发遇到的问题及解决方法
- Linux驱动开发--Linux驱动开发遇到的问题
- linux遇到的问题及解决方法
- 关于在2440上移植rtl8192和rtl8188cus linux驱动遇到的问题及解决方法!!!
- 遇到的问题及解决方法
- 遇到的问题及解决方法
- 最近开发中遇到的DLL问题思考及解决方法
- Web Part 开发中遇到的问题及解决方法
- ssh框架开发中遇到的部分问题及解决方法
- 开发某企业网站遇到的问题及解决方法
- android 开发中遇到的问题及解决方法
- android 开发中遇到的问题及解决方法
- SSH开发中遇到的问题及解决方法
- android 开发中遇到的问题及解决方法
- delphi 开发中遇到的DLL问题思考及解决方法
- delphi 开发中遇到的DLL问题思考及解决方法
- cgi开发中遇到的一些问题及解决方法
- 开发中遇到的小问题及解决方法
- MFC view显示Png图片(bitmap方式显示)
- 在博创三剑客up-star2410平台上,做的qt的例子
- help(json)
- eclipse创建2dx项目
- finally——return的执行顺序问题
- linux ---------驱动开发遇到的问题及解决方法
- 内线HR揭秘:如何顺利过网申
- bash: test1: command not found
- Effective C++ 条款31: 千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针的引用
- Json概述以及python对json的相关操作
- Appro DM368x IPNC 4.0 开发环境配置
- C++学习计划
- 关于SQL Server的两个递归查询
- 使用模板有什么缺点?如何避免?