驱动的分层分离概念(platform)及实例讲解(点亮led)

2021-07-18  本文已影响0人  Leon_Geo

引言

分层就是将一个复杂的工作分成了4层, 分而做之,降低难度。每一层只专注于自己的事情, 系统已经将其中的核心层和事件处理层写好了,所以我们只需要来写硬件相关的驱动层代码即可。

分离是指把硬件相关的部分(驱动层)从纯软件部分(事件处理层)抽离出来,使我们只需要关注硬件相关部分代码的编写。具体来说就是在驱动层中使用platform机制(将所有设备挂接到一个虚拟的总线上,方便sysfs节点和设备电源的管理,使得驱动代码,具有更好的扩展性和跨平台性,就不会因为新的平台而再次编写驱动)把硬件相关的代码(固定的,如板子的网卡、中断地址)和驱动(会根据程序作变动,如点哪一个灯)分离开来,即要编写两个文件:dev.c和drv.c(platform设备和platform驱动)

image-20210717161931798

接下来我们来分析platform机制以及分离概念。

1、platform机制

bus-drv-dev模型

platform_bus_type的结构体定义如下所示(位于drivers/base):

struct bus_type platform_bus_type = {              
.name         = "platform",         //设备名称
.dev_attrs    = platform_dev_attrs, //设备属性、含获取sys文件名,该总线会放在/sys/bus下
.match        = platform_match,     //匹配设备和驱动,匹配成功就调用driver的.probe函数
.uevent       = platform_uevent,    //消息传递,比如热插拔操作
.suspend      = platform_suspend,   //电源管理的低功耗挂起
.suspend_late = platform_suspend_late,  
.resume_early = platform_resume_early,
.resume       = platform_resume,  //恢复
};

2、利用platform机制,编写LED驱动层

2.1 创建设备代码

#include <linux/module.h>
#include <linux/version.h>

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>

static struct resource led_resource[] = { //资源数组,用来保存设备的信息
    [0] = {
        .start = 0x56000050,          //led的寄存器GPFCON起始地址
        .end   = 0x56000050 + 8 - 1,  // led的寄存器GPFDAT结束地址
        .flags = IORESOURCE_MEM,      //表示地址资源
    },
    [1] = {
        .start =  5,                  //表示GPF第几个引脚开始
        .end   = 5,                   //结束引脚
        .flags = IORESOURCE_IRQ,      //表示中断资源    
    } 
};

//释放函数
static void led_release(struct device * dev)
{
 //释放函数,必须向内核提供一个release函数, 否则卸载时,内核找不到该函数会报错。   
}


/*分配、设置一个LED设备 */
static struct platform_device led_dev = {
    .name   = "myled",  //对应的platform_driver驱动的名字
    .id     = -1,       //表示只有一个设备
    .num_resources  = ARRAY_SIZE(led_resource), //资源数量,ARRAY_SIZE()函数:获取数量
    .resource   = led_resource, //资源数组led_resource
    .dev = {    
        .release = led_release,
    },
};

//入口函数,注册dev设备
static int led_dev_init(void)
{
  platform_device_register(&led_dev);
  return 0;
}

//出口函数,注销dev设备
static void led_dev_exit(void) 
{
  platform_device_unregister(&led_dev); 
}
module_init(led_dev_init);   //修饰入口函数
module_exit(led_dev_exit);  //修饰出口函数
MODULE_LICENSE("GPL");   //声明函数

2.2 创建驱动代码

2.3 创建Make file 文件

2.4 创建测试文件

当用户输入led_test on时,LED点亮;输入led_test off时,LED熄灭。

2.5 实验结果

image-20210717234851686

3、小结:

分层分离驱动
上一篇下一篇

猜你喜欢

热点阅读