which is mdev
/sbin/mdev
自动创建设备结点
1.Busybox添加支持mdev
2.Rootfs/etc/rcS添加: mount -a #linux会自动解析fstab
3.Rootfs/etc/rcS添加fstab
4.fstab文件添加sysfs和proc支持(下面两句话是创建设备结点的必要条件)
proc /proc proc
defaults 0 0
#把/proc挂接成 proc 文件系统的入口
sysfs /sys sysfs
defaults 0 0
#把/sys挂接成 sysfs 文件系统的入口
5.Rootfs/etc/rcS添加:
echo /sbin/mdev >
/proc/sys/kernel/hotplug
6.驱动代码如下:
struct class *mycls =
class_create(THIS_MODULE, "tarena");
//生成新目录/sys/class/tarena/tarena
device_create(mycls, NULL, MKDEV(major,
minor), NULL, "myled");
设备结点:/dev/myled, 主次设备号分别为major, minor
类销毁
.销毁设备驱动创建的对应的设备类
.void class_destroy(struct class
*cls);
--cls:待销毁的设备类
设备的创建和销毁
.删除对应的设备文件
.void device_destory(struct class *class,
dev_t devt);
--
class:待销毁的设备所属设备类
--
devt:待销毁的设备的设备号(包括主设备号和次设备号)
vi /etc/fstab
注释掉proc、sysfs
ls /dev/
reboot开发板
ls /dev/
下面什么都没有
打开proc、sysfs
vi /etc/init.d/rcS
#!/bin/sh
# This is the fisrt script called by init process
/bin/mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev >
/proc/sys/kernel/hotplug
mdev -s #执行mdev,使之执行创建设备结点
#include< linux/init.h >
#include< linux/module.h >
#include< linux/fs.h >
#include< linux/device.h >
#inlcude< linux/cdev.h >
#include< asm/gpio.h >
#include< plat/gpio-cfg.h >
#include< linux/uaccess.h >
//定义硬件的数据结构
struct led_resource
{
int gpio;
char *name;
}
初始化LED灯的资源信息
staitc struct led_resoure led_info[] =
{
[0] = {
.gpio = S5PV210_GPC1[3],
.name = "LED1"
},
[1] = {
.gpio = S5PV210_GPC1[4],
.name = "LED2"
}
}
#define LED_ON 0x100001
//开LED命令
#define LED_OFF 0x100002
//关LED命令
#define LED_ON1 0x100002
//开LED命令1
#define LED_OFF1 0x100002
//关LED命令1
#define LED_READ 0x100002
//LED读
#define LED_WRITE 0x100002 //LED写
staitc int major;
staitc struct cdev led_cdev; //分配字符设备
staitc struct class *cls ; //记录树枝的设备类
staitc int led_open(struct inode *inode, struct file
*file)
{
//1.申请GPIO
//2.配置GPIO为输出, 输出0
int i ;
for(i = 0; i < ARRAY_SIZE(led_info); i++)
{
gpio_request(led_info[i].gpio,
led_info[i].name);
gpio_direction_output(led_info[i].gpio,
0);
}
printf("%s\n", __func__);
}
staitc int led_close(struct inode *inode, struct file
*file)
{
//1.配置GPIO为输出, 输出0
//2.释放GPIO
int i ;
for(i = 0; i < ARRAY_SIZE(led_info); i++)
{
gpio_direction_output(led_info[i].gpio, 0);
gpio_free(led_info[i].gpio);
}
printf("%s\n", __func__);
}
staitc int led_ioctl(struct inode
*inode,
struct file *file,
unsigned cmd,
unsigned long arg)
{
//解析cmd
switch(cmd)
{
case LED_ON:
{
int i;
for(i = 0; i < ARRAY_SIZE(led_info); i++)
{
gpio_set_value(led_info[i].gpio, 1);
}
}
break;
case LED_OFF:
{
int i;
for(i = 0; i < ARRAY_SIZE(led_info); i++)
{
gpio_set_value(led_info[i].gpio, 0);
}
}
break;
case LED_ON1:
{
int index; //内核缓冲区
copy_from_user(&index, (int *)arg, 4);
if(index == 1)
gpio_set_value(led_info[0].gpio, 1);
else if(index == 2)
gpio_set_value(led_info[1].gpio, 1);
}
break;
case LED_OFF1:
{
int index; //内核缓冲区
copy_from_user(&index, (int *)arg, 4);
if(index == 1)
gpio_set_value(led_info[0].gpio, 0);
else if(index == 2)
gpio_set_value(led_info[1].gpio, 0);
}
break;
case LED_READ:
{
int rdata = 0xaa;
copy_to_user((int*)arg, &rdata, 4);
}
break;
case LED_WRITE:
{
int wdata ;
copy_from_user( &rdata,(int*)arg, 4);
printk("%s: wdata = %#x\n", __func__, wdata);
}
break;
}
}
//分配驱动操作集合
staitc struct file_operations led_fops
=
{
.onwer = THIS_MODULE,
.open = led_open, //申请GPIO,配置GPIO
.release = led_close,
//配置GPIO, 释放GPIO
.ioctl = led_ioctl //控制LED
}
static int led_init(void)
{
dev_t dev;
//1.申请设备号
alloc_chrdev_region(&dev, 0, 1, "leds");
major = MAJOR(dev);
//2.初始化cdev
cdev_init(&led_cdev, &led_fops);
//3.注册cdev
cdev_add(&led_cdev, dev, 1);
//4.自动创建设备结点
cls = class_create(THIS_MODULE, "tarena");
//生成树枝
device_create(cls, NULL, dev, NULL, "myled");
return 0 ;
}
staitc void led_exit(void)
{
//1.卸载cdev
cdev_del(&led_cdev);
//2.释放设备号
unregister_chrdev_region(MKDEV(major, 0), 1);
//3.删除设备结点
device_destory(cls, MKDEV(major, 0)); //摘苹果
class_destroy(cls); //砍树枝
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL);
测试
int rdata;
int wdata;
int index;
ioctl(fd, LED_ON);
ioctl(fd, LED_OFF);
index = 1;
ioctl(fd, LED_ON1, &index);
index = 2;
ioctl(fd, LED_ON1, &index);
index = 1;
ioctl(fd, LED_OFF1, &index);
index = 2;
ioctl(fd, LED_OFF1, &index);
ioctl(fd, LED_READ, &rdata);
printf("rdata = %d\n", rdata);
wdata = 0x55;
ioctl(fd, LED_WRITE, &wdata);