嵌入式Linux应用开发-第十章LED模板总线设备驱动模型

嵌入式Linux应用开发-第十章LED模板总线设备驱动模型

  • 第十章 LED模板驱动程序的改造:总线设备驱动模型
    • 10.1 原来的框架
    • 10.2 要实现的框架
    • 10.3 写代码
      • 10.3.1 注意事项
      • 10.3.2 实现 platform_device结构体
      • 10.3.3 实现 platform_driver结构体
    • 10.4 课后作业

第十章 LED模板驱动程序的改造:总线设备驱动模型

在这里插入图片描述

10.1 原来的框架

在这里插入图片描述

10.2 要实现的框架

在这里插入图片描述

10.3 写代码

使用 GIT下载所有源码后,本节源码位于如下目录:

01_all_series_quickstart\ 
05_嵌入式 Linux驱动开发基础知识\source\ 
02_led_drv\04_led_drv_template_bus_dev_drv 

10.3.1 注意事项

① 如果 platform_device中不提供 release函数,如下图所示不提供红框部分的函数:
在这里插入图片描述

则在调用 platform_device_unregister时会出现警告,如下图所示:

rootaroc-rk3399-pc;/mnti# insmod board_A_led.ko
rootaroc-rk3399-pc:/mnt]# rmmod board_A_led.ko
2412528005524125,29502724125.3051301
Device 'xxxxxx led.0' does not have a release() function, it is broken and must be fixed
---- cut here -----------
WARNING: at drivers/base/core.c:251

你可以提供一个 release函数,如果实在无事可做,把这函数写为空。

② EXPORT_SYMBOL a.c编译为 a.ko,里面定义了 func_a;如果它想让 b.ko使用该函数,那么 a.c里需要导出此函数(如果 a.c, b.c都编进内核,则无需导出):

EXPORT_SYMBOL(led_device_create); 

并且,使用时要先加载 a.ko。 如果先加载 b.ko,会有类似如下“Unknown symbol”的提示:

rootaroc-rk3399-pc:/mnt]# insmod chip_demo_gpio.ko
24299,917448] chip_demo_gpio: Unknown symbo register led operations (err 0)
24299.935714] chip_demo_gpio: Unknown symbol led class destroy device (err 0)
24299.9508431 chip_demo_gpio: Unknown symbol led class create device (err 0)
24299,9714821 chip_demo_gpio: Unknown symbol register led operations (err 0)
24299.982958] chip_demo_gpio: Unknown symbol led class destroy device (err 0)
24299,9948341 chip_demo_gpio: Unknown symbol led class create device (err 0)
can't insert 'chip_demo_gpio.ko': unknown symbol in module, or unknown nsmoc: parameter

10.3.2 实现 platform_device结构体

board_A.c作为一个可加载模块,里面也有入口函数、出口函数。在入口函数中注册 platform_device结构体,在 platform_device结构体中指定使用哪个 GPIO引脚。
首先看入口函数,它调用 platform_device_register函数,向内核注册 board_A_led_dev结构体:

50 static int __init led_dev_init(void) 
51 { 
52     int err; 
53 
54     err = platform_device_register(&board_A_led_dev); 
55 
56     return 0; 
57 } 
58 

board_A_led_dev结构体定义如下。 在 resouces数组中指定了 2个引脚(第 27~38行);
我们还提供了一个空函数 led_dev_release(第 23~25行),它被赋给 board_A_led_dev结构体(第 46行),这个函数在卸载 platform_device时会被调用,如果不提供的话内核会打印警告信息。

23 static void led_dev_release(struct device *dev) 
24 { 
25 } 
26 
27 static struct resource resources[] = { 
28         { 
29                 .start = GROUP_PIN(3,1), 
30                 .flags = IORESOURCE_IRQ, 
31                 .name = "xxxxxx_led_pin", 
32         }, 
33         { 
34                 .start = GROUP_PIN(5,8), 
35                 .flags = IORESOURCE_IRQ, 
36                 .name = "xxxxxx_led_pin", 
37         }, 
38 }; 
39 
40 
41 static struct platform_device board_A_led_dev = { 
42         .name = "xxxxxx_led", 
43         .num_resources = ARRAY_SIZE(resources), 
44         .resource = resources, 
45         .dev = { 
46                 .release = led_dev_release, 
47          }, 
48 }; 
49 

10.3.3 实现 platform_driver结构体

chip_demo_gpio.c中注册 platform_driver结构体,它使用 Bus/Dev/Drv模型,当有匹配的platform_device时,它的 probe函数就会被调用。
在 probe函数中所做的事情跟之前的代码没有差别。
先看入口函数。
第 150行向内核注册一个 platform_driver结构体; 这个结构体的核心在于第 140行的 chip_demo_gpio_probe函数。
138 static struct platform_driver chip_demo_gpio_driver = {
139 .probe = chip_demo_gpio_probe,
140 .remove = chip_demo_gpio_remove,
141 .driver = {
142 .name = “xxxxxx_led”,
143 },
144 };
145
146 static int __init chip_demo_gpio_drv_init(void)
147 {
148 int err;
149
150 err = platform_driver_register(&chip_demo_gpio_driver);
151 register_led_operations(&board_demo_led_opr);
152
153 return 0;
154 }
155

chip_demo_gpio_probe函数代码如下。
第 107行:从匹配的 platform_device中获取资源,确定 GPIO引脚。
第 111行:把引脚记录下来,在操作硬件时要用。
第 112行:新发现了一个 GPIO引脚,就调用上层驱动的代码创建设备节点。

100 static int chip_demo_gpio_probe(struct platform_device *pdev) 
101 { 
102     struct resource *res; 
103     int i = 0; 
104 
105     while (1) 
106     { 
107         res = platform_get_resource(pdev, IORESOURCE_IRQ, i++); 
108         if (!res) 
109             break; 
110 
111         g_ledpins[g_ledcnt] = res->start; 
112         led_class_create_device(g_ledcnt); 
113         g_ledcnt++; 
114     } 
115     return 0; 
116 
117 } 
118 

操作硬件的代码如下,第 31、63行的代码里用到了数组 g_ledpins,里面的值来自 platform_device,在 probe函数中根据 platform_device的资源确定了引脚:

23 static int g_ledpins[100]; 
24 static int g_ledcnt = 0; 
25 
26 static int board_demo_led_init (int which) /* 初始化 LED, which-哪个 LED */ 
27 { 
28     //printk("%s %s line %d, led %d\n", __FILE__, __FUNCTION__, __LINE__, which); 
29 
30   printk("init gpio: group %d, pin %d\n", GROUP(g_ledpins[which]), PIN(g_ledpins[which])); 
31     switch(GROUP(g_ledpins[which])) 
32     { 
33         case 0: 
34         { 
35             printk("init pin of group 0 ...\n"); 
36             break; 
37         } 
38         case 1: 
39         { 
40             printk("init pin of group 1 ...\n"); 
41             break; 
42         } 
43         case 2: 
44         { 
45             printk("init pin of group 2 ...\n"); 
46             break; 
47         } 
48         case 3: 
49         { 
50             printk("init pin of group 3 ...\n"); 
51             break; 
52         } 
53     } 
54 
55     return 0; 
56 } 
57 
58 static int board_demo_led_ctl (int which, char status) /* 控制 LED, which-哪个 LED, status:1-亮,0-灭 */ 
59 { 
60     //printk("%s %s line %d, led %d, %s\n", __FILE__, __FUNCTION__, __LINE__, which, status ? "on" : "off"); 
61    printk("set led %s: group %d, pin %d\n", status ? "on" : "off", GROUP(g_ledpins[which]), PIN(g_ledpins[which])); 
62 
63     switch(GROUP(g_ledpins[which])) 
64     { 
65         case 0: 
66         { 
67             printk("set pin of group 0 ...\n"); 
68             break; 
69         } 
70         case 1: 
71         { 
72             printk("set pin of group 1 ...\n"); 
73             break; 
74         } 
75         case 2: 
76         { 
77             printk("set pin of group 2 ...\n"); 
78             break; 
79         } 
80         case 3: 
81         { 
82             printk("set pin of group 3 ...\n"); 
83             break; 
84         } 
85     } 
86 
87     return 0; 88 } 
89 
90 static struct led_operations board_demo_led_opr = { 
91     .init = board_demo_led_init, 
92     .ctl  = board_demo_led_ctl, 
93 }; 
94 
95 struct led_operations *get_board_led_opr(void) 
96 { 
97     return &board_demo_led_opr; 
98 } 
99 

10.4 课后作业

完善半成品程序:04_led_drv_template_bus_dev_drv_unfinished。
请仿照本节提供的程序(位于 04_led_drv_template_bus_dev_drv目录),改造你所用的单板的 LED驱动程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/145201.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

HUAWEI悦盒ec6108v9c 如何刷成海纳思系统(家用低功耗服务器,使用Home Assistant服务)

环境: 1.HW悦盒ec6108v9c一套 2.16G U盘 3.格式化软件USB_format.exe 4.固件 mv100-mdmo1g-usb-flash.zip(底层是Ubuntu 20.04系统) 5.十字螺丝刀 6.翘片/薄铲子 7.有线网络环境 8.镊子/回形针 问题描述: 最近玩智能家居…

客户端负载均衡_负载均衡策略

以前的Ribbon有多种负载均衡策略 RandomRule - 随性而为 解释: 随机 RoundRobinRule - 按部就班 解释: 轮询 RetryRule - 卷土重来 解释: 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试。 Weigh…

OpenHarmony自定义组件介绍

一、创建自定义组件 在ArkUI中,UI显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。在进行 UI 界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、业务逻辑…

【面试八股】IP协议八股

IP协议八股 子网掩码的作用为什么IP协议需要分片IP协议什么时候需要分片IP协议是怎么进行分片的那么IP协议是如果进行标识属于同一个分片呢?TCP协议和UDP协议将数据交给IP协议之后,是否需要分片传输? 子网掩码的作用 用来标识网络号和主机号…

照片后期处理软件DxO FilmPack 6 mac中文说明

DxO FilmPack 6 for Mac是一款照片后期处理软件。它可以模拟超过60种著名胶片品牌和类型的色彩和颗粒感,使照片具有复古、艺术和时尚风格。 ​DxO FilmPack 6 mac支持RAW和JPG格式的照片,并提供丰富的调整选项,如亮度、对比度、曝光、阴影和高…

Linux Qt5.15.2 编译QWebEngine源码支持音视频H264

背景 默认自带的QWebEngine 因版权问题不支持音视频功能,需要自己编译源码以支持。 平台:Linux(UOS V20 1050) Qt:5.15.2 准备工作 下载 Qt 5.15.2 对应版本源码,使用镜像网站或者Qt Maintenance Tool工…

Docker-Windows安装使用

1.下载docker https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 2.配置虚拟化环境 通过控制面板“设置”启用 Hyper-V 角色 右键单击 Windows 按钮并选择“应用和功能”。选择相关设置下右侧的“程序和功能”。选择“打开或关闭 Windows 功能”。选择“Hyper-…

解决vs2022项目文件夹内.vs文件夹容量虚高问题

打开系统显示隐藏文件夹 会在vs2022的项目文件夹内有一个.vs文件夹 在子目录里会有一个Browse.VC.db文件,我的项目代码只有120m,而这个db文件居然有70m 而且每次打开vs项目,会使这个文件发生容量变化,如果你的git项目恰好包含这个.vs文件夹,那就比较不爽了,每次都要更新这个文件…

西门子S7-1200使用LRCF通信库与安川机器人进行EthernetIP通信的具体方法示例

西门子S7-1200使用LRCF通信库与安川机器人进行EthernetIP通信的具体方法示例 准备条件: PLC:S7-1200 1214C DC/DC/DC 系统版本4.5及以上。 机器人控制柜:安川YRC1000。 软件:TIA V17 PLC做主站,机器人做从站。 具体方法可参考以下内容: 使用的库文件为西门子 1200系列…

BUUCTF reverse wp 21 - 30

[ACTF新生赛2020]rome 无壳, 直接拖进IDA32 y键把v2改成char[49], n键重命名为iuput int func() {int result; // eaxint v1[4]; // [esp14h] [ebp-44h]char input[49]; // [esp24h] [ebp-34h] BYREFstrcpy(&input[23], "Qsw3sj_lz4_Ujwl");printf("Please…

Simulink仿真封装中的参数个对话框设置

目录 参数和对话框窗格 初始化窗格 文档窗格 为了更加直观和清晰的分析仿真,会将多个元件实现的一个功能封装在一起,通过参数对话框窗格,可以使用参数、显示和动作选项板中的对话框控制设计封装对话框。如图所示: 参数和对话框…

第5讲:v-if与v-show的使用方法及区别

v-if条件判断 v-if是条件渲染指令,它根据表达式的真假来删除和插入元素,它的基本语法如下: v-if “expression” expression是一个返回bool值的表达式,表达式可以是一个bool属性,也可以是一个返回bool的运算式 &#…

RTSP协议抓包及讲解

文章目录 前言一、RTSP 亲手搭建直播点播1、数据源为视频文件2、数据源为摄像头①、搭建 RTSP 流媒体服务器②、客户端拉流 二、RTSP 协议简介三、手撕 RTSP 协议1、Wireshark 抓包①、搭建环境②、wireshark 抓包 2、RTSP 交互流程①、OPTIONS②、DESCRIBE③、SETUP④、PLAY⑤…

buildroot移植Qt5无法显示字体问题

报错:QFontDatabase: Cannot find font directory /usr/lib/fonts. Note that Qt no longer ships fonts. Deploy some (from DejaVu Fonts for example) or switch to fontconfig. 原因:很明显是Qt没有找到字库文件; 解决方法: 1…

[old]TeamDev DotNetBrowser Crack

TeamDev DotNetBrowser将 Chromium Web 浏览器添加到您的 .NET 应用程序中。在 WPF 和 WinForms 中显示现代网页。使用 DOM、JS、网络、打印等。在 Windows x86/x64/ARM64、macOS x64/Apple Silicon、Linux x64/ARM64 上运行,支持.NET Framework 4.5 特征 HTML5、C…

神经辐射场(NeRF)2023最新论文及源代码合集

神经辐射场(NeRF)作为一种先进的计算机图形学技术,能够生成高质量的三维重建模型,在计算机图形学、计算机视觉、增强现实等领域都有着广泛的应用前景,因此,自2020年惊艳亮相后,神经辐射场也成为…

C/C++指针笔试题详解

个人主页:点我进入主页 专栏分类:C语言初阶 C语言程序设计————KTV C语言小游戏 C语言进阶 C语言刷题 欢迎大家点赞,评论,收藏。 一起努力,一起奔赴大厂。 目录 1.前言 2.指针题写出下列程序的结…

十六.镜头知识之工业镜头的质量判断因素

十六.镜头知识之工业镜头的质量判断因素 文章目录 十六.镜头知识之工业镜头的质量判断因素1.分辨率(Resolution)2.明锐度(Acutance)3.景深(DOF):4. 最大相对孔径与光圈系数5.工业镜头各参数间的相互影响关系5.1.焦距大小的影响情况5.2.光圈大小的影响情况5.3.像场中…

混淆技术研究-混淆技术-源码分析(2)

简介 OLLVM(Obfuscator-LLVM)是基于LLVM(Low Level Virtual Machine)框架的一种代码混淆器。它主要用于对C/C++和汇编语言程序进行混淆,以增加代码的复杂性,提高代码的安全性和抵抗逆向工程的能力。 IR(Intermediate Representation)是指中间表示,是编译器在将源代码…

【7.Vue 利用Heatmap.js 制作自定义热力图】

1.效果 2.背景 需要根据后端检测的设备的数值显示设备周围的空气情况,用户希望用热力图的方式来显示,于是在网上找了资料,发现可以用Heatmap.js来实现。 Heatmap.js 官网:https://www.patrick-wied.at/static/heatmapjs/ 3.引入…