OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 10653|回复: 13

驱动模块静态编译到 Linux 内核

[复制链接]

9

主题

890

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
2395
金钱
2395
注册时间
2019-9-25
在线时间
398 小时
发表于 2020-3-25 22:47:40 | 显示全部楼层 |阅读模式
本帖最后由 仰望星空之云 于 2021-7-10 10:24 编辑

【正点原子】I.MX6U嵌入式Linux驱动开发指南》教程里也有讲解到如何将驱动编译进内核,在内核移植部分  37.4 CPU  主频和网络驱动修改
和  第五十九章 Linux LCD  驱动实验 部分也讲到这个方法。驱动可以编译成.ko文件,也可以编译进内核,编译成.ko文件的,我们需要用
手动执行指令insmod或者 modprobe来加载这个模块,编译进内核的话就不用手动加载模块了。前者叫动态加载,后者叫静态加载。本次以
《【正点原子】I.MX6U嵌入式Linux驱动开发指南》教程里   第四十二章 新字符设备驱动实验 为例子来将 newchrled驱动编译进内核。

简单总结一下操作步骤:

1、添加驱动.c文件到内核源码的drivers下对应的目录下
2、修改drivers下对应目录下的Kconfig文件
3、修改drivers下对应目录下的Mkefile文件
4、修改设备树
5、执行make distcleanmake defconfig相关的指令,然后执行make menuconfig,在menuconfig菜单中选中我们新添加的驱动,目的是将其编译进内核,最后执行make进行编译。(简单概括就是进行内核的配置和编译
6、将编译好的内核放到开发板上运行,进行验证。

下面我们按照以上简单的步骤进行操作。
PS:我使用的内核源码是我自己根据教程移植的,大家用自己的内核源码的话,配置指令和编译指令就根据自己的配置文件来。
一、添加驱动.c文件到内核源码的drivers下对应的目录下
本实验对应的例程路径为:开发板光盘-> 2Linux 驱动例程-> 3_newchrled,我们在A盘找到驱动源文件newchrled.c,将其拷贝到内核源码的/drivers/leds/下。

图片1.png

内核源码的drivers目录中是系统中所有的设备驱动源程序存放的地方,其下面有分类很多目录,比如/drivers/net下是和网络有关的驱动程序目录,/drivers/sound下的是和声卡有关的,
其实也可以通过目录下的字眼大概辨别出来里边的目录对应的是什么的。这里,新字符设备驱动操作的是一个LED灯的实验,我就把newchrled.c放在了和LED相关的目录下了。

二、修改/drivers/leds/下的Kconfig文件

图片2.png

Kconfig下有很多的config,每一个“config”关键字后面表示定义一个新的配置选项,比如config LEDS_SYSCON这个配置选项,后面的几行代码表示这个配置选项的一些属性信息,属性会包含有
类型、数据范围、输入提示、依赖关系、选择关系及帮助信息、默认值等信息。如bool就是表示一个类型,help就是表示一些帮助信息,depends on表示依赖关系,tristate表示三态选择器,三
态可以有ynm(y就是yes,n就是no,m就是model的意思)意思就是在菜单配置时,有三种选择的情况,分别是编译进内核、不编译、编译成模块驱动。关于Kconfig的配置,大家可以看看教程和视频以及网上查询更加详细的资料介绍。

图片3.png

如下图,添加一个config LEDS_TEST,配置选项,我就照葫芦画瓢了,复制里边现成的然后简单改一下,这个是我添加的一个config,修改好了保存退出。
  1. config LEDS_TEST
  2.         tristate "LED test"
  3.         depends on LEDS_CLASS
  4.         select REGMAP
  5.         help
  6.           This option enables support for the test.
复制代码
图片4.png

三、修改/drivers/leds/下对应目录下的Makefile文件

添加这行:
  1. obj-$(CONFIG_LEDS_TEST)             += newchrled.o
复制代码

配置的时候注意格式和套路,CONFIG_LEDS_TEST其实就是在Kconfig下配置好的config LEDS_TEST,将它们写成大写,newchrled.o就是编译newchrled.c以后生成的文件,
$表示一个取值符号,$(CONFIG_LEDS_TEST)这个就是一个整体,表示取CONFIG_LEDS_TEST的值,CONFIG_LEDS_TEST可以是y(表示编译进内核),也可以是m(表示编译成模块),
或者是n(其实就是不编译,没编译进内核也没编译成模块),到底它是y?是m?或者是是n呢?这个由我们自己在menuconfig菜单配置那里定下来,修改好了保存退出。

图片5.png

四、修改设备树
因为我做的这个实验是点亮和灭掉LED灯的,从原理图上看出这个灯是接在了GPIO1 IO3上,这个灯其实在设备树下有被配置成了呼吸灯了,并且其默认状态是开启的,也就是灯会
亮(呼吸灯就是在文件系统挂载以后灯会一闪一闪的,有被配置成其它灯的也最好关掉吧),这个会影响我的测试,所以我要在设备数下将对应的节点整个注释掉。
  1. /*
  2. ledsss {
  3.                 compatible = "gpio-leds";
  4.                 pinctrl-names = "default";
  5.                 pinctrl-0 = <&pinctrl_gpio_leds>;
  6.                 status = "disabled";//add by lhy
  7.                 led-user {
  8.                         label = "led-s";
  9.                         gpios = <&gpio1 3 0>;
  10.                         linux,default-trigger = "heartbeat";
  11.                        default-state = "on";
  12.                 };
  13.         };
  14. */
复制代码
或者可以不用整段注释掉。修改  default-state = "on";为  default-state = "off";也是可以的

图片6.png

五、进行内核的配置和编译
1)清理内核:
  1. make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
复制代码
图片7.png

2)配置内核:
  1. make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_alientek_emmc_defconfig
  2. make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
复制代码
图片8.png
图片9.png

在执行menuconfig的时候会出来配置菜单,找到Device Drivers了按下回车进入

图片10.png

Device Drivers下找到LED Support,按下回车键入,然后在LED Support下找到LED test ,看到没,这个LED test 就是我们之前在 Kconfig下配置的tristate "LED test"我们按下键盘下Y键就出现
*号了,这个表示选中此选项并编译进内核的意思,按下键盘的M键就会显示M,表示选中并编译成模块。(后面我会啰嗦两句讲一下编译成模块后怎么操作)这里,按下Y键选择编译进内核。

图片11.png

保存并退出,进行内核编译。
3)编译内核

  1. make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
复制代码

图片12.png

PS:这里要啰嗦两句,我们在执行make menuconfig指令,菜单栏配置好了选项,然后保存和退出菜单后会在imx_alientek_emmc_defconfig以及.config文件中找到对应的配置,可以找到CONFIG_LEDS_TEST=y这句。
图片13.png

这个是因为我们在munuconfig的时候,将LED test 这个配置选中并编译进内核了,所以当执行make menuconfig并配置完菜单,保存退出以后,imx_alientek_emmc_defconfig.config下自然多出了这句话。
所以/drivers/leds/Mkefile下的obj-$(CONFIG_LEDS_TEST) += newchrled.o也就等于obj-y+= newchrled.o,即在执行编译内核的时候,内核会根据Makefile的配置信息将newchrled驱动编译进内核。如果我们
在make munuconfig的时候,选择将newchrled驱动编译成模块(也就是在菜单选择的时候选中M),那么CONFIG_LEDS_TEST=m/drivers/leds/Mkefile下的obj-$(CONFIG_LEDS_TEST) += newchrled.o也就等于
obj-m+= newchrled.o,即在执行编译内核的时候,内核会根据Makefile的配置信息将newchrled驱动编译成模块。如果此时再执行distclean指令的话,这些配置就会被清掉了(我遇见有的小伙伴在操作教程
37.4.4 保存修改后的图形化配置文件 这节实验的时候,一不小心又执行了distclean指令,把之前的配置给清理掉了,然后在测试移植好的内核的时候,发现网络不通啦。)
六、进行验证
将编译生成的内核zImage和设备树imx6ull-alientek-emmc.dtb拷贝到开发板上运行(这里我使用TFTP加载的内核和设备树,NFS挂载文件系统)。开发板启动设置环境变量:
  1. setenv serverip 192.168.1.25
  2. setenv ipaddr 192.168.1.100
  3. setenv ethaddr 00:04:9f:04:d2:35
  4. setenv gatewayip 192.168.1.1
复制代码

192.168.1.25是我的ubuntuIP地址,192.168.1.100是开发板的IP地址

  1. setenv bootcmd 'tftp ${loadaddr} zImage;tftp ${fdt_addr} imx6ull-alientek-emmc.dtb; bootz ${loadaddr} - ${fdt_addr};'
  2. setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs rw nfsroot=192.168.1.25:/home/MY/NFS/rootfs ip=192.168.1.110:192.168.1.25:192.168.1.1:255.255.255.0::eth0:off'
复制代码

/home/MY/NFS/rootfs是我ubuntuNFS的文件系统目录

图片14.png

设置好环境变量以后保存,开发板重启。
按照教程编译ledApp然后将生成的ledApp拷贝到ubuntuNFS目录下的文件系统根目录下
  1. arm-linux-gnueabihf-gcc ledApp.c -o ledApp
  2. cp ledApp /home/MY/NFS/rootfs
复制代码
图片15.png

开发板启动后,在文件系统的根目录下查看有了拷贝的ledApp文件,同时查看/dev下已经生成/dev/newchrled设备节点(以前我们在做这个实验的时候,是编译成模块然后通过执行
指令modprobe newchrled.ko加载模块后才能生成/dev/newchrdev这个设备节点,现在编译进内核了直接启动后就有了这个节点了)。

图片16.png

现在我们测试一下功能,执行如下指令:
  1. ./ledApp /dev/newchrled 1                       
  2. ./ledApp /dev/newchrled 0
复制代码

图片17.png

发现当执行第一个指令的时候底板的DS0红灯会亮起,执行第二个指令的时候,底板的DS0红灯会灭掉,现象和我们教程上的一致,实验成功。

七、(啰嗦一下)菜单选中编译成模块的情况
如下如果将newchrled驱动编译成模块,菜单下选中为M(这个方法其实和教程里的方法类似的,只是在编译内核的时候也同时编译生成newchrled.ko文件了,或者之前编译了内核,可以只编译模块make modules来生成.ko文件):

图片18.png

编译完成以后,会发现在内核源码的/drivers/leds下生成newchrled.o文件和newchrled.ko文件,将生成的newchrled.ko文件拷贝到文件系统根目录下。
或者,如果文件系统在ubuntu下,比如NNFS挂载文件系统,可以执行
make modules_install INSTALL_MOD_PATH=/home/MY/NFS/myrootfs
来讲编译好的模块安装到文件系统中,这个INSTALL_MOD_PATH=后面写的文件系统的目录,就是要安装模块到文件系统里,这个目录根据情况来,
如果是要安装到TF卡里的文件系统,就把TF卡插在ubuntu上,这个目录就是/media/MY/roofs
1.png

图片19.png

然后用insmod指令加载驱动,执行 ./ledApp /dev/newchrled 1可以发现灯被点亮了,实验成功。

图片20.png

如果要用modprobe来加载模块驱动的话,记得先执行depmod指令,并且ledApp 文件和newchrled.ko文件最好拷贝到/lib/modules/4.1.15下进行测试。


PS:我们将驱动编译进内核的时候,有时候需要配置设备树,有时候不需要配置设备树,什么时候要配置设备树什么时候不需要就根据对应的驱动来,其实也就是多方面考虑的,
比如我这个实验里有呼吸灯占用了这个GPIO1 IO3,所以我要在设备树下将影响到我测试的节点注释掉,又或者教程  第五十九章 Linux LCD  驱动实验 中也是将LCD驱动编译进了内核,
这个是也是要配置设备树的,设备树里添加了节点和IOMUX,节点里有LCD相关的属性信息等等。对于设备树的理解,大家可以看看左工教程里有关于设备树的文档和视频。

在调试某个驱动的时候,我一般是先以编译成模块的方式来调试,当调试好了以后,如果想把这个驱动编译进内核的话再编译进内核,而不是一上来就直接用编译进内核的方式来调试,
毕竟编译进内核的话编译内核时间比较长,编译成模块的话时间比较快,大大节约了时间。


正点原子开源电子公众号开启了,喜欢的伙伴可以关注哦:https://mp.weixin.qq.com/s/IFDd5am26K1rImLXjoBhEw

1.png


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

12

主题

56

帖子

0

精华

初级会员

Rank: 2

积分
178
金钱
178
注册时间
2020-3-11
在线时间
17 小时
发表于 2020-3-25 23:48:32 | 显示全部楼层
赞,总结的很不错 值得学习
回复 支持 反对

使用道具 举报

3

主题

187

帖子

0

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
558
金钱
558
注册时间
2019-5-22
在线时间
267 小时
发表于 2020-3-26 09:21:17 | 显示全部楼层
学习了
回复 支持 反对

使用道具 举报

4

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
175
金钱
175
注册时间
2019-10-5
在线时间
31 小时
发表于 2020-3-26 11:00:56 | 显示全部楼层
顶起!老兄你再早发两天,我前两天就不用那么痛苦了!
回复 支持 反对

使用道具 举报

9

主题

890

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
2395
金钱
2395
注册时间
2019-9-25
在线时间
398 小时
 楼主| 发表于 2020-3-27 20:12:28 | 显示全部楼层
Evan5566 发表于 2020-3-26 11:00
顶起!老兄你再早发两天,我前两天就不用那么痛苦了!

老哥,有啥好的总结也可以分享分享给大家
回复 支持 反对

使用道具 举报

4

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
175
金钱
175
注册时间
2019-10-5
在线时间
31 小时
发表于 2020-3-27 20:50:20 | 显示全部楼层
仰望星空之云 发表于 2020-3-27 20:12
老哥,有啥好的总结也可以分享分享给大家

未命名1585310763.png 我现在8188eu.ko移植到板子上显示找不到,查了半天找不到原因,有啥解决思路吗兄弟?
回复 支持 反对

使用道具 举报

2

主题

711

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2179
金钱
2179
注册时间
2018-8-27
在线时间
258 小时
发表于 2020-3-28 12:28:14 | 显示全部楼层
可以的哦
回复 支持 反对

使用道具 举报

9

主题

890

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
2395
金钱
2395
注册时间
2019-9-25
在线时间
398 小时
 楼主| 发表于 2020-3-28 14:06:10 | 显示全部楼层
本帖最后由 仰望星空之云 于 2020-3-28 14:07 编辑
Evan5566 发表于 2020-3-27 20:50
我现在8188eu.ko移植到板子上显示找不到,查了半天找不到原因,有啥解决思路吗兄弟?

在执行modprobe之前有执行depmod了么,噢噢噢噢,看到了,执行了,modprobe指令后的那个.ko去掉,就是不加.ko
回复 支持 反对

使用道具 举报

4

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
175
金钱
175
注册时间
2019-10-5
在线时间
31 小时
发表于 2020-3-28 16:03:23 | 显示全部楼层
仰望星空之云 发表于 2020-3-28 14:06
在执行modprobe之前有执行depmod了么,噢噢噢噢,看到了,执行了,modprobe指令后的那个.ko去掉,就 ...

不加.ko的话,没有教程的那些消息。后来发现好像是驱动在开机之后自己就加载了,卸载驱动后再insmod就可以了。目前卡在了连不上WiFi了。。。 未命名1585382452.png
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2020-5-27
在线时间
5 小时
发表于 2020-6-2 22:17:38 | 显示全部楼层
学习了,棒!
回复 支持 反对

使用道具 举报

9

主题

890

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
2395
金钱
2395
注册时间
2019-9-25
在线时间
398 小时
 楼主| 发表于 2020-7-30 10:24:13 | 显示全部楼层
Evan5566 发表于 2020-3-28 16:03
不加.ko的话,没有教程的那些消息。后来发现好像是驱动在开机之后自己就加载了,卸载驱动后再insmod就可 ...

您用的是出厂的文件系统来测试的?有没有用驱动开发指南教程里移植的busybox文件系统,按照教程移植wifi驱动过?
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2020-5-4
在线时间
4 小时
发表于 2020-9-22 09:25:00 | 显示全部楼层
回复 支持 反对

使用道具 举报

6

主题

200

帖子

0

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
1063
金钱
1063
注册时间
2019-9-19
在线时间
194 小时
发表于 2021-4-16 12:35:04 | 显示全部楼层
写得很详细,可以学习下
=======================
出征,嗒嗒嗒——
快点上车!
=======================
回复 支持 反对

使用道具 举报

18

主题

155

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3955
金钱
3955
注册时间
2016-7-8
在线时间
824 小时
发表于 2021-9-1 17:27:26 | 显示全部楼层
醍醐灌顶
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-8 07:21

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表