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

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

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

智能推荐

艾美捷Epigentek DNA样品的超声能量处理方案-程序员宅基地

文章浏览阅读15次。空化气泡的大小和相应的空化能量可以通过调整完全标度的振幅水平来操纵和数字控制。通过强调超声技术中的更高通量处理和防止样品污染,Epigentek EpiSonic超声仪可以轻松集成到现有的实验室工作流程中,并且特别适合与表观遗传学和下一代应用的兼容性。Epigentek的EpiSonic已成为一种有效的剪切设备,用于在染色质免疫沉淀技术中制备染色质样品,以及用于下一代测序平台的DNA文库制备。该装置的经济性及其多重样品的能力使其成为每个实验室拥有的经济高效的工具,而不仅仅是核心设施。

11、合宙Air模块Luat开发:通过http协议获取天气信息_合宙获取天气-程序员宅基地

文章浏览阅读4.2k次,点赞3次,收藏14次。目录点击这里查看所有博文  本系列博客,理论上适用于合宙的Air202、Air268、Air720x、Air720S以及最近发布的Air720U(我还没拿到样机,应该也能支持)。  先不管支不支持,如果你用的是合宙的模块,那都不妨一试,也许会有意外收获。  我使用的是Air720SL模块,如果在其他模块上不能用,那就是底层core固件暂时还没有支持,这里的代码是没有问题的。例程仅供参考!..._合宙获取天气

EasyMesh和802.11s对比-程序员宅基地

文章浏览阅读7.7k次,点赞2次,收藏41次。1 关于meshMesh的意思是网状物,以前读书的时候,在自动化领域有传感器自组网,zigbee、蓝牙等无线方式实现各个网络节点消息通信,通过各种算法,保证整个网络中所有节点信息能经过多跳最终传递到目的地,用于数据采集。十多年过去了,在无线路由器领域又把这个mesh概念翻炒了一下,各大品牌都推出了mesh路由器,大多数是3个为一组,实现在面积较大的住宅里,增强wifi覆盖范围,智能在多热点之间切换,提升上网体验。因为节点基本上在3个以内,所以mesh的算法不必太复杂,组网形式比较简单。各厂家都自定义了组_802.11s

线程的几种状态_线程状态-程序员宅基地

文章浏览阅读5.2k次,点赞8次,收藏21次。线程的几种状态_线程状态

stack的常见用法详解_stack函数用法-程序员宅基地

文章浏览阅读4.2w次,点赞124次,收藏688次。stack翻译为栈,是STL中实现的一个后进先出的容器。要使用 stack,应先添加头文件include<stack>,并在头文件下面加上“ using namespacestd;"1. stack的定义其定义的写法和其他STL容器相同, typename可以任意基本数据类型或容器:stack<typename> name;2. stack容器内元素的访问..._stack函数用法

2018.11.16javascript课上随笔(DOM)-程序员宅基地

文章浏览阅读71次。<li> <a href = "“#”>-</a></li><li>子节点:文本节点(回车),元素节点,文本节点。不同节点树:  节点(各种类型节点)childNodes:返回子节点的所有子节点的集合,包含任何类型、元素节点(元素类型节点):child。node.getAttribute(at...

随便推点

layui.extend的一点知识 第三方模块base 路径_layui extend-程序员宅基地

文章浏览阅读3.4k次。//config的设置是全局的layui.config({ base: '/res/js/' //假设这是你存放拓展模块的根目录}).extend({ //设定模块别名 mymod: 'mymod' //如果 mymod.js 是在根目录,也可以不用设定别名 ,mod1: 'admin/mod1' //相对于上述 base 目录的子目录}); //你也可以忽略 base 设定的根目录,直接在 extend 指定路径(主要:该功能为 layui 2.2.0 新增)layui.exten_layui extend

5G云计算:5G网络的分层思想_5g分层结构-程序员宅基地

文章浏览阅读3.2k次,点赞6次,收藏13次。分层思想分层思想分层思想-1分层思想-2分层思想-2OSI七层参考模型物理层和数据链路层物理层数据链路层网络层传输层会话层表示层应用层OSI七层模型的分层结构TCP/IP协议族的组成数据封装过程数据解封装过程PDU设备与层的对应关系各层通信分层思想分层思想-1在现实生活种,我们在喝牛奶时,未必了解他的生产过程,我们所接触的或许只是从超时购买牛奶。分层思想-2平时我们在网络时也未必知道数据的传输过程我们的所考虑的就是可以传就可以,不用管他时怎么传输的分层思想-2将复杂的流程分解为几个功能_5g分层结构

基于二值化图像转GCode的单向扫描实现-程序员宅基地

文章浏览阅读191次。在激光雕刻中,单向扫描(Unidirectional Scanning)是一种雕刻技术,其中激光头只在一个方向上移动,而不是来回移动。这种移动方式主要应用于通过激光逐行扫描图像表面的过程。具体而言,单向扫描的过程通常包括以下步骤:横向移动(X轴): 激光头沿X轴方向移动到图像的一侧。纵向移动(Y轴): 激光头沿Y轴方向开始逐行移动,刻蚀图像表面。这一过程是单向的,即在每一行上激光头只在一个方向上移动。返回横向移动: 一旦一行完成,激光头返回到图像的一侧,准备进行下一行的刻蚀。

算法随笔:强连通分量-程序员宅基地

文章浏览阅读577次。强连通:在有向图G中,如果两个点u和v是互相可达的,即从u出发可以到达v,从v出发也可以到达u,则成u和v是强连通的。强连通分量:如果一个有向图G不是强连通图,那么可以把它分成躲个子图,其中每个子图的内部是强连通的,而且这些子图已经扩展到最大,不能与子图外的任一点强连通,成这样的一个“极大连通”子图是G的一个强连通分量(SCC)。强连通分量的一些性质:(1)一个点必须有出度和入度,才会与其他点强连通。(2)把一个SCC从图中挖掉,不影响其他点的强连通性。_强连通分量

Django(2)|templates模板+静态资源目录static_django templates-程序员宅基地

文章浏览阅读3.9k次,点赞5次,收藏18次。在做web开发,要给用户提供一个页面,页面包括静态页面+数据,两者结合起来就是完整的可视化的页面,django的模板系统支持这种功能,首先需要写一个静态页面,然后通过python的模板语法将数据渲染上去。1.创建一个templates目录2.配置。_django templates

linux下的GPU测试软件,Ubuntu等Linux系统显卡性能测试软件 Unigine 3D-程序员宅基地

文章浏览阅读1.7k次。Ubuntu等Linux系统显卡性能测试软件 Unigine 3DUbuntu Intel显卡驱动安装,请参考:ATI和NVIDIA显卡请在软件和更新中的附加驱动中安装。 这里推荐: 运行后,F9就可评分,已测试显卡有K2000 2GB 900+分,GT330m 1GB 340+ 分,GT620 1GB 340+ 分,四代i5核显340+ 分,还有写博客的小盒子100+ 分。relaybot@re...

推荐文章

热门文章

相关标签