驱动开发概念详解_硬件驱动开发是什么-程序员宅基地

技术标签: 嵌入式开发  驱动开发  

1、什么是驱动

        能够驱使硬件实现特定功能的软件代码,可以根据驱动程序是否依赖于系统内核将其分为裸机驱动和系统驱动

1.1裸机驱动

        编写的驱动代码中没有进行任何内核相关的API调用,开发者查询资料配置寄存器完成硬件相关控制,不依赖于系统内核,由开发者独立完成,相对而言比较简单。

1.2系统驱动

        系统驱动指的是编写的驱动代码中需要调用系统内核中提供到的各自API,驱动最终也会加载到系统内核生效。系统驱动开发者无法独立完成,需要依赖于系统内核,基于系统驱动实现的硬件功能也更加复杂

进程上下文切换概念:当进程进行系统调用时,进程访问到的资源从用户空间到内核空间,就叫上下文切换。

内核层向上提供的接口类型:

文件管理、内存管理、进程管理、网络管理(socket)、设备管理(设备驱动的管理)

设备驱动的分类:

linux设备驱动的类型要根据设备的类型进行驱动,系统将其分为字符设备、块设备、网卡设备

字符设备:能够以字节流的形式进行顺序访问的设备叫做字符设备(鼠标、键盘、led灯)

块设备:能够以块(512字节)为单位进行随机访问的设备叫做块设备(磁盘)

网卡设备:进行网络通信时使用网卡设备实现,网卡设备的数据读写基于套接字实现

2、linux内核模块化编程

1、内核模块化的意义

不同于应用程序,驱动是加载到内核空间中的,所以需要内核模块的编程框架编写驱动代码

2、内核模块的三要素

内核模块由三部分组成:入口、出口、许可证

入口:内核模块安装时执行,主要负责资源的申请工作

出口:卸载内核模块时执行、主要负责资源的释放工作

许可证:声明内核模块遵循GPL协议

3、内核模块编程

#include <linux/init.h>
#include <linux/module.h>

//入口函数  安装内核模块时执行
static int __init mycdev_init(void)
{
    //static用于限制入口函数只能在当前文件中使用
    //int指定函数的返回值为int类型,返回值一定要加,不然编译报错
    //mycdev_init,入口函数的函数名,可以自己修改
    //void表示这个函数参,当函数没有参数时一定在参数列表中加void,不然会报错
    /*在ubuntu中的内核目录下索引指定的API时,可以在内核顶层目录下输入ctags -R
            接着使用vi -t 接口名即可索引
    */
    //#define __init        __section(".init.text")
    //__init用于向编译器声明当前mycdev_init函数加载到.init.text段
    //.init.text段指定在内核的链接脚本文件vmlinux.lds中
    
    return 0;
}

//出口函数,卸载内核模块时执行
static void __exit mycdev_exit(void)
{
    //#define __exit          __section(".exit.text")
}
//用于声明当前内核模块入口函数的地址
module_init(mycdev_init);
//用于声明当前内核模块出口函数的地址
module_exit(mycdev_exit);
//声明当前内核模块遵循GPL协议
MODULE_LICENSE("GPL"); 

4、内核模块的编译

4.1编译内核模块的命令

make modules

4.2内部编译(静态编译)

需要依赖于内核源码树进行编译

  • 将编写的内核模块源码存放到linux内核指定目录下
  • 修改该目录下的kconfig文件,添加当前模块文件的选配项
  • 执行make menuconfig,将当前内核模块源码的选配项选配为【M】
  • 执行make menuconfig进行模块化编译

 外部编译(动态编译)

不需要依赖于内核源码树,在编译时只需要编译当前内核模块文件即可,外部编译需要自己手写当前内核模块编译的Makefile

4.3编写动态编译的内核模块的Makefile

#定义变量存放内核源码顶层路径
#KERNELDIR:= /home/ubuntu/linux-5.10.61       #用于编译生成ARM架构的模块
KERNELDIR := /lib/modules/$(shell uname -r)/build  #用于生成x86架构的模块
#定义变量保存模块化编译的文件的路径
PWD:= $(shell pwd)
all:
#make modules是模块化编译的命令
#make -C $(KERNELDIR)表示读取KERNELDIR路径下的Makefile进行make编译
#M=$(PWD)指定模块化编译的路径
    make -C $(KERNELDIR) M=$(PWD) modules
clean: #编译清除
    make -C $(KERNELDIR) M=$(PWD) clean

obj-m:=demo.o  #指定将demo.o独立链接生成内核模块文件

 通用版本的Makefile

modname?=demo  #给定一个默认的模块名
arch?=arm #给定一个架构的模块名
ifeq ($(arch),arm)#判断要编译的架构进而使用不同的Makefile规则进行编译
#定义变量存放内核源码顶层路径
KERNELDIR:= /home/ubuntu/linux-5.10.61   #用于编译生成ARM架构的模块
else
KERNELDIR := /lib/modules/$(shell uname -r)/build  #用于生成x86架构的模块
endif

#定义变量保存模块化编译的文件的路径
PWD:= $(shell pwd)
all:
#make modules是模块化编译的命令
#make -C $(KERNELDIR)表示读取KERNELDIR路径下的Makefile进行make编译
#M=$(PWD)指定模块化编译的路径
    make -C $(KERNELDIR) M=$(PWD) modules
clean: #编译清除
    make -C $(KERNELDIR) M=$(PWD) clean

obj-m:=$(modname).o  #指定将demo.o独立链接生成内核模块文件

5、内核模块相关指令

安装内核模块:

sudo insmod ****.ko

查看被安装的内核模块

lsmod

卸载内核模块

sudo rmmod ***

查看内核模块相关信息

modinfo ****.ko

 内核中的消息打印函数:

printk(消息输出级别 "格式控制符",输出列表);

 查看消息默认级别

终端输入 cat /proc/sys/kernel/printk查看

终端默认级别 消息默认级别 终端支持的消息最高级别 终端支持消息的最低级别

dmesg命令的使用

功能:输出从内核启动到当前时刻开始所有的打印信息

dmesg -c/dmesg -C: 清除当前dmesg的buf中保存的所有打印信息

6、linux内核模块传参

内核模块传参

内核模块传参指的是安装模块时在命令行给内核模块中的变量传递数值

ex:insmod demo.ko a=100 

内核模块传参的意义

通过内核模块传参的使用,我们可以对内核模块的一些属性进行修改,让其适配多种不同的硬件

 内核模块传参实现的相关API

module_param(name,type,perm)
//声明可以通过命令行传参的变量信息
参数:name 要进行命令行传参的变量名
      type:要进行命令行传参的变量类型
/ * Standard types are:
             byte(单字节类型), hexint, short, ushort, int, uint, long, ulong
           charp: a character pointer(char *)
           bool: a bool, values 0/1, y/n, Y/N.
           invbool: the above, only sense-reversed (N = true).
 */
     perm:文件权限,当使用module_param函数声明要传参的变量时,会在/sys/module/当前内核模块名/parameters/目录下生成一个以当前变量名为名的文件,文件的权限就是perm和文件权限掩码运算得到,文件的数值时变量的值
2.MODULE_PARM_DESC(变量名, 对变量的描述)
功能:添加对要传参的变量的描述,这个描述可以通过modinfo ***.ko查看到

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_60039521/article/details/132861460

智能推荐

C++11 多线程_c11多线程打印abc十次-程序员宅基地

文章浏览阅读282次。C++11开始支持多线程编程,之前多线程编程都需要系统的支持,在不同的系统下创建线程需要不同的API如pthread_create(),Createthread(),beginthread()等,使用起来都比较复杂,C++11提供了新头文件、、、等用于支持多线程。使用C++11开启一个线程是比较简单的,下面来看一个简单的例子:#include #include_c11多线程打印abc十次

[转]开源大数据处理工具汇总_开源 数据转换-程序员宅基地

文章浏览阅读483次。查询引擎一、Phoenix贡献者::Salesforce简介:这是一个Java中间层,可以让开发者在Apache HBase上执行SQL查询。Phoenix完全使用Java编写,代码位于GitHub上,并且提供了一个客户端可嵌入的JDBC驱动。Phoenix查询引擎会将SQL查询转换为一个或多个HBase scan,并编排执行以生成标准的JDBC结果集。直接使用HBase API、..._开源 数据转换

【C++学习】map和set-程序员宅基地

文章浏览阅读963次,点赞26次,收藏10次。【C++学习】map和set

SaaS到底是什么,如何做?这份笔记讲明白了_saas如何开发-程序员宅基地

文章浏览阅读1.3k次。阅读本篇文章,您将可以了解:1、什么是SaaS;2、SaaS的商业模式;3、SaaS的技术架构;4、国内比较好的SaaS平台。_saas如何开发

摄像头接入_大华sdk frealdatacallback码流输出链接-程序员宅基地

文章浏览阅读1.5k次。摄像头接入目前摄像头直播的方案主要有以下几种方式: rtsp方式接入,只能实现视频预览 国标协议接入,实现比较复杂,需要多实现SIP服务器 通过netsdk获取到视频码流,推流到流媒体服务器,通过wsflv,flv,hls等流媒体协议播放,H265不支持 一、采用方案对比后最终采用了第三种方式,java使用jna的方式接入大华netsdk,获取到dav视频码流后去除大华头尾,拿到H264裸码流,通过javacv(对ffmpeg、opencv等库的封装)推送到.._大华sdk frealdatacallback码流输出链接

git-commit-amend踩坑_git remote-tracking 本地commit amend不了-程序员宅基地

文章浏览阅读1.4k次。因为改动比较小,所以我不想重建一个commit,于是我是用了git commit --amend命令,由于之前已经将该commit推送到远程仓库,导致修改后推送失败。百度后发现如果你的commit已经push到了远程仓库,那么使用--amend修改commit后,git push时一定要使用 --force-with-lease 参数来强制推送,否则就会报错。这是我自己推送失败的例子解决方式一、第一种使用后git commit --amend -m "修改Git学习(三)指令"注意:-m “._git remote-tracking 本地commit amend不了

随便推点

自动化安装Linux系统—ftp_ftp://192.168.9.157-程序员宅基地

文章浏览阅读1.9k次。autoinstall_system—ftp文章目录autoinstall_system—ftp服务介绍工作过程第一步:PXE Client向DHCP服务器发送请求第二步:DHCP服务器提供信息第三步:PXE客户端请求下载启动文件第四步:Boot Server响应客户端请求并传送文件第五步:请求下载自动应答文件第六步:客户端安装操作系统实验环境需要安装的服务操作过程一、 关闭selinux 和 防火墙二、部署 DHCP 服务器1、修改配置2、重启服务3、查看dhcp服务三、部署tftp-server服._ftp://192.168.9.157

D L N A介 绍-程序员宅基地

文章浏览阅读799次。这部分的内容大多来源于网络及官方文档,按照自己的翻译理解整理所成。东西比较多,从头慢慢看还是可以懂个大概的。 目录:一、DNLA的建立二、DLNA的成员三、DLNA标准的制定四、DLNA的设备五、DLNA的架构六、云时代的数字家庭(待填坑) 扩展阅读I: UPnP的工作过程------------DLNA基础协议框架扩展阅读II UPnP AV(Audi

用JAVA实现记事本_记事本 cambria math 分数-程序员宅基地

文章浏览阅读275次。用Java语言实现Windows版本的记事本程序(实现了部分功能模块的记事本),代码复制粘贴如下:import java.awt.;import java.io.;import java.awt.event.;import javax.swing.;import java.net.;import javax.swing.border.;import java.util.Date;import java.text.SimpleDateFormat;import java.lang.*;_记事本 cambria math 分数

Linux SSH密码暴力破解技术及攻防实战_password top 1000-程序员宅基地

文章浏览阅读6k次,点赞8次,收藏55次。对于Linux操作系统来说,一般通过VNC、Teamviewer和SSH等工具来进行远程管理,SSH是 Secure Shell的缩写,由IETF的网络小组(Network Working Group)所制定;SSH 为建立在应用层基础上的安全协议。SSH 是目前较可靠,专为远程登录会话和加粗样式其他网络服务提供安全性的协议。利用SSH协议可以有效防止远程管理过程中的信息泄露问题。SSH客户端适..._password top 1000

html静态页面微信分享带缩略图,【荐】静态页面实现微信分享带缩略图、标题和描述...-程序员宅基地

文章浏览阅读1.2k次。这篇文章主要为大家详细介绍了【荐】静态页面实现微信分享带缩略图、标题和描述,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,有需要的朋友可以收藏方便以后借鉴。静态页面实现微信分享带缩略图、标题和描述,想法很现实,要想实现这样的功能这里就要用到大ajax技术,在这里361源码分享给大家。服务端文件jssdk.php代码:..._html分享链接加图片和描述不需要调用jssdk

VASP学习1入门知识_vaspwiki-程序员宅基地

文章浏览阅读5.9k次,点赞10次,收藏63次。大师兄科研实例使用方法:1从最基本的计算开始,通过示例讲解,结合一些脚本的使用,引导大家思考解决自己的问题。因此,在这本书的学习过程里,每一章节会对应一个例子,大家务必手动搭建模型,输入文件(切忌复制粘贴),然后进行计算,得到和大师兄一致的结果。为了引导大家主动浏览官网解决问题,很多都会采用VASP官网的例子。2如何学习本书,大师兄在学习程序时,受learn_python_the_hard_w..._vaspwiki

推荐文章

热门文章

相关标签