Linux 驱动分离模型

一,过程概述

       驱动分离模型主要用途是讲驱动的硬件相关代码与硬件无关代码分离,提高驱动的移植性,可重复性。主要编写2个文件,一个driver文件和一个device文件

1. device文件的操作

    a)创建一个 struct platform_device 结构体  static struct platform_device led_device
     ,设置 name, name必须与driver 文件下的struct platform_driver.driver.name 一致. 内核根据name来匹配driver是否支持某个device

   b) 创建一个 struct resource 结构体, 里面主要包括硬件相关信息内存地址 中断号 等等,resource 结构体包含在 platform_device 结构体中,这样使两者关联起来

   c) 在驱动 init 函数中注册 platform_device  platform_device_register(&led_device);  在驱动exit函数中卸载 platform_device_unregister(&led_device);

2. deriver 文件的操作

   a) 创建一个 struct platform_driver 结构体  static struct platform_driver led_drv 设置 probe 函数,当内核匹配上同名的 platform_device 结构体时调用。remove 函数 ,

        当内核发 现与之匹配的  platform_device 驱动被卸载时调用。 driver.name 这个name 必须与platform_device 的name 保持一致。内核通过该项来进行匹配

   b) 在驱动 init 函数中注册 struct platform_driver   platform_driver_register(&led_drv);; 在驱动exit函数中卸载 platform_driver_unregister(&led_drv);

   c)  在 probe 函数中进行真正的驱动相关操作。 获取platform_device 中的硬件相关信息 resource 。

二 示例代码

1. device文件代码

#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>
#include <linux/module.h>
#include <linux/version.h>

#include "s3c6410.h"

void led_device_release(struct device *dev)

{
	printk(KERN_INFO"led dev, release led\n");
}

static struct resource led_res[] = {
	[0] = {
		.start = ELFIN_GPIO_BASE+GPKCON0_OFFSET,
		.end   = ELFIN_GPIO_BASE+GPKCON0_OFFSET + 16 -1,
		.flags = IORESOURCE_MEM
	},
	[1] = {
		.start = 4,
		.end   = 4,
		.flags = IORESOURCE_IRQ
	}
};

static struct platform_device led_device = {
	.name = "led_drv",
	.id	  = -1,
	.num_resources = ARRAY_SIZE(led_res),
	.resource = led_res,
	.dev = {
		.release  = led_device_release,
	}
};

static int len_dev_init(void)
{
	platform_device_register(&led_device);
	return 0;
	
}

static void len_dev_exit(void)
{
	platform_device_unregister(&led_device);
}


module_init(len_dev_init);
module_exit(len_dev_exit);
MODULE_LICENSE("GPL");



2. driver文件代码

#include <linux/module.h>
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/irq.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/uaccess.h>
#include <linux/errno.h>
#include <linux/io.h>

#include "s3c6410.h"

static int major;
static struct class  *led_class;
static struct device *led_class_dev;

static volatile unsigned long *gpio_con;
static volatile unsigned long *gpio_dat; 
static int pin;

static int led_drv_open(struct inode *inode, struct file *file)
{
	*gpio_con &= ~(0xf<<(pin*4));
	*gpio_con |=  (0x1<<(pin*4));
	return 0;
}

static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
	int val = 0;

	if(copy_from_user(&val, buf, count))
		return -EINVAL;
	
	if(val)
	{
		*gpio_dat &= ~(1<<pin);
	}
	else
	{
		*gpio_dat |= (1<<pin);
	}
	return 0;
}

static struct file_operations led_drv_fops = 
{
	.owner	=	THIS_MODULE,
	.open	=	led_drv_open,
	.write	=	led_drv_write,
};

static int led_probe(struct platform_device *pdev)
{
	struct resource *res;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	gpio_con = ioremap(res->start, res->end - res->start + 1);
	gpio_dat = gpio_con+2;

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	pin = res->start;
	
	major= register_chrdev(0, "led_drv", &led_drv_fops);

	led_class = class_create(THIS_MODULE, "led_class");
	if(IS_ERR(led_class))
		return PTR_ERR(led_class);
	
	led_class_dev = device_create(led_class, NULL, MKDEV(major, 0), NULL, "led");
	if(unlikely(IS_ERR(led_class_dev)))
		return PTR_ERR(led_class_dev);;
	
	printk(KERN_INFO"led drv, found led\n");
	return 0;
}

static int led_remove(struct platform_device *pdev)
{
	
	device_unregister(led_class_dev);
	
	class_destroy(led_class);
	
	unregister_chrdev(major, "led_drv");	

	iounmap(gpio_con); 
	
	printk(KERN_INFO"led drv, remove led\n");
	return 0;
}

static struct platform_driver led_drv = {
	.probe	= led_probe,
	.remove = led_remove,
	.driver = {
		.name = "led_drv",
	}
};

static int led_drv_init(void)
{
	platform_driver_register(&led_drv);
	return 0;
}

static void led_drc_exit(void)
{
	platform_driver_unregister(&led_drv);
}

module_init(led_drv_init);
module_exit(led_drc_exit);
MODULE_LICENSE("GPL");






 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值