LED模板驱动程序的改造:设备树驱动模型

应用程序调用glibc函数

内核层大致分为两个源文件

1)drv.c (发出硬件操作指令)

包含file operation结构体的设置、注册,结构体中包含了.open(),.read()等驱动函数;

  • .open()会调用对应的函数led_drv_open();
  • led_drv_open()会找到led_operation(此结构体由底层驱动源文件led_gpio.drv.c提供)结构体中某一个成员比如init,此成员的值实际上是对应硬件寄存器操作函数的地址;
  • p_led_opr->init(minor, status);根据次设备号和stasus状态参数执行硬件引脚操作,完成硬件驱动。

2)led_gpio_drv.c(执行硬件操作动作)

包含platform_driver结构体的设置注册,该结构体中包含了

/* 1. 定义platform_driver */
static struct platform_driver chip_demo_gpio_driver = {
    .probe      = chip_demo_gpio_probe,
    .remove     = chip_demo_gpio_remove,
    .driver     = {
        .name   = "100ask_led",
        .of_match_table = ask100_leds,
    },
};

.probe()函数,该函数包括了a.从设备节点读取引脚信息并保存,b.调用drv.c文件中的函数创造led设备节点;

static int chip_demo_gpio_probe(struct platform_device *pdev)
{
	//int err;
	
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

	/* 4.1 设备树中定义�? led-gpios=<...>;	*/
    led_gpio = gpiod_get(&pdev->dev, "led", 0);
	if (IS_ERR(led_gpio)) {
		dev_err(&pdev->dev, "Failed to get GPIO for led\n");
		return PTR_ERR(led_gpio);
	}
    
	/* 4.2 注册file_operations 	*/
	major = register_chrdev(0, "100ask_led", &led_drv);  /* /dev/led */

	led_class = class_create(THIS_MODULE, "100ask_led_class");
	if (IS_ERR(led_class)) {
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
		unregister_chrdev(major, "led");
		gpiod_put(led_gpio);
		return PTR_ERR(led_class);
	}

	device_create(led_class, NULL, MKDEV(major, 0), NULL, "100ask_led%d", 0); /* /dev/100ask_led0 */
        
    return 0;
    
}

.remove()函数,该函数包括设备的注销和gpio的释放等。

static int chip_demo_gpio_remove(struct platform_device *pdev)
{
	device_destroy(led_class, MKDEV(major, 0));
	class_destroy(led_class);
	unregister_chrdev(major, "100ask_led");
	gpiod_put(led_gpio);
    
    return 0;
}

当platform_device中的dev.of_node中的compatible与platform_driver的platform_driver -> driver -> of_match_table->of_device_id中的compatible匹配时,就会调用probe();

获取引脚信息后,硬件寄存器操作函数board_led_init()书写了对不同寄存器的不同操作;

硬件寄存器操作函数board_led_init()的地址被赋值给led_opr结构体中的init成员;使用指针变量将led_opr的地址返回给drv.c文件

注:2文件中用到的硬件资源的来源:设备树文件dts编译所得的dtb二进制文件被uboot传递给内核后解析注册为platform_device中所得。

补充:在引入Pinctrl等子系统之后,硬件资源的获取会变得更加简单,对引脚的设置也更加容易,以上提到的内核层文件内容可以整合到一个驱动程序源文件中。且此源文件适用于所有的开发板,不同的开发板使用不同的设备树文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值