字符设备三种注册方式

提供三种自己写的程序至于理论网上都是大家可以参考》》》》》

 

1,早期字符注册

程序如下:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/io.h>

#define GPM4_BASE 0x110002E0

typedef struct
{
volatile unsigned long CON;
volatile unsigned long DAT;
}* GPM4_t;

static GPM4_t GPM4=NULL;

// 7 编写文件操作函数
static ssize_t led_write(struct file *fil, const char __user *buf, size_t count, loff_t *offsets)
{
// 8 接收上层数据
unsigned char ledflag;
unsigned long ret = copy_from_user(&ledflag,buf,count);

printk("driver ledflag:%d\n",ledflag);

GPM4->DAT &= ~(1<<0);
GPM4->DAT |= (!ledflag)<<0;

return ret;
}

// 4 构造file_operation文件操作集合
// 6 填充文件操作集合
static struct file_operations led_fops =
{
.owner = THIS_MODULE,
.write = led_write,
};

static unsigned int led_major;

// 2 编写驱动加载卸载函数
static int __init led_driver_init(void)
{
printk("led driver install......\n");

// 3 早期字符设备注册
// 参数1:主设备号 >0 静态注册 以写入的设备号注册
// =0 动态注册 自动分配一个设备号
// 参数2:名称 辅助识别
// 参数3:文件操作集合 驱动支持的上层操作接口
// 返回:静态注册 成功返回0 失败返回错误
// 动态注册 成功返回分配的主设备号
led_major = register_chrdev(0,"leddriver",&led_fops);

// 9 映射硬件地址到内核空间
GPM4 = ioremap(GPM4_BASE, 8);

// 10 IO配置为输出(LED)
GPM4->CON |= 0x1111<<0;
GPM4->DAT |= 0xF<<0;

return 0;
}

static void __exit led_driver_exit(void)
{
printk("led driver remove......\n");

// 9 取消硬件映射
iounmap(GPM4);

// 5 取消注册
unregister_chrdev(led_major,"leddriver");
}

// 1 指定驱动加载卸载程序
module_init(led_driver_init);
module_exit(led_driver_exit);
// GNU声明
MODULE_LICENSE("GPL");

 测试程序:

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

int main(int argc,char *argv[])
{
int led_fd;
unsigned char ledflag = 0;

if(argc!=3)
{
printf("Usage:<%s> </dev/?node> <0/1>\n",argv[0]);
return -1;
}

led_fd = open(argv[1],O_WRONLY);

ledflag = argv[2][0]-48;
write(led_fd, &ledflag,1);
}

Makefile

obj-m += leddriver.o
SOURCE = ledtest.o

CROSS_COMPLIE = arm-linux-
CC = $(CROSS_COMPLIE)gcc

KERNDIR = /file/samsung/linux-3.5
#CURDIR = $(shell pwd)
CURDIR = `pwd`

.PHONY: module clean

all: module $(SOURCE:.o=)

module:
$(MAKE) -C $(KERNDIR) M=$(CURDIR) modules

$(SOURCE:.o=):$(SOURCE)
$(CC) -o $@ $^

%.o:%.c
$(CC) -c $<

clean:
$(MAKE) -C $(KERNDIR) M=$(CURDIR) clean
rm $(SOURCE:.o=)

 

2,cdev注册

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/err.h>

#define GPM4_BASE 0x110002E0

typedef struct
{
volatile unsigned long CON;
volatile unsigned long DAT;
}* GPM4_t;

static GPM4_t GPM4=NULL;

static ssize_t led_write(struct file *fil, const char __user *buf, size_t count, loff_t *offsets)
{
unsigned char ledflag;
unsigned long ret = copy_from_user(&ledflag,buf,count);

printk("driver ledflag:%d\n",ledflag);

// 01 00 11 10 21 20 31 30
GPM4->DAT &= ~(1<<(ledflag/10));
GPM4->DAT |= (!(ledflag%10))<<(ledflag/10);

return ret;
}

static struct file_operations led_fops =
{
.owner = THIS_MODULE,
.write = led_write,
};

static dev_t led_dev;
struct cdev *led_cdev;

static int __init led_driver_init(void)
{
printk("led driver install......\n");

// register_chrdev
alloc_chrdev_region(&led_dev, 0, 1,"leddriver");

led_cdev = cdev_alloc();

led_cdev->owner = THIS_MODULE;
led_cdev->ops = &led_fops;
led_cdev->count = 1;
led_cdev->dev = led_dev;

// cdev_init(led_cdev, &led_fops);

cdev_add(led_cdev,led_dev, 1);

GPM4 = ioremap(GPM4_BASE, 8);

GPM4->CON |= 0x1111<<0;
GPM4->DAT |= 0xF<<0;

return 0;
}

static void __exit led_driver_exit(void)
{
printk("led driver remove......\n");

iounmap(GPM4);

cdev_del(led_cdev);
unregister_chrdev_region(led_dev,1);
}

module_init(led_driver_init);
module_exit(led_driver_exit);
MODULE_LICENSE("GPL");

 测试程序

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc,char *argv[])
{
int led_fd;
unsigned char ledflag = 0;

if(argc!=3)
{
printf("Usage:<%s> </dev/?node> <0/1>\n",argv[0]);
return -1;
}

led_fd = open(argv[1],O_WRONLY);

ledflag = atoi(argv[2]);
write(led_fd, &ledflag,1);
}

 

 Makefile

obj-m += leddriver.o
SOURCE = ledtest.o

CROSS_COMPLIE = arm-linux-
CC = $(CROSS_COMPLIE)gcc

KERNDIR = /file/samsung/linux-3.5
#CURDIR = $(shell pwd)
CURDIR = `pwd`

.PHONY: module clean

all: module $(SOURCE:.o=)

module:
$(MAKE) -C $(KERNDIR) M=$(CURDIR) modules

$(SOURCE:.o=):$(SOURCE)
$(CC) -o $@ $^

%.o:%.c
$(CC) -c $<

clean:
$(MAKE) -C $(KERNDIR) M=$(CURDIR) clean
rm $(SOURCE:.o=)

 3,misc注册

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/miscdevice.h>

#define GPM4_BASE 0x110002E0

typedef struct
{
volatile unsigned long CON;
volatile unsigned long DAT;
}* GPM4_t;

static GPM4_t GPM4=NULL;

static ssize_t led_write(struct file *fil, const char __user *buf, size_t count, loff_t *offsets)
{
unsigned char ledflag;
unsigned long ret = copy_from_user(&ledflag,buf,count);

printk("driver ledflag:%d\n",ledflag);

// 01 00 11 10 21 20 31 30
GPM4->DAT &= ~(1<<(ledflag/10));
GPM4->DAT |= (!(ledflag%10))<<(ledflag/10);

return ret;
}

static struct file_operations led_fops =
{
.owner = THIS_MODULE,
.write = led_write,
};

static struct miscdevice led_miscdevice =
{
.minor = MISC_DYNAMIC_MINOR,
.name = "led",
.fops = &led_fops,
};

static int __init led_driver_init(void)
{
printk("led driver install......\n");

misc_register(&led_miscdevice);

GPM4 = ioremap(GPM4_BASE, 8);

GPM4->CON |= 0x1111<<0;
GPM4->DAT |= 0xF<<0;

return 0;
}

static void __exit led_driver_exit(void)
{
printk("led driver remove......\n");

misc_deregister(&led_miscdevice);

iounmap(GPM4);
}

module_init(led_driver_init);
module_exit(led_driver_exit);
MODULE_LICENSE("GPL");

 测试

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc,char *argv[])
{
int led_fd;
unsigned char ledflag = 0;

if(argc!=3)
{
printf("Usage:<%s> </dev/?node> <0/1>\n",argv[0]);
return -1;
}

led_fd = open(argv[1],O_WRONLY);

ledflag = atoi(argv[2]);
write(led_fd, &ledflag,1);
}

 

 Makefile

obj-m += leddriver.o
SOURCE = ledtest.o

CROSS_COMPLIE = arm-linux-
CC = $(CROSS_COMPLIE)gcc

KERNDIR = /file/samsung/linux-3.5
#CURDIR = $(shell pwd)
CURDIR = `pwd`

.PHONY: module clean

all: module $(SOURCE:.o=)

module:
$(MAKE) -C $(KERNDIR) M=$(CURDIR) modules

$(SOURCE:.o=):$(SOURCE)
$(CC) -o $@ $^

%.o:%.c
$(CC) -c $<

clean:
$(MAKE) -C $(KERNDIR) M=$(CURDIR) clean
rm $(SOURCE:.o=)

 

posted @ 2017-06-02 09:39  root-linux  阅读(1643)  评论(0编辑  收藏  举报