从应用层的mmap到驱动层的mmap

吐舌头应用层

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <strings.h>
#include <sys/mman.h>

int main(int argc, char **argv)
{
	if(2 != argc)
	{
		printf("Usage: %s <file>\n", argv[0]);
		return 0;
	}

	int fd = open(argv[1], O_RDWR);
	if(-1 == fd)
	{
		perror("open");
		return -1;
	}
	// 将fd代表的设备文件映射到用户虚拟地址空间
	char *q = mmap(NULL, 10240, PROT_WRITE|PROT_READ , MAP_SHARED, fd, 0);
	if( MAP_FAILED == q)
	{
		perror("mmap");
		return -1;
	}
	int *p = (int*)(q+0x0c44);
	
	while(1)
	{
		*p = 1<<7;
		sleep(1);
		sync();
		*p &= ~(1<<7);
		sleep(1);
		sync();
	}


	close(fd);
}

吐舌头驱动层

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <asm/io.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <asm/uaccess.h> 
#include <linux/highmem.h> 
#include <asm/kmap_types.h>

MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("a simple driver example!");

typedef struct leddat{
	int *baseaddr;
	int pin;
}LEDDAT; 

struct led{
	dev_t num;
	struct cdev *mycdev;

	LEDDAT leds[4];
}MYLED;

static int myled_open(struct inode *inodep, struct file *filep)
{
	int i = 4;
	printk("led open called\n");

	MYLED.leds[0].baseaddr = ioremap(0x11000c40, 8);
	MYLED.leds[0].pin = 7;
	MYLED.leds[1].baseaddr = ioremap(0x11000c20, 8);
	MYLED.leds[1].pin = 0;
	MYLED.leds[2].baseaddr = ioremap(0x114001E0, 8);
	MYLED.leds[2].pin = 4;
	MYLED.leds[3].baseaddr = ioremap(0x114001E0, 8);
	MYLED.leds[3].pin = 5;
//	*MYLED.gpx2con = *MYLED.gpx2con &~(0xf<<28)  |   1<<28;
	while(i--)
		iowrite32((ioread32(MYLED.leds[i].baseaddr)&~(0xf<<(MYLED.leds[i].pin*4))) | 1<<(MYLED.leds[i].pin*4) ,MYLED.leds[i].baseaddr);

	return 0;
}

char buf[100] = {"hello"};

static ssize_t myled_read (struct file *f, char __user *p, size_t n, loff_t *off)
{
	if(copy_to_user(p, buf, 5))
	{
		return -EFAULT;
	}

	return 5;
}

static ssize_t myled_write (struct file *f, const char __user *p, size_t n, loff_t *off)
{
	if(copy_from_user(buf, p, n))
	{
		return -EFAULT;
	}

	return n;
}

#define ON   _IOW('L', 0, int)
#define OFF  _IOW('L', 1, int)
#define XXX  _IOW('L', 2, int)

static long myled_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
	int *dataaddr = MYLED.leds[arg].baseaddr+1;
	int pin = MYLED.leds[arg].pin;

	switch(cmd)
	{
	case ON:
		iowrite32((ioread32(dataaddr) | 1<<pin ), dataaddr);
		break;
	case OFF:
		iowrite32((ioread32(dataaddr) & ~(1<<pin)) ,dataaddr);
		break;
	case XXX:
		printk("unknow cmd\n");
		break;
	}

	return 0;
}

static int myled_release(struct inode *inodep, struct file *filep)
{
	int i = 4;
	printk("led closed\n");

	while(i--)
		iounmap(MYLED.leds[i].baseaddr);

	return 0;
}

int myled_mmap(struct file *f, struct vm_area_struct *vma)
{// 以页对其映射
	return remap_pfn_range(vma, vma->vm_start, 0x11000000>>PAGE_SHIFT, 
		vma->vm_end-vma->vm_start, 
		vma->vm_page_prot);
}

struct file_operations myops = {
	.owner = THIS_MODULE,
	.open = myled_open,
	.unlocked_ioctl  = myled_ioctl,
	.read = myled_read,
	.write = myled_write,
	.mmap = myled_mmap,
	.release = myled_release
};

static int __init mymodule_init(void)
{
	int ret = 0;
	printk("led module in\n");


	//request dev num
	ret = alloc_chrdev_region(&MYLED.num, 0, 1, "leddddddddddd");
	if(ret)
	{
		printk("devnum alloc fail!\n");
		return ret;
	}
	printk("num: %d\n", MAJOR(MYLED.num) );

	//create cdev object
	MYLED.mycdev =  cdev_alloc();
	if(NULL==MYLED.mycdev)
	{
		printk("alloc cdev fail!\n");
		goto cdev_alloc_out;
	}

	//init cdev ops
	cdev_init(MYLED.mycdev,  &myops);
	MYLED.mycdev->owner = THIS_MODULE;

	//register cdev into kernel
	ret = cdev_add(MYLED.mycdev, MYLED.num, 1);
	if(ret)
	{
		printk("add cdev fail!\n");
		goto cdev_add_out;
	}

	return 0;


cdev_add_out:
	kfree(MYLED.mycdev);
cdev_alloc_out:
	unregister_chrdev_region(MYLED.num, 1);

	return ret;
}

static void __exit mymodule_exit(void)
{
	//unregister cdev from kernel
	cdev_del(MYLED.mycdev);
	//release cdev object
	kfree(MYLED.mycdev);
	//release dev num
	unregister_chrdev_region(MYLED.num, 4); 

	printk("led module release\n");
}


module_init(mymodule_init);
module_exit(mymodule_exit);





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值