分层概念:
驱动程序向上注册的原理:
比如:输入子程序一个input.c作为一层,下层为Dev.c和Dir.c,分别编写Dev.c和Dir.c向上Input.c注册;如图所示
分离概念:
分离概念主要是讲,设备驱动程序分成两个部分,也将引进另一个新概念bus_dri_dev模型
总线-驱动-设备模式,是讲吧一个驱动分成两个部分,分别挂载到一条总线上的链表中,总线上有.match函数还对两个链表相同名字相匹配,匹配成功跳到driver驱动程序的probe函数来实现驱动的操作。
一下例子主要编写总线驱动设备模式来实现一个控制LED灯的驱动实验:
led_drv.c
#include <linux/module.h>
#include <linux/version.h> #include <linux/init.h> #include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h> /* 分配/设置/注册一个platform_device */ static struct resource led_resource[] = {
[] = {
.start = 0x56000050,
.end = 0x56000050 + - ,
.flags = IORESOURCE_MEM,
},
[] = {
.start = ,
.end = ,
.flags = IORESOURCE_IRQ,
} }; static void led_release(struct device * dev)
{
} static struct platform_device led_dev = {
.name = "myled",
.id = -,
.num_resources = ARRAY_SIZE(led_resource),
.resource = led_resource,
.dev = {
.release = led_release,
},
}; static int led_dev_init(void)
{
platform_device_register(&led_dev);
return ;
} static void led_dev_exit(void)
{
platform_device_unregister(&led_dev);
} module_init(led_dev_init);
module_exit(led_dev_exit); MODULE_LICENSE("GPL");
led_dev.c
#include <linux/module.h>
#include <linux/version.h> #include <linux/init.h> #include <linux/kernel.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/platform_device.h> /* 分配/设置/注册一个platform_device */ static struct resource led_resource[] = {
[] = {
.start = 0x56000050,
.end = 0x56000050 + - ,
.flags = IORESOURCE_MEM,
},
[] = {
.start = ,
.end = ,
.flags = IORESOURCE_IRQ,
} }; static void led_release(struct device * dev)
{
} static struct platform_device led_dev = {
.name = "myled",
.id = -,
.num_resources = ARRAY_SIZE(led_resource),
.resource = led_resource,
.dev = {
.release = led_release,
},
}; static int led_dev_init(void)
{
platform_device_register(&led_dev);
return ;
} static void led_dev_exit(void)
{
platform_device_unregister(&led_dev);
} module_init(led_dev_init);
module_exit(led_dev_exit); MODULE_LICENSE("GPL");
Makefile:
KERN_DIR = /work/system/linux-2.6.22.6 all:
make -C $(KERN_DIR) M=`pwd` modules clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order obj-m += led_drv.o
obj-m += led_dev.o
led_test.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h> /* led_test on
* led_test off
*/
int main(int argc, char **argv)
{
int fd;
int val = ;
fd = open("/dev/led", O_RDWR);
if (fd < )
{
printf("can't open!\n");
}
if (argc != )
{
printf("Usage :\n");
printf("%s <on|off>\n", argv[]);
return ;
} if (strcmp(argv[], "on") == )
{
val = ;
}
else
{
val = ;
} write(fd, &val, );
return ;
}