linux完整的驱动组成和应用空间和内核空间之间传递参数

/*
注:soc:s5pv210
hello_drv.c
*/
//1.头文件声明
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>

#include <asm/io.h>
#include <asm/uaccess.h>
#define GPC0_BASE 0xE0200060 //led基地址


int hello_major;//主设备号
struct class *hello_cls;
struct device *hello_dev;

unsigned int *gpc0_conf;
unsigned int *gpc0_data;

//3.实现操作接口
int hello_open (struct inode *inode, struct file *filp)
{
	printk("-----^_^-----%s-----\n",__FUNCTION__);
	//led初始化
	*gpc0_conf &=~(0xff<<12);//配置输出模式
	*gpc0_conf |=0x11<<12;
	*gpc0_data &=~(0x03<<3);//配置起始灭
	/**gpc0_data |=0x03<<3;*/
	return 0;
}
int hello_release(struct inode *inode, struct file *filp)
{
	printk("-----^_^-----%s-----\n",__FUNCTION__);
	*gpc0_data &=~(0x03<<3);//关灯
	return 0;
}
ssize_t hello_write (struct file *filp, const char __user *buf, size_t size, loff_t *flags)
{
	int value;
	int ret;
	printk("-----^_^-----%s-----\n",__FUNCTION__);
	ret = copy_from_user(&value, buf, size);
	if(ret>0){
		printk("-----^_^-----copy_from_user error-----\n");
		return -EINVAL;
	}
	/*if(value){
		printk("-----^_^-----turn on led-----\n");
		*gpc0_data |=0x03<<3;//开所有灯
	}else{
		printk("-----^_^-----turn on led-----\n");
		*gpc0_data &=~(0x03<<3);//关所有灯	
	}*/
	switch(value){
		case 1://led1 on
		*gpc0_data |=0x01<<3;//开灯
		break;
		case 2://led1 off
		*gpc0_data &=~(0x01<<3);//关灯
		break;
		case 3://led2 on
		*gpc0_data |=0x01<<4;//开灯
		break;
		case 4://led2 off
		*gpc0_data &=~(0x01<<4);//关灯
		break;
		case 5://led1 led2 on
		*gpc0_data |=0x03<<3;//开灯
		break;
		case 6://led1 led2 off
		*gpc0_data &=~(0x03<<3);//关灯	
		break;
	}
	return size;
}
struct file_operations fops={
	.open					=hello_open,
	.release				=hello_release,
	.write					=hello_write,
};

//2.模块加载函数
static int __init hello_drv_init(void)
{
	int ret;//返回值
	
	printk("-----^_^-----%s-----\n",__FUNCTION__);
#if 0 
	//1、静态申请设备号
	ret = register_chrdev(254,"hello_dev",&fops);//主设备号为254
	if(ret!=0){
		printk("-----^_^-----register_chrdev error-----\n");
		return -EINVAL;
	}
#else
	//1、动态申请设备号
	hello_major =register_chrdev(0,"hello_major",&fops);
	if(hello_major<0){
		printk("-----^_^-----register_chrdev error-----\n");
		return -EINVAL;
	}
#endif
	//2、创建设备节点
	hello_cls=class_create(THIS_MODULE, "hello_drv");
	if(IS_ERR(hello_cls)){
		printk("-----^_^-----class_create error-----\n");
		ret=PTR_ERR(hello_cls);
		goto err_unregister_dev;
	}
	hello_dev =device_create(hello_cls,NULL, MKDEV(hello_major, 4),NULL,"hello_drv");
	if(IS_ERR(hello_dev)){
		printk("-----^_^-----device_create error-----\n");
		ret=PTR_ERR(hello_dev);
		goto err_class_destory;
	}	
	//4、硬件初始化-----地址映射
	gpc0_conf = (unsigned int *)ioremap(GPC0_BASE, 8);//控制寄存器和数据寄存器各4个字节
	if(IS_ERR(gpc0_conf)){
		printk("-----^_^-----ioremap error-----\n");
		ret=PTR_ERR(gpc0_conf);
		goto err_device_destory;
	}
	gpc0_data = gpc0_conf+1;
	
	return 0;
err_device_destory:
	device_destroy(hello_cls, MKDEV(hello_major, 4));
err_class_destory:
	class_destroy(hello_cls);
err_unregister_dev:
	unregister_chrdev(hello_major, "hello_major");
	return ret;
}
//3.模块卸载函数
static void __exit hello_drv_exit(void)
{
	printk("-----^_^-----%s-----\n",__FUNCTION__);
	iounmap(gpc0_conf);
	device_destroy(hello_cls, MKDEV(hello_major, 4));
	class_destroy(hello_cls);
#if 0
	unregister_chrdev(254, "hello_dev");
#else
	unregister_chrdev(hello_major, "hello_major");
#endif
	
}
//4.声明和认证
module_init(hello_drv_init);
module_exit(hello_drv_exit);
MODULE_LICENSE("GPL");
/*
Makefile
*/
KERNEL_DIR=/home/zzz/fs210/kerner_v1/linux-3.0.8
CUR_DIR=$(shell pwd)
OBJS=hello_drv
OBJS1=test
all:
        make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
        arm-none-linux-gnueabi-gcc $(OBJS1).c -o $(OBJS1)
clean:
        make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
        rm -rf $(OBJS1)
install:
        cp *.ko /opt/rootfs/drv_module
        cp $(OBJS1) /opt/rootfs/drv_module
obj-m +=$(OBJS).o

/*
应用程序
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
    int fd; 
    int temp;
    fd = open("/dev/hello_drv",O_RDWR);
    if(fd<0){
        perror("open error");
        exit
    }   
    while(1){
        printf("请输入开灯或者关灯:");
        scanf("%d",&temp);
        write(fd,&temp,sizeof(temp));
    
    }   
    close(fd);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值