一个最基本的lLinux驱动开发框架和编译驱动方式

news2024/11/24 20:59:15

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、编写驱动文件
      • 1.相关头文件
      • 2.驱动入口 &出口
      • 3.申明
      • 完整代码
  • 二、编译驱动的方式
  • 三、编译驱动
    • 1. 和内核一起编译:
    • 2. 编译成驱动模块:
    • 3.开发板加载驱动模块
  • 总结


前言

这里给大家介绍最基本的驱动开发框架


一、编写驱动文件

主要有下面几个部分组成:

1.相关头文件

这两个头文件黑丝驱动开发必须包含的头文件

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

2.驱动入口 &出口

static int hello_init(void)
{
    printk("hello world\n");
    return 0;

}

static void hello_exit(void)
{
    printk("by-by\n");
    
}


module_init(hello_init);//入口
module_exit(hello_exit);//出口

入口函数一般是主要完成平台总线的注册等操作,出口函数就是对资源的回收

3.申明

由于Linux是开源的所以需要声明凭证GPL,同时内核也提供了很多相关的宏,给写着描述

MODULE_LICENSE("GPL");//这个是必须要写的,不然编译会有问题
MODULE_AUTHOR("ljm");//作者
MODULE_DESCRIPTION("这是一个基本的驱动框架");

完整代码

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



static int hello_init(void)
{
    printk("hello world\n");
    return 0;

}

static void hello_exit(void)
{
    printk("by-by\n");
    
}

module_init(hello_init);
module_exit(hello_exit);


MODULE_LICENSE("GPL");
MODULE_AUTHOR("ljm");


二、编译驱动的方式

我们编译驱动有两种方式,一种是和内核一起编译,另一种是编译成内核模块,这两种有什么区别:
和内核一起编译:
对于和内核一起编译来说,是直接把驱动文件添加到内核源码的driver目录下的某一目录下,之后和内核一起编译,这中方式适合我们完成驱动调试好之后

编译成内核模块:
对于编译成内核模块来说,是没有这种要求,我们可以把驱动放在任何地方,可以单独编译成模块即带有.ko的文件,之后我们再使用命令insmod xxx.ko来加载驱动即可,优点就是我们不需要的话可以直接使用命令rmmod xxx.ko卸载掉,而不需要再去修改编译内核,可以看出这种方式适合我们在驱动开发时使用,适合我们调试,节省时间。


三、编译驱动

下面使用上面介绍的两种方式来演示一下如何编译驱动:

1. 和内核一起编译:

进入到内核源码目录下的如下目录:

drivers/misc

1)添加驱动文件,这个文件就是我们前面写好的文件
在这里插入图片描述

2)修改Makefile文件(也是在该目录下)
这个配置就是告诉makefile文件要把hellmodule.c编译
在这里插入图片描述

补充:这里除了这种配置外还可以按照下面做法配置:
细心的朋友可能注意到自己添加的哪部分为什么是obj-y而别人是obj-$(变量),如下:
在这里插入图片描述
这里解释一下,-y表示默认编译到内核中,而 obj-¥(变量)表示要不要编译,编译成什么状态由这个变量决定,那么问题来了,这个变量又是哪来的,在哪里设置?这个问题也就是要说的第二种配置:

还是和前面一样,把hellomodule.c拷贝到drivers/misc目录下
(也可以在misc下新建一个目录给自己的驱动,不过需要在自己驱动文件同级目录下写Kconfig,Makefile,还有修改misc的Kconfig文件添加自己Kconfig的路径 下面不介绍这种)

在这里插入图片描述
修改Makefile文件
表示告诉makefil文件hellomodule.c要不要编译,编译成什么状态(模块或者和内核一起编译)由变量CONFIG_HELLOMODULE决定
在这里插入图片描述
变量CONFIG_HELLOMODULE要依据下面决定
修改Kconfig文件:
在这里插入图片描述具体意思如下:


config HELLOMODULE  //变量,如果我们选择编译到内核相当于*,模块相当于m,不编译就空  ,图形配置决定,后面会说
        tristate "HELLOMODULE"  //表示该驱动有三态,* M 空
        default n  默认不编译
        help
          this is my first driver. //帮助信息

图形配置该驱动
输入以下命令:

 export ARCH=arm64 //导出环境变量为arm64
 make rockchip_linux_defconfig //配置默认的内核配置文件,会产生.config文件,即最终的配置文件
 

在这里插入图片描述
输入以下命令进入图形配置:

 make menuconfig

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里我选择编译到内核
在这里插入图片描述
然后保存配置
在这里插入图片描述
在这里插入图片描述
之后退出即可
保存退出之后,输入以下命令保存配置内核文件。

make savedefconfig

输入以下命令保存到默认的配置文件中:

cp defconfig arch/arm64/configs/rockchip_linux_defconfig

之所以进行这两步,是因为我们后面使用的是瑞芯微的脚本编译内核,而脚本里面默认编译的配置文件就是rockchip_linux_defconfig,所以我们得更新一下,不然看不到,因为我们的配置文件.config,并没有被这个脚本使用,当然你也可以使用直接使用make命令,但是使用这种方法编译出来的貌似还不能用

在这里插入图片描述

接下来后面的步骤是一样

3)重新编译内核
回到SDK的目录下输入以下命令编译
在这里插入图片描述

4)编译完成:
在这里插入图片描述

5)烧录新编译的镜像:
在这里插入图片描述
前面章节已经介绍了如何烧录传送门

6)烧录完成后在串口打印中可以看到如下所示的打印:
在这里插入图片描述
这个打印消息就是我们驱动加载的时候打印的消息
在这里插入图片描述

可以看出这里打印消息一模一样,表示已经加载驱动成功

2. 编译成驱动模块:

前面的方法中我们是将驱动和内核一起编译,但是我们每次修改驱动就要从新编译一次内核,特别费时间,所以我们经常把驱动编译成模块

1)编写Makefile文件

KERNEL_DIR=/home/topeet/Linux/linux_sdk/kernel  #内核源码路径

ARCH=arm64  #芯片架构
CROSS_COMPILE=/usr/local/arm64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-  #编译器
export  ARCH  CROSS_COMPILE

obj-m := hellomodule.o #编译成内核模块
all:
	$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules

.PHONE:clean   #伪命令

clean:
	$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean	

读者要依据自己的内核源码路径和编译器的路径设置

其中对于编译器,瑞芯微提供的SDK里面就有编译器,我们只需要使用这个即可
在这里插入图片描述
如下编写Makefile设置:

KERNEL_DIR=/home/topeet/Linux/linux_sdk/kernel

ARCH=arm64
CROSS_COMPILE=/home/topeet/Linux/linux_sdk/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
export  ARCH  CROSS_COMPILE

obj-m := hellomodule.o
all:
        $(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules

.PHONE:clean copy

clean:
        $(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean      

copy:
        sudo  cp  *.ko  /home/embedfire/workdir

如果你出现如下错误,那么就说明你还没有设置好编译器的环境:
在这里插入图片描述
为了方便我们以后编写应用层的代码,我们最好把这个编译器环境导出来感兴趣的读者可以看这篇文章传送门

2).编译
把Makefile文件和驱动文件放在一起,如下:
在这里插入图片描述
执行以下命令:

make //编译

在这里插入图片描述

make clean //清除编译

其中hellomodule.ko就是我们的驱动模块在这里插入图片描述


3.开发板加载驱动模块

通过网络Nfs或者其他方式把hellomodule.ko文件发给开发板,在开发板中执行以下操作:

insmod hellomodule.ko  //表示加载驱动模块

在这里插入图片描述

rmmod hellomodule.ko //卸载模块

在这里插入图片描述

总结

本文从零开始搭建了驱动的编写,编译,加载到实现,相信对于没有基础的读者会有一定的帮助,如果有帮助到你的地方清点击收藏+关注哦

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

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

相关文章

Kafka消息写入流程

Kafka消息写入流程 0,写入消息简要流程图 1,从示例开始 在Kafka中,Producer实例是线程安全的,通常一个Producer的进程只需要生成一个Producer实例. 这样比一个进程中生成多个Producer实例的效率反而会更高. 在Producer的配置中,可以配置Producer的每个batch的内存缓冲区的大小…

如何下载最新的NDVI数据?需要翻墙,安装MRT,如何处理下载的NDVI数据?

一、下载NDVI数据 参照网站&#xff1a; https://www.zhihu.com/question/48176218 1、先在网站https://modis.gsfc.nasa.gov/data/dataprod/mod13.php查看要下载的数据 其实没什么要看的&#xff0c;就看下面这个图就可以了&#xff0c;根据下图找到自己要下载的数据简称&am…

Python实现猎人猎物优化算法(HPO)优化支持向量机分类模型(SVC算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 猎人猎物优化搜索算法(Hunter–prey optimizer, HPO)是由Naruei& Keynia于2022年提出的一种最新的优…

Hibernate-Validator的使用(一)

文章目录学习建议全部的约束注解关于NotEmpty和NotBlank的注意事项关于Size的注意事项约束注解可以放的位置JavaBeanValidator接口约束注解的继承性普通方法和构造方法入参和返回值ExecutableValidator 接口约束注解的继承性错误信息国际化显示定义message使用的消息key定义Val…

模仿现实生活中的通讯录(2)

距离第一篇已经过去很久&#xff0c;我之所以暂时放下通讯录&#xff0c;是因为学业颇多&#xff0c;无暇顾及。现在放假已经有一段时间了&#xff0c;脱离每天忙碌的生活后&#xff0c;我只想享受一下整日无事&#xff0c;浑浑噩噩过一天的感觉&#xff0c;只不过差点没收得住…

leetcode150/155. 逆波兰表达式求值、最小栈;剑指 Offer 31. 栈的压入、弹出序列

目录 题目链接与简介 题目一 1.算法思路 2.总结心得 3.可执行代码 题目二 1.算法思路 2.总结心得 3.可执行代码 题目三 1.算法思路 2.总结心得 3.可执行代码 题目链接与简介 1.逆波兰表达式求值 2.最小栈 3.剑指 Offer 31. 栈的压入、弹出序列 题目一 LeetCod…

软件测试 -- 进阶 8 软件测试流程和过程

盖天下之事&#xff0c;不难于立法&#xff0c;而难于法之必行&#xff1b;不难于听言&#xff0c;而难于言之必效。-- 明 张居正 释译&#xff1a;天下大事&#xff0c;困难的不在于要制定什么法律&#xff0c;而在于立了法就一定要执行&#xff1b;重要的不在于说什么&a…

【实时数仓】DWS层之地区主题表(FlinkSQL)、关键词主题表(FlinkSQL)

文章目录一 DWS层-地区主题表(FlinkSQL)1 分组开窗和聚合计算&#xff08;1&#xff09;分组窗口&#xff08;2&#xff09;选择分组窗口的开始和结束时间戳&#xff08;3&#xff09;系统内置函数&#xff08;4&#xff09;完整代码2 将动态表转换为流&#xff0c;写入ClickHo…

计算机基础(五):C语言的程序的处理过程

一段C语言程序 打开任何一个C语言的教程&#xff0c;首先自然是展示一段 Hello World 的程序&#xff0c;类似于下面这段&#xff1a; #include <stdio.h>int main() {/* 我的第一个 C 程序 */printf("Hello, World! \n");return 0; }运行上面这段程序也很简…

Qt中的数据库(简单使用)

在Qt中支持对数据库的操作 Qt中数据库的类有&#xff1a; 驱动层&#xff1a;为具体的数据库和SQL接口层之间提供底层的桥梁SQL层&#xff1a;提供对数据库的访问 QSqlDateBase类用来创建连接QSqlQuery可以使用SQL语句实现交互用户接口层&#xff1a;实现将数据库中的数据链接…

36. 卷积神经网络(LeNet)

通过之前几节&#xff0c;我们学习了构建一个完整卷积神经网络的所需组件。 回想一下&#xff0c;之前我们将softmax回归模型和多层感知机模型应用于Fashion-MNIST数据集中的服装图片&#xff0c;为了能够应用softmax回归和多层感知机&#xff1a; 我们首先将每个大小为的图像…

【Web开发】Python实现Web服务器(Ubuntu下Flask使用MySQL数据库)

&#x1f37a;基于Python的Web服务器系列相关文章编写如下&#x1f37a;&#xff1a; &#x1f388;【Web开发】Python实现Web服务器&#xff08;Flask快速入门&#xff09;&#x1f388;&#x1f388;【Web开发】Python实现Web服务器&#xff08;Flask案例测试&#xff09;&a…

大数据-玩转数据-Kafka实战

一、kafka使用要点 要点一&#xff1a;Producer即生产者&#xff0c;向Kafka集群发送消息&#xff0c;在发送消息之前&#xff0c;会对消息进行分类&#xff0c;即Topic&#xff0c;topic1&#xff0c;topic2。Topic即主题&#xff0c;通过对消息指定主题可以将消息分类&#…

工具-能写会看正则表达式【强烈建议收藏!】

正则表达式,很常用的一个技能点,但是一般的开发流程中都是这样的: 需要验证数据上网搜一下正则表达式CV 搞定!!!今天有时间回看了一下文档,简单整理了一下里面需要注意的点,并且通过分析几个常见的正则表达式,下次遇到正则争取不再只依靠 CV 大法! 基础部分 基本语法 …

初识指针(9)

目录 1、指针是什么&#xff1f; 2、指针和指针类型 1、指针- 整数 2、指针的解引用 3、野指针 1、野指针成因 2、如何规避野指针 4、指针运算 1、指针- 整数 2、指针- 指针 3、指针的关系运算 5、指针和数组 6、二级指针 7、指针数组 1、指针是什么&#xff1f;…

04-Hystrix

服务熔断Hystrix 1. Hystrix是什么 分布式系统环境下&#xff0c;服务间类似依赖非常常见&#xff0c;一个业务调用通常依赖多个基础服务。如下图&#xff0c;对于同步调用&#xff0c;当库存服务不可用时&#xff0c;商品服务请求线程被阻塞&#xff0c;当有大批量请求调用库…

SpringBoot-2 读取properties;自动加载127个类原理总结;全部加载,按需配置

读取properties 方式一&#xff1a;非配置类填写&#xff1a;ComponentConfigurationProperties 1)建立bean&#xff1a; /只有在容器中的组件才拥有springboot提供的强大功能 Component ConfigurationProperties(prefix "mycar") public class Car {private Stri…

【机器学习】模型评估与选择

模型评估与选择 目录一、评估方法1、留出法2、交叉验证法3、自助法二、性能度量1、错误率与准确率2、查准率、查全率阈值对查准率、查全率的影响3、F1度量&#xff08;基于查准率与查全率的调和平均&#xff09;4、P-R Curve5、ROC CurvePRC和ROC的选用准则PRC和ROC的差异6、代…

python 中文转带音调的拼音

python 中文转带音调的拼音 前言python 中文转带音调的拼音1、1.1 安装pinyin模块1.2 试验1.3 效果图1.4 代码实现前言 今天整理中药材,每个药材上标上带音调的拼音,查了些,有的易形成乱码,如Shān Mi Dōnɡ,想到python自已动手转算了 python 中文转带音调的拼音 1、 …

(五)汇编语言——[bx]和loop指令

目录 [...]与&#xff08;...&#xff09; [...] &#xff08;...&#xff09; idata Loop指令 段前缀 总结 [...]与&#xff08;...&#xff09; [...] 这个我们其实见过&#xff0c;代表的是一个内存单元&#xff0c;段地址在DS中&#xff0c;偏移地址就是[bx]。 &am…