【1】区分主次设备号
设备号(32bit) = 主设备号(12bit [msb])+ 次设备号(20bit [lsb])
1】示例
ls -l /dev/tty0
主次设备号的范围理论上都是[0, 255]
主设备号:区分不同类型的设备
次设备号:区分同一类型设备的不同个体
MINORBITS:次设备号的位数
MINORMASK:次设备号掩码
MAJOR(dev):得到主设备号
MINOR(dev):得到次设备号
MKDEV(ma,mi):将主设备号与次设备号合为一个32bit整型数(dev_t)
【2】静态注册设备号
就是自己先挑一个没有被内核占用的设备号去注册
0】查看被内核占用的设备号
cat /proc/devices
1】register_chrdev_region(注册设备号)
注释:
from:要注册的起始设备号
count:要连续注册的设备号个数
name:给设备起的名称
2】unregister_chrdev_region(注销设备号)
注释:
from:要注销的起始设备号
count:要连续注销的设备号个数
【3】静态注册实验
1】进入工程目录
cd /home/zjd/s5p6818/KERNEL/drivers
2】创建新的工程
mkdir chrdev
3】编写程序
vim chrdev.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#define CHRDEV_MAGOR 200
#define CHRDEV_MINOR 10
#define CHRDEV_NUM 1
#define CHRDEV_NAME "leds"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Zjd");
int dev = 0; // store the major dev number and the minor dev number
int __init chrdev_init(void)
{
int major = CHRDEV_MAGOR; // major dev number
int minor = CHRDEV_MINOR; // minor dev number
// dev = major << 20 | minor;
// there is a define func to do this task
dev = MKDEV(major, minor);
register_chrdev_region(dev, CHRDEV_NUM, CHRDEV_NAME); //register the number of device
return 0;
}
void __exit chrdev_exit(void)
{
unregister_chrdev_region(dev, CHRDEV_NUM);
return ;
}
module_init(chrdev_init);
module_exit(chrdev_exit);
4】编写Makefile
vim Makefile
obj-m += chrdev.o
KERNEL_PATH=/home/zjd/s5p6818/KERNEL/kernel
ROOTFS_PATH=/nfs_share/_install
all:
make -C $(KERNEL_PATH) M=$(PWD) modules
cp *.ko $(ROOTFS_PATH)
clean:
make -C $(KERNEL_PATH) M=$(PWD) clean
5】编译工程
make
6】下位机验证
注意:我们现在只有设备号,而没有设备文件
【4】动态注册设备号
内核自己找一个没有注册的设备号,注册完归程序员使用
1】alloc_chrdev_region(注册设备号)
注释:
dev:回填设备号
baseminor:次设备号的基值(起始值)
count:要连续注册的设备号个数
name:给设备起的名称
2】unregister_chrdev_region(注销设备号)
注释:
from:要注销的起始设备号
count:要连续注销的设备号个数
【5】动态注册实验
1】编写程序
vim chrdev.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#define CHRDEV_MAGOR 200
#define CHRDEV_MINOR 10
#define CHRDEV_NUM 1
#define CHRDEV_NAME "leds"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Zjd");
int dev = 0; // store the major dev number and the minor dev number
#if 0
// fixed register
int __init chrdev_init(void)
{
int major = CHRDEV_MAGOR; // major dev number
int minor = CHRDEV_MINOR; // minor dev number
// dev = major << 20 | minor;
// there is a define func to do this task
dev = MKDEV(major, minor);
register_chrdev_region(dev, CHRDEV_NUM, CHRDEV_NAME); //register the number of device
return 0;
}
#else
// variable register
int __init chrdev_init(void)
{
int major = CHRDEV_MAGOR; // major dev number
int minor = CHRDEV_MINOR; // minor dev number
// there is a define func to register the number of devices automatically
alloc_chrdev_region(&dev, CHRDEV_MINOR, CHRDEV_NUM, CHRDEV_NAME);
major = MAJOR(dev); // gain the major dev number
minor = MINOR(dev); // gain the minor dev number
printk(KERN_EMERG "dev number is :%d\n major number is :%d\n minor number is :%d\n", dev, major, minor);
return 0;
}
#endif
void __exit chrdev_exit(void)
{
unregister_chrdev_region(dev, CHRDEV_NUM);
return ;
}
module_init(chrdev_init);
module_exit(chrdev_exit);
2】编写Makefile
vim Makefile
obj-m += chrdev.o
KERNEL_PATH=/home/zjd/s5p6818/KERNEL/kernel
ROOTFS_PATH=/nfs_share/_install
all:
make -C $(KERNEL_PATH) M=$(PWD) modules
cp *.ko $(ROOTFS_PATH)
clean:
make -C $(KERNEL_PATH) M=$(PWD) clean
3】编译工程
make
4】下位机验证
注意:我们现在只有设备号,而没有设备文件