LED——platform框架

韦东山老师视频链接

本文是对视频学习的笔记记录。

platform总线、设备与驱动

        在linux2.6以后的设备驱动模型中,需关心总线、设备和驱动这3个实体,总线将设备和驱动绑定。在系统没注册一个设备的时候,会寻找与之匹配的驱动,相反的,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配有总线完成。实现资源与驱动的分离。

        platform_device指定资源。

struct platform_device {
	const char	*name;
	int		id;
	bool		id_auto;
	struct device	dev;
	u32		num_resources;
	struct resource	*resource;

	const struct platform_device_id	*id_entry;
	char *driver_override; /* Driver name to force a match */

	/* MFD cell pointer */
	struct mfd_cell *mfd_cell;

	/* arch specific additions */
	struct pdev_archdata	archdata;
};

        platform_driver

struct platform_driver {
	int (*probe)(struct platform_device *);
	int (*remove)(struct platform_device *);
	void (*shutdown)(struct platform_device *);
	int (*suspend)(struct platform_device *, pm_message_t state);
	int (*resume)(struct platform_device *);
	struct device_driver driver;
	const struct platform_device_id *id_table;
	bool prevent_deferred_probe;
};

DEV与DRV匹配规则

先比较

  •  platform_device.driver_override和 platform_driver.driver.name ;可以设置 platform_device 的 driver_override,强制选择某个 platform_driver。 

再比较

  • platform_device. name和 platform_driver.id_table[i].name ;Platform_driver.id_table 是“platform_device_id”指针,表示该 drv 支持若干个 device,它里面列出了各个 device的{.name, .driver_data},其中的“name”表示该drv支持的设备的名字,driver_data是些提供给该 device的私有数据

最后比较

  • platform_device.name和 platform_driver.driver.name ;platform_driver.id_table可能为空, 这时可以根据platform_driver.driver.name来寻找同名的platform_device

board_A_led.c

#include "led_resource.h"
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

struct resource res[] = {
        {
			.start = GROUP_PIN(5,3),
			.flags = IORESOURCE_IRQ,
		}, 
        {
			.start = GROUP_PIN(3,3),
			.flags = IORESOURCE_IRQ,
		},
        {
			.start = GROUP_PIN(4,3),
			.flags = IORESOURCE_IRQ,
		},

};

static struct platform_device board_A_led_dev={
    .name="ss_led",
    .resource=res,
    .num_resources=ARRAY_SIZE(res),
};

static int __init board_A_led_dev_init(void){
    return platform_device_register(&board_A_led_dev);
}

static void __exit board_A_led_dev_exit(void){
   platform_device_unregister(&board_A_led_dev);
}

module_init(board_A_led_dev_init);
module_exit(board_A_led_dev_exit);
MODULE_LICENSE("GPL");

chip_demo_gpio.c主要部分


int chip_demo_gpio_drv_probe(struct platform_device *pdev){
    int i=0;
    struct resource *r;
    pin_num=0;
    while(1){
        //获取资源
        r=platform_get_resource(pdev,IORESOURCE_IRQ,i++);
        if(r){
            pin[pin_num]=r->start;
        //使用leddrv.c提供接口进行device_create
            led_device_create(pin_num++);
        }
        else break;
    }
   
    return 0;
    
}

int chip_demo_gpio_drv_remove(struct platform_device *pdev){
    while(pin_num){
        //使用leddrv.c提供接口进行device_destroy
        led_device_destroy(pin_num--);
    }
    return 0;

}

static struct platform_driver chip_demo_gpio_drv={
    .probe=chip_demo_gpio_drv_probe,
    .remove=chip_demo_gpio_drv_remove,
    .driver={
        .name="ss_led",
    }
};

static int __init chip_demo_gpio_drv_init(void){
    //chip_demo_gpio.c底层调用,为的就是把led_opr传给leddrv.c
    regester_led_operation(&led_opr);
    return platform_driver_register(&chip_demo_gpio_drv);
}

static void __exit chip_demo_gpio_drv_exit(void){
    platform_driver_unregister(&chip_demo_gpio_drv);
}

module_init(chip_demo_gpio_drv_init);
module_exit(chip_demo_gpio_drv_exit);
MODULE_LICENSE("GPL");

leddrv.c重要部分

static int __init led_init(void){
    printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);
    major=register_chrdev(0,"myled",&led_drv);
    led_class=class_create(THIS_MODULE,"myled_class");
    return 0;
}

static void __exit led_exit(void){
    printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);
    led_opr->unmap();
    class_destroy(led_class);
    unregister_chrdev(major,"myled");
}
//给chip_demo_gpio.c底层提供的接口,为了device_create
void led_device_create(int minor){
    device_create(led_class,NULL,MKDEV(major,minor),NULL,"myled%d",minor);
}
//给chip_demo_gpio.c底层提供的接口,为了device_destroy
void led_device_destroy(int minor){
    device_destroy(led_class,MKDEV(major,minor));
}
//给chip_demo_gpio.c底层提供的接口,为了能得到led_opr
void regester_led_operation(struct led_operations * opr){
    led_opr=opr;
    led_opr->map();
}

EXPORT_SYMBOL(led_device_destroy);
EXPORT_SYMBOL(led_device_create);
EXPORT_SYMBOL(regester_led_operation);

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL"); 

 文件之间关系图

        chip_demo_gpio.c和leddrv.c之间看着存在相互依赖的关系,chip_demo_gpio.c需要leddrv.c提供led_class,,,,, leddev.c需要chip_demo_gpio.c返回led_opr。

        所以,先加载leddev,然后加载chip_demo_gpio,需要chip_demo_gpio主动调用regester_led_operation返回led_opr给leddrv.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值