#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
bash复制代码
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
cpp复制代码
#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
bash复制代码
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
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#define CHRDEV_MAGOR 200
#define CHRDEV_MINOR 10
#define CHRDEV_NUM 1
#define CHRDEV_NAME "myleds"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Zjd");
int dev = 0; // store the major dev number and the minor dev number
// 1_step :define a struct cdev be named led_cdev
struct cdev led_cdev;
// 3_step :implement the function of led_fops
int led_open(struct inode *inode, struct file *fp)
{
printk(KERN_EMERG "enter:%s\n", __FUNCTION__);
return 0;
}
int led_close(struct inode *inode, struct file *fp)
{
printk(KERN_EMERG "enter:%s\n", __FUNCTION__);
return 0;
}
// 2_step :define a struct file_operation be named led_fops
// what functions shall we to implement ?
// there is turn_on and turn_off of the leds
// So, we should to implement the function of open() and release(), eithor or we should keep up the same type as the definations of the struct file_operations
struct file_operations led_fops = {
.owner = THIS_MODULE,
// int (*open) (struct inode *, struct file *);
.open = led_open,
// int (*release) (struct inode *, struct file *);
.release = led_close
};
#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);
// 4_step :initalize the struct cdev object led_cdev
cdev_init(&led_cdev, &led_fops);
// 5_step :register led_cdev into Kernel
cdev_add(&led_cdev, dev, CHRDEV_NUM);
return 0;
}
#endif
void __exit chrdev_exit(void)
{
// 6_step :destory cdev
cdev_del(&led_cdev);
unregister_chrdev_region(dev, CHRDEV_NUM);
return ;
}
module_init(chrdev_init);
module_exit(chrdev_exit);
4】编写Makefile
vim Makefile
bash复制代码
obj-m += chrdev_func.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
#define GPIOBOUT *(volatile unsigned int *)0xC001B000
#define GPIOBOUT *(volatile unsigned int *)0xC001B000
#define GPIOBOUT *(volatile unsigned int *)0xC001B000
#define GPIOBOUT *(volatile unsigned int *)0xC001B000
#define GPIOBOUT *(volatile unsigned int *)0xC001B000
#define GPIOBOUT *(volatile unsigned int *)0xC001B000
3、内核中提供的操作GPIO的API
【0】gpio宏定义
【1】gpio_request(申请GPIO管脚)
int gpio_request(unsigned gpio, const char *label)
【2】使用GPI管脚
1】gpio_direction_input(设置输入)
2】gpio_direction_output(设置输出)
3】gpio_set_value(设置value)
4】gpio_get_value(获取value)
【3】gpio_free(释放GPIO管脚)
void gpio_free(unsigned gpio)
4、实验
【1】进入工程目录
cd /home/zjd/s5p6818/KERNEL/drivers
【2】创建新的工程
mkdir led_drv
【3】编写程序
vim led_drv.c
cpp复制代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/gpio.h>
#include <mach/platform.h>
#define CHRDEV_MAGOR 200
#define CHRDEV_MINOR 26
#define CHRDEV_NUM 1
#define CHRDEV_NAME "myleds"
#define HIGH 1
#define LOW 0
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Zjd");
int dev = 0; // store the major dev number and the minor dev number
// 1_step :define a struct cdev be named led_cdev
struct cdev led_cdev;
// 3_step :implement the function of led_fops
int led_open(struct inode *inode, struct file *fp)
{
printk(KERN_EMERG "enter:%s\n", __FUNCTION__);
// c_step :set the value=0(turn on) of the gpio
gpio_set_value(PAD_GPIOB26, LOW);
return 0;
}
int led_close(struct inode *inode, struct file *fp)
{
printk(KERN_EMERG "enter:%s\n", __FUNCTION__);
// c_step :set the value=1(turn off) of the gpio
gpio_set_value(PAD_GPIOB26, HIGH);
return 0;
}
// 2_step :define a struct file_operation be named led_fops
// what functions shall we to implement ?
// there is turn_on and turn_off of the leds
// So, we should to implement the function of open() and release(), eithor or we should keep up the same type as the definations of the struct file_operations
struct file_operations led_fops = {
.owner = THIS_MODULE,
// int (*open) (struct inode *, struct file *);
.open = led_open,
// int (*release) (struct inode *, struct file *);
.release = led_close
};
#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);
// 4_step :initalize the struct cdev object led_cdev
cdev_init(&led_cdev, &led_fops);
// 5_step :register led_cdev into Kernel
cdev_add(&led_cdev, dev, CHRDEV_NUM);
// a_step :apply gpio
gpio_request(PAD_GPIOB26, "LED0");
// b_step :set the default value=1(turn_off) of GPIOB26
gpio_direction_output(PAD_GPIOB26, HIGH);
return 0;
}
#endif
void __exit chrdev_exit(void)
{
// e_step :release gpio
gpio_free(PAD_GPIOB26);
// 6_step :destory cdev
cdev_del(&led_cdev);
unregister_chrdev_region(dev, CHRDEV_NUM); // unregister the number of dev
return ;
}
module_init(chrdev_init);
module_exit(chrdev_exit);
【4】编写Makefile
vim Makefile
bash复制代码
obj-m += led_drv.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