• RK3568驱动指南|第六篇-平台总线-第53章 probe函数编写实验


    瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。


    【公众号】迅为电子

    【粉丝群】824412014(加群获取驱动文档+例程)

    【视频观看】嵌入式学习之Linux驱动(第六篇-平台总线_全新升级)_基于RK3568

    【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


    第53章 probe函数编写实验

    在上面的两个章节中分别注册了platform设备和platform驱动,匹配成功之后会进入在注册platform驱动程序中编写的probe函数,在上个章节只是为了验证是否匹配成功,所以只是在probe中加入了一句相关打印,而驱动是要控制硬件的,但是平台总线模型对硬件的描述写在了platform_device.c中,platform设备和platform驱动匹配成功之后,那我们如何在驱动platform_driver.c的probe函数中,得到platform_device.c中编写的硬件资源呢。下面开始本节课程的学习吧。

    53.1 获取device资源

    方法1:直接访问 platform_device 结构体的资源数组

    在上一章节的讲解中提到:struct platform_driver 结构体继承了 struct device_driver 结构体,因此可以直接访问 struct device_driver 中定义的成员。实例代码如下所示:

    1. if (pdev->num_resources >= 2) {
    2. struct resource *res_mem = &pdev->resource[0];
    3. struct resource *res_irq = &pdev->resource[1];
    4. // 使用获取到的硬件资源进行处理
    5. printk("Method 1: Memory Resource: start = 0x%lld, end = 0x%lld\n",
    6. res_mem->start, res_mem->end);
    7. printk("Method 1: IRQ Resource: number = %lld\n", res_irq->start);
    8. }

    在这种方法中,直接访问platform_device结构体的资源数组来获取硬件资源。pdev->resource是一个资源数组,其中存储了设备的硬件资源信息。通过访问数组的不同索引,可以获取到特定的资源。

    在这个示例中,假设资源数组的第一个元素是内存资源,第二个元素是中断资源。所以我们将第一个元素的指针赋值给res_mem,第二个元素的指针赋值给res_irq。

    方法2:使用 platform_get_resource() 获取硬件资源

    platform_get_resource()函数用于获取设备的资源信息。它的声明位于头文件中,与平台设备(platform_device)相关。

    函数原型:

    struct resource *platform_get_resource(struct platform_device *pdev,                                       unsigned int type, unsigned int num);

    参数说明:

    pdev:指向要获取资源的平台设备(platform_device)结构体的指针。

    type:指定资源的类型,可以是以下值之一:

    IORESOURCE_MEM:表示内存资源。

    IORESOURCE_IO:表示I/O资源。

    IORESOURCE_IRQ:表示中断资源。

    其他资源类型的宏定义可在头文件中找到。

    num:指定要获取的资源的索引。在一个设备中可能存在多个相同类型的资源,通过索引可以选择获取特定的资源。

    返回值:

    如果成功获取资源,则返回指向资源(struct resource)的指针。

    如果获取资源失败,或者指定的资源不存在,则返回NULL。

    platform_get_resource()函数用于从平台设备的资源数组中获取指定类型和索引的资源。在平台设备的资源数组中,每个元素都是一个struct resource结构体,描述了一个资源的信息,如起始地址、结束地址、中断号等。

    示例用法:

    1. struct platform_device *pdev;
    2. struct resource *res;
    3. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    4. if (!res) {
    5. // 处理获取内存资源失败的情况
    6. }
    7. // 使用获取到的内存资源进行处理
    8. unsigned long start = res->start;
    9. unsigned long end = res->end;
    10. ...

     在上述示例中,首先通过platform_get_resource()函数获取平台设备的第一个内存资源(索引为0)。如果获取资源失败(返回NULL),则可以根据实际情况进行错误处理。如果获取资源成功,则可以使用返回的资源指针来访问资源的信息,如起始地址和结束地址。

    通过platform_get_resource()函数,可以方便地在驱动程序中获取平台设备的资源信息,并根据这些信息进行后续的操作和配置。

    53.2 实验程序的编写

    本实验对应的网盘路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\42_probe

    在上一章程序的基础上,添加第一小节两种获取设备资源的方式并打印出来。

    编写完成的probe.c代码如下所示。

    1. #include
    2. #include
    3. #include
    4. static int my_platform_driver_probe(struct platform_device *pdev)
    5. {
    6. struct resource *res_mem, *res_irq;
    7. // 方法1:直接访问 platform_device 结构体的资源数组
    8. if (pdev->num_resources >= 2) {
    9. struct resource *res_mem = &pdev->resource[0];
    10. struct resource *res_irq = &pdev->resource[1];
    11. // 使用获取到的硬件资源进行处理
    12. printk("Method 1: Memory Resource: start = 0x%llx, end = 0x%llx\n",
    13. res_mem->start, res_mem->end);
    14. printk("Method 1: IRQ Resource: number = %lld\n", res_irq->start);
    15. }
    16. // 方法2:使用 platform_get_resource() 获取硬件资源
    17. res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    18. if (!res_mem) {
    19. dev_err(&pdev->dev, "Failed to get memory resource\n");
    20. return -ENODEV;
    21. }
    22. res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    23. if (!res_irq) {
    24. dev_err(&pdev->dev, "Failed to get IRQ resource\n");
    25. return -ENODEV;
    26. }
    27. // 使用获取到的硬件资源进行处理
    28. printk("Method 2: Memory Resource: start = 0x%llx, end = 0x%llx\n",
    29. res_mem->start, res_mem->end);
    30. printk("Method 2: IRQ Resource: number = %lld\n", res_irq->start);
    31. return 0;
    32. }
    33. static int my_platform_driver_remove(struct platform_device *pdev)
    34. {
    35. // 设备移除操作
    36. return 0;
    37. }
    38. static struct platform_driver my_platform_driver = {
    39. .driver = {
    40. .name = "my_platform_device", // 与 platform_device.c 中的设备名称匹配
    41. .owner = THIS_MODULE,
    42. },
    43. .probe = my_platform_driver_probe,
    44. .remove = my_platform_driver_remove,
    45. };
    46. static int __init my_platform_driver_init(void)
    47. {
    48. int ret;
    49. ret = platform_driver_register(&my_platform_driver); // 注册平台驱动
    50. if (ret) {
    51. printk("Failed to register platform driver\n");
    52. return ret;
    53. }
    54. printk("Platform driver registered\n");
    55. return 0;
    56. }
    57. static void __exit my_platform_driver_exit(void)
    58. {
    59. platform_driver_unregister(&my_platform_driver); // 注销平台驱动
    60. printk("Platform driver unregistered\n");
    61. }
    62. module_init(my_platform_driver_init);
    63. module_exit(my_platform_driver_exit);
    64. MODULE_LICENSE("GPL");
    65. MODULE_AUTHOR("topeet");

    53.3 运行测试

    53.3.1 编译驱动程序

    在上一小节中的probe.c代码同一目录下创建 Makefile 文件,Makefile 文件内容如下所示:

    1. export ARCH=arm64#设置平台架构
    2. export CROSS_COMPILE=aarch64-linux-gnu-#交叉编译器前缀
    3. obj-m += probe.o #此处要和你的驱动源文件同名
    4. KDIR :=/home/topeet/Linux/linux_sdk/kernel #这里是你的内核目录
    5. PWD ?= $(shell pwd)
    6. all:
    7. make -C $(KDIR) M=$(PWD) modules #make操作
    8. clean:
    9. make -C $(KDIR) M=$(PWD) clean #make clean操作

    对于Makefile的内容注释已在上图添加,保存退出之后,来到存放probe.c和Makefile文件目录下,如下图(图53-1)所示:

    图 53-1

    然后使用命令“make”进行驱动的编译,编译完成如下图(图53-2)所示:

    图 53-2

    编译完生成probe.ko目标文件,如下图(图53-3)所示:

    图 53-3

    至此驱动模块就编译成功了。

    53.3.2 运行测试

    本小节的测试要使用两个ko文件,第一个ko文件为第53章编译出来的platform_device.ko驱动,第二个ko文件为在上一小节编译出的probe.ko驱动文件。

    开发板启动之后,首先使用以下命令进行platform设备的注册,如下图(图53-4)所示:

    insmod platform_device.ko

    然后继续使用以下命令加载probe.ko驱动,打印如下图(53-5)所示:

    insmod probe.ko

    图 53-5

    在上图中,打印了两种方式下获取得到的内存信息和中断信息,最后可以使用以下命令进行驱动的卸载,如下图(图53-6)所示:

    rmmod  probe.ko

    rmmod platform_device.ko


     

  • 相关阅读:
    天空卫士C++ 一面(技术面、61min)
    mybatis02(动态sql及分页)
    视频号视频下载教程,为视频博主提供的PC电脑版下载方法
    PHP低版本安全问题
    RocketMQ创建topic流程解析
    golang如何使用指针灵活操作内存?unsafe包原理解析
    滑动平均窗口的定义,优点,缺点,以及目前的应用!!
    android 11源码编译系统介绍
    Azkaban安装部署
    剑指 Offer 03. 数组中重复的数字
  • 原文地址:https://blog.csdn.net/BeiJingXunWei/article/details/133824251