嵌入式Linux 开发经验:platform_driver_register 的使用方法

这篇具有很好参考价值的文章主要介绍了嵌入式Linux 开发经验:platform_driver_register 的使用方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

  • 嵌入式Linux 设备驱动开发时,经常遇到平台驱动 platform_driver_register 的注册,最近深入了看了驱动开发为何使用平台驱动

  • 开发一个设备驱动时,为了实现 设备的 打开、关闭、控制等操作,可以注册为 Linux misc 设备,不过在这之前,可以先使用 platform_driver_register 注册平台驱动,在平台驱动 probe 函数中,初始化调用 misc 设备的注册操作

  • platform driver 在设备驱动开发中,到底起到了什么作用?为何不直接注册一个实际的设备,如 misc 【字符设备】?

Linux 驱动模型

  • 仔细研究了一下,发现当前较新的Linux 内核版本,使用了【设备树】,这里注册的不是平台设备,而是平台的驱动,好处就是平台驱动在注册时,会自动匹配设备节点,匹配成功后,就会调用用户注册平台驱动时的 probe函数,匹配失败,就不会调用 probe函数。

  • 利用平台驱动的这个机制,在设备匹配成功再去注册设备,那么注册实际的设备的操作放在平台驱动 probe 中调用,再适合不过了,如根据设备树觉得是否需要注册一个 misc 字符设备,如果匹配失败,那这个设备不存在,就无须注册,匹配成功,说明设备存在,就会在 probe 中注册设备。

  • 如果只是为了匹配设备树,自己写个 match 函数就可以吧,为何还要注册平台驱动这么麻烦?其实平台驱动本身一点都不麻烦,相反如果自己去拿个【设备节点名称】去匹配设备树,才会比较的麻烦,也就是说,注册了平台驱动,这个匹配操作就自动完成了,不需要用户写一些匹配设备树的操作函数手动去匹配了。

  • 注册了平台驱动,设备驱动如果是【模块编译】的,在移除设备驱动模块时,平台驱动remove 函数会自动调用 ,这样可以在 remove 函数中做些设备释放的相关操作

  • 如此看来,注册平台驱动,简化了设备驱动的开发,交给内核驱动模型去管理设备驱动,带来了很多的便利

测试环境搭建

  • ubuntu 20.04

  • VMware Workstation Pro 16

  • 基于qemu(模拟器),vexpress-a9 平台

  • Linux 6.0.10 (当前最新版本)

  • 注册一个简单的平台驱动,掌握平台驱动注册的方法

注册Linux 平台驱动示例

  • 在Linux 内核 目录: linux-6.0.10/drivers 下创建 led_control 文件夹,当前 qemu 环境,无法控制具体的引脚,这里只作为示例,也可以实际的开发板验证

  • 新建 linux-6.0.10/drivers/led_control/led_control.c

#include "led_control.h"

#define LED_CONTROL_DRIVER_NAME		"led_control"

static int led_control_probe(struct platform_device *pdev);
static int led_control_remove(struct platform_device *pdev);
static void led_control_shutdown(struct platform_device *pdev);

/* 设备树匹配:这里的节点,在相应的 dts 设备树文件中添加 */
static const struct of_device_id led_control_of_match[] = {
	{
		.compatible = "gpio,led,led-control",
	},
};

/* 平台驱动 : 核心是 probe函数,设备树匹配后,会调用 probe  */
static struct platform_driver led_control_driver = {
	.probe = led_control_probe,
	.remove = led_control_remove,
	.shutdown = led_control_shutdown,
	.driver = {
		.name = LED_CONTROL_DRIVER_NAME,
		.of_match_table = of_match_ptr(led_control_of_match),
	},
};

static int led_control_probe(struct platform_device *pdev)
{
	printk(KERN_INFO "%s : enter\n", __func__);
	// led_miscdev_init();  /* 设备存在就会进入这里,注册 misc 设备 */
	return 0;
}

static int led_control_remove(struct platform_device *pdev)
{
	printk(KERN_INFO "%s : enter\n", __func__);
	//led_miscdev_exit(); /* 移除设备驱动模块时,反注册 misc 设备 */
	return 0;
}

static void led_control_shutdown(struct platform_device *pdev)
{
	printk(KERN_INFO "%s : enter\n", __func__);
}

static int __init led_control_driver_init(void)
{
	printk(KERN_INFO "%s : enter\n", __func__);
	return platform_driver_register(&led_control_driver);
}
late_initcall(led_control_driver_init); /* 自动初始化机制:开机后会调用 */

static void __exit led_control_driver_exit(void)
{
	printk(KERN_INFO "%s : enter\n", __func__);
	platform_driver_unregister(&led_control_driver);
}

module_exit(led_control_driver_exit);  /* 移除驱动模块时会调用 */

MODULE_AUTHOR("zhangsz");
MODULE_DESCRIPTION("led control driver");
MODULE_LICENSE("GPL");
  • 新建 linux-6.0.10/drivers/led_control/led_control.h
#ifndef __LED_CONTROL_H__
#define __LED_CONTROL_H__

#include <linux/of.h>
#include <linux/platform_device.h>

//#include "led_misc.h"

#endif
  • 新建 linux-6.0.10/drivers/led_control/Kconfig,这里增加一个【宏】
config LED_CONTROL
	tristate "Support LED Control"
	help
		Enable LED Control driver
	default y
  • 新建 linux-6.0.10/drivers/led_control/Makefile,Linux 下,默认使用 Makefile 管理文件的编译
obj-$(CONFIG_LED_CONTROL) += led_control.o

其他修改

  • 虽然 led_control 驱动里面Kconfig 默认选中 【default y】,但是 menuconfig 中找不到这个 Kconfig 配置,需要修改 linux-6.0.10/drivers/Kconfig,把 led_control 的 Kconfig 路径添加进去

platform_driver_register,嵌入式Linux,linux,platform driver,平台驱动

source "drivers/led_control/Kconfig"
  • 修改二:还需修改 linux-6.0.10/drivers/Makefile,增加 led_control 的 Makefile 路径

platform_driver_register,嵌入式Linux,linux,platform driver,平台驱动

obj-$(CONFIG_LED_CONTROL)       += led_control/
  • 修改三: 修改设备树文件 vim arch/arm/boot/dts/vexpress-v2p-ca9.dts,增加一个虚拟的设备节点
        led_control@0 {
                compatible = "gpio,led,led-control";
        };

platform_driver_register,嵌入式Linux,linux,platform driver,平台驱动

platform_driver_register,嵌入式Linux,linux,platform driver,平台驱动

  • 备注:可以使用VS Code ssh 连接ubuntu 主机,进行代码的编写

编译

  • led_control 属于内核驱动,默认跟内核一起编译,当然也可以使用【模块编译】

platform_driver_register,嵌入式Linux,linux,platform driver,平台驱动

  • 编译命令:这里使用 qemu
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- vexpress_defconfig

# 默认选择了 led_control,可以 menuconfig 看看
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

## 编译,默认生成 zImage
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8
  • 把 内核编译生成的 zImage,放到 qemu 根文件系统中

启动 qemu

  • 简单编写个 启动 qemu 的shell 脚本,这样每次就不用输入那么长的命令了

  • vim boot_qemu.sh

#!/bin/bash
echo "---------- boot qemu ----------"
echo $1

qemu-system-arm -M vexpress-a9 -m 512M -dtb vexpress-v2p-ca9.dtb -kernel zImage -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd $1
  • chmod +x boot_qemu.sh 增加执行的权限

  • 启动 qemu ,sudo ./boot_qemu.sh rootfs.ext4.img ,完整的启动命令行为

qemu-system-arm -M vexpress-a9 -m 512M -dtb vexpress-v2p-ca9.dtb -kernel zImage -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd rootfs.ext4.img
  • 其中 rootfs.ext4.img 是 根文件系统,制作方法可以参考前面的文章
    ubuntu 20.04 qemu linux6.0.1 制作ext4根文件系统

  • 启动后,发现 led_control 平台驱动 注册成功,并且匹配设备树节点成功,进入了 probe 函数


led_control_driver_init : enter
led_control_probe : enter

platform_driver_register,嵌入式Linux,linux,platform driver,平台驱动

  • 进入 Linux shell,查看 platform 驱动的文件 ls sys/devices/platform/ -la,可以找到注册的 platform 驱动
    led_control@0

platform_driver_register,嵌入式Linux,linux,platform driver,平台驱动

  • reboot 时,发现调用了 led_control_shutdown : enter

platform_driver_register,嵌入式Linux,linux,platform driver,平台驱动

  • 以上说明 platform 驱动 注册成功,调用正常

小结

  • Linux 的一些 misc 设备,通过先注册 platform driver 平台驱动,在平台驱动 probe 函数中再注册初始化misc 设备,这是一种很好的驱动开发设计方法,充分利用了Linux 内核提供的驱动模型带来的便利,让驱动开发精简,利于管理

  • Linux 设备驱动还是比较的庞大,需要花些时间与精力耐心研究,才能有所收获文章来源地址https://www.toymoban.com/news/detail-791630.html

到了这里,关于嵌入式Linux 开发经验:platform_driver_register 的使用方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 嵌入式Linux开发-USB驱动

    哥们马上就要被裁了,总得整理一下技术方面的积累,准备开始下一轮的面试和找工作之旅了。。。。 通用串行总线(USB)是主机和外围设备之间的一种连接。 从拓扑上来看,是一颗由几个点对点的连接构建而成的树。这些连接是连接设备和集线器(hub)的四线电缆(底线、电源线

    2024年02月20日
    浏览(64)
  • 嵌入式Linux驱动开发之点灯

      使用驱动开发的方式点亮一个LED灯。看看两者有啥区别不? 首先查看原理图,看看我们的板子上的LED等接在哪一个IO口上面。 好了,看原理图我们知道LED灯接在芯片的GPIO1的第三个引脚上面,也就是GPIO1_IO03。 先掌握三个名词 CCM: Clock Controller Module (时钟控制模块) IOMUXC : I

    2024年02月01日
    浏览(92)
  • 嵌入式开发之linux内核移植

    目录  前言 一、下载内核源码 1.1 下载linux-3.0.1 1.2 解压源码文件 二、 内核添加yaffs2文件系统支持 2.1 下载yaffs2 2.2 内核添加yaffs2文件补丁 三、配置开发板 3.1 修改机器ID 3.2 添加开发板初始化文件 3.3 配置NandFalsh 3.3.1 添加NandFlash设备 3.3.2 添加NandFlash驱动 3.3 修改Kconfig(支持

    2024年02月07日
    浏览(88)
  • 嵌入式Linux应用开发笔记:串口

    串口(UART)是嵌入式设备中比较常用的功能。这篇文章将记录下应用程序中串口操作相关内容。 这篇文章中内容均在下面的开发板上进行测试: 《新唐NUC980使用记录:自制开发板(基于NUC980DK61YC)》 这篇文章是在下面文章基础上进行的: 《新唐NUC980使用记录(5.10.y内核)

    2024年02月09日
    浏览(42)
  • 嵌入式Linux驱动开发——常见框架梳理

    本文主要介绍了Linux驱动开发中一些常用的驱动框架,platform、input、iic、spi等,硬件平台使用的是正点原子的imx6ull开发板。 不管什么框架最后都是要追溯到配置IO的电气属性和复用功能 如果要使用外部中断,设备树节点中还需添加相关信息,什么边沿触发 1:module_init和mod

    2024年02月15日
    浏览(58)
  • 嵌入式Linux开发实操(八):UART串口开发

    串口可以说是非常好用的一个接口,它同USB、CAN、I2C、SPI等接口一样,为SOC/MCU构建了丰富的接口功能。那么在嵌入式linux中又是如何搭建和使用UART接口的呢? 一、Console接口即ttyS0 ttyS0通常做为u-boot(bootloader的一种,像是Windows的BIOS),它需要一个交互界面,一般使用ttyS0,即可

    2024年02月12日
    浏览(35)
  • 嵌入式Linux驱动开发系列六:Makefile

    Makefile是什么? gcc hello.c -o hello gcc aa.c bb.c cc.c dd.c ... make工具和Makefile make和Makefile是什么关系? make工具:找出修改过的文件,根据依赖关系,找出受影响的相关文件,最后按照规则单独编译这些文件。 Makefile文件:记录依赖关系和编译规则。 必须要学精Makefile吗? 怎么学习Makefi

    2024年02月13日
    浏览(51)
  • 嵌入式开发--电子钢琴项目(Linux+C开发)附上源码

    复盘一下之前做的一个小项目,温习一下c语言和Linux的知识,唔,就是这样子。 所用软件以及工具如下: 1、VMware-workstation-full搭配Ubuntu18.04的Linux操作系统,VMware是桌面虚拟计算机软件,提供用户可在单一的桌面上同时运行不同的操作系统和进行开发、测试 、部署新的应用程

    2024年02月08日
    浏览(43)
  • 正点原子嵌入式linux驱动开发——Linux WIFI驱动

    WIFI的使用已经很常见了,手机、平板、汽车等等,虽然可以使用有线网络,但是有时候很多设备存在布线困难的情况,此时WIFI就是一个不错的选择。 正点原子STM32MP1开发板支持USB和SDIO这两种接口的WIFI ,本章就来学习一下如何在STM32MP1开发板上使用USB和SDIO这两种WIFI。 正点原

    2024年02月05日
    浏览(62)
  • 正点原子嵌入式linux驱动开发——Linux CAN驱动

    CAN是目前应用非常广泛的现场总线之一,主要应用于汽车电子和工业领域 ,尤其是汽车领域,汽车上大量的传感器与模块都是通过CAN总线连接起来的。CAN总线目前是自动化领域发展的热点技术之一,由于其高可靠性,CAN总线目前广泛的应用于工业自动化、船舶、汽车、医疗和

    2024年02月06日
    浏览(67)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包