21,600
社区成员
发帖
与我相关
我的任务
分享
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/types.h>
#include <linux/errno.h>
/* Standard module information, edit as appropriate */
MODULE_LICENSE("GPL");
MODULE_AUTHOR
("Xilinx Inc.");
MODULE_DESCRIPTION
("mygpio - loadable module template generated by petalinux-create -t modules");
#define DRIVER_NAME "mygpio"
/* Simple example of how to receive command line parameters to your module.
Delete if you don't need them */
unsigned myint = 0xdeadbeef;
char *mystr = "default";
module_param(myint, int, S_IRUGO);
module_param(mystr, charp, S_IRUGO);
struct mygpio_local {
unsigned long mem_start;
unsigned long mem_end;
void __iomem *base_addr;
struct device *dev;
struct cdev cdev;
};
static struct mygpio_local *lp;
struct class *mygpio_class;
static int mygpio_major;
/*文件打开函数*/
static int mygpio_open(struct inode *inode, struct file *filp){
printk("mygpio open success\n");
return 0;
}
/*文件释放函数*/
static int mygpio_release(struct inode *inode, struct file *filp){
printk("mygpio release success\n");
return 0;
}
/*文件写函数*/
static ssize_t mygpio_write(struct file *f, const char __user * buf, size_t len, loff_t * off)
{
int ret;
printk("mygpio start to write.\n");
ret=copy_from_user(lp->base_addr,buf,len);
if(ret!=0){
printk("copy from user failure\n");
return -EFAULT;
}
return len;
}
static long mygpio_ioctl(struct file *filp, unsigned int reg_num, unsigned long arg)
{
printk("reg num is %d,arg is %d\n",reg_num,arg);
iowrite32(arg,lp->base_addr+reg_num*4);
return 0;
}
static ssize_t mygpio_read(struct file *f, char __user * buf, size_t len, loff_t * off)
{
int ret;
printk("mygpio start to read\n");
ret=copy_to_user(buf,lp->base_addr,len);
if(ret!=0){
printk("copy to user failure\n");
return -EFAULT;
}
return len;
}
/*文件操作结构体*/
static const struct file_operations mygpio_fops={
.owner = THIS_MODULE,
.open = mygpio_open,//打开设备函数
.write = mygpio_write,
.read = mygpio_read,
.unlocked_ioctl=mygpio_ioctl,
.release= mygpio_release,//释放设备函数
};
static void mygpio_cdev_setup_cdev(struct mygpio_local *devp, int minor){
int err;
dev_t devno = MKDEV(mygpio_major, minor);/*构造设备号*/
cdev_init(&devp->cdev, &mygpio_fops);/*初始化cdev设备*/
devp->cdev.owner = THIS_MODULE;/*使驱动程序属于该模块*/
devp->cdev.ops = &mygpio_fops;/*cdev连接file_operations指针*/
err = cdev_add(&devp->cdev, devno, 1);/*将cdev注册到系统中*/
if (err)
printk(KERN_NOTICE "mygpio: error in cdev_add()\n");
}
static int mygpio_probe(struct platform_device *pdev)
{
struct resource *r_mem; /* IO mem resources */
struct device *dev = &pdev->dev;
dev_t devno;
int rc = 0;
int ret;
dev_info(dev, "Device Tree Probing\n");
/* Get iospace for the device */
r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r_mem) {
dev_err(dev, "invalid address\n");
return -ENODEV;
}
lp = (struct mygpio_local *) kmalloc(sizeof(struct mygpio_local), GFP_KERNEL);
if (!lp) {
dev_err(dev, "Cound not allocate mygpio device\n");
return -ENOMEM;
}
dev_set_drvdata(dev, lp);
lp->mem_start = r_mem->start;
lp->mem_end = r_mem->end;
if (!request_mem_region(lp->mem_start,
lp->mem_end - lp->mem_start + 1,
DRIVER_NAME)) {
dev_err(dev, "Couldn't lock memory region at %p\n",
(void *)lp->mem_start);
rc = -EBUSY;
goto error1;
}
lp->base_addr = ioremap(lp->mem_start, lp->mem_end - lp->mem_start + 1);
if (!lp->base_addr) {
dev_err(dev, "mygpio: Could not allocate iomem\n");
rc = -EIO;
goto error2;
}
dev_info(dev,"mygpio at 0x%08x mapped to 0x%08x",
(unsigned int __force)lp->mem_start,
(unsigned int __force)lp->base_addr);
ret=alloc_chrdev_region(&devno,0,1,"mygpio");//分配设备号
if(ret<0){
printk("mygpio: allocate devno failed\n");
return ret;
}
mygpio_major=MAJOR(devno);
//用于创建/dev目录下的设备节点
mygpio_class=class_create(THIS_MODULE,"mygpio_class");
if(IS_ERR(mygpio_class)){
printk("mygpio_class: create class error\n");
return -1;
}
lp->dev=device_create(mygpio_class,NULL,devno,NULL,"mygpio");
mygpio_cdev_setup_cdev(lp,0);
return 0;
error2:
release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1);
error1:
kfree(lp);
dev_set_drvdata(dev, NULL);
return rc;
}
static int mygpio_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1);
kfree(lp);
dev_set_drvdata(dev, NULL);
return 0;
}
#ifdef CONFIG_OF
static struct of_device_id mygpio_of_match[] = {
{ .compatible = "xlnx,ww-gpio-1.00.a", },
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(of, mygpio_of_match);
#else
# define mygpio_of_match
#endif
static struct platform_driver mygpio_driver = {
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = mygpio_of_match,
},
.probe = mygpio_probe,
.remove = mygpio_remove,
};
static int __init mygpio_init(void)
{
printk("<1>Hello module mygpio.\n");
printk("<1>Module parameters were (0x%08x) and \"%s\"\n", myint,
mystr);
return platform_driver_register(&mygpio_driver);
}
static void __exit mygpio_exit(void)
{
platform_driver_unregister(&mygpio_driver);
printk(KERN_ALERT "Goodbye module mygpio.\n");
}
module_init(mygpio_init);
module_exit(mygpio_exit);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <signal.h>
int fd1,fd2;
void dma_data_read(void)
{
char buffer[4096];
int i;
printf("start to read !\n");
read(fd1,&buffer,sizeof(buffer));//从内核空间读出dma传送的数据并保存在buffer中
//打印出保存的数据,验证传输的数据是否正确是否正确
for(i=0;i<4096;i++)
{
printf("buffer[%d]=%d,\n",i,buffer[i]);
}
}
int main(int argc, char **argv)
{
printf("Test start!\n");
int gpiodata;
int Oflags;
int ret;
signal(SIGIO,dma_data_read);
fd1=open("/dev/s2mmdma",O_RDWR);//打开s2mmdma设备
if(fd1<0){
printf("can not open device s2mmdma!\n");
return 0;
}
fd2=open("/dev/mygpio",O_RDWR);//打开mygpio设备
if(fd2<0){
printf("can't open device mygpio!\n");
}
//建立异步通知机制,当dma通道传输完成时,会通过异步通知机制告诉应用程序去读数据
ret=fcntl(fd1,F_SETOWN,getpid());
if(ret<0){
printf("can't fcntl_1!\n");
}
Oflags=fcntl(fd1,F_GETFL);
printf("Oflags is : %d\n",Oflags);
if(Oflags<0){
printf("can't fcntl_2\n");
}
ret=fcntl(fd1,F_SETFL,Oflags | FASYNC);
if(ret<0){
printf("can't fcntl_3\n");
}
//
printf("input gpio data:\n");
scanf("%d",&gpiodata);
ioctl(fd1,1,4096); //第二个参数怎定为1,第三个参数是dma传输的长度 以字节为单位 当把传输的字节长度写入dma相应的寄存器后,dma传输就绪(详见pg021)
//write(fd2,&gpiodata,sizeof(gpiodata));
ioctl(fd2,0,gpiodata);//控制gpio的输出,开始产生数据
sleep(1);
close(fd1);
close(fd2);
return 0;
}