嵌入式开发记录-day16 驱动开发-linux最小驱动开发、Makefile、U盘挂载
1、配置Makefile编译环境
1、拷贝linux内核文件iTop4412_Kernel_3.0_20200410.tar.gz到/home/topeet/下,并解压 tar -zvxf iTop4412_Kernel_3.0_20200410.tar.gz
2、cd iTop4412_Kernel_3.0
3、修改Makefile文件 vim Makefile,将
ARCH ?= arm
CROSS_COMPILE ?= /usr/local/arm/arm-2009q3/bin/arm-none-linux-
4、配置内核,由于使用的是iTOP-4412的板子,所以在目录下/home/topeet/iTop4412_Kernel_3.0/arch/arm/configs/找到iTop-4412_defconfig文件
5、将iTop-4412_defconfig文件拷贝到根目录/topeet/iTop4412_Kernel_3.0/下
cp iTop-4412_defconfig /topeet/iTop4412_Kernel_3.0/
mv iTop-4412_defconfig .config // 重命名.config 文件 有可能拷错了内核版本,可以再尝试下,或者将正确的内核拷贝过去,再试试
make menuconfig // 执行命令
// 执行make menuconfig 有可能出错,提示如下
root@liu-virtual:/home/topeet/iTop4412_Kernel_3.0# make menuconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
*** Unable to find the ncurses libraries or the
*** required header files.
*** 'make menuconfig' requires the ncurses libraries.
***
*** Install ncurses (ncurses-devel) and try again.
***
make[1]: *** [scripts/kconfig/dochecklxdialog] 错误 1
make: *** [menuconfig] 错误 2
// 缺少库文件
sudo apt-get install libncurses5-dev
make menuconfig // 再次执行
//弹出窗口,使.config文件生效,可以不用做修改,
// 直接退出,但是必须执行,.config 与之前发生变化
6、编译内核
linux内核版本大于3,所以执行make
make // 执行make命令,等待一段时间
有可能出错,提示
drivers/misc/inv_mpu/mpuirq.c:256: error: expected ')' before 'KBUILD_MODNAME'
drivers/misc/inv_mpu/mpuirq.c:256: error: 'KBUILD_MODNAME' undeclared here (not in a function)
drivers/misc/inv_mpu/mpuirq.c:256: error: expected ',' or ';' before string constant
make[3]: *** [drivers/misc/inv_mpu/mpuirq.o] 错误 1
make[2]: *** [drivers/misc/inv_mpu] 错误 2
make[1]: *** [drivers/misc] 错误 2
make: *** [drivers] 错误 2
gedit mpuirq.c // 打开文件将256行注释掉,重新执行,还有警告但是,没有错,正常执行完毕;猜测应该mpu模块的驱动用不了;
7、安装内核
make modules_install // 安装模块
make install // 安装内核
// 修改timeout 开机时候选择启动内核
gedit boot/grub/grub.cfg
// 将set timeout = 0,0改为5
8、然后重启reboot
详细配置请看大佬 https://blog.csdn.net/crazycoder8848/article/details/44131735
--------------------------------------------由于上面太折腾了,所以换了讯为已经弄好的Ubuntu镜像,但是还是下了好久------------------------------------
2、最简linux驱动
mini_linux_module.c
1 #include <linux/module.h>
2 #include <linux/init.h>
3
4 //2、 必须遵循GPL协议
5 // 没有linux版本限制、且开源
6 MODULE_LICENSE("Dual BSD/GPL");
7 // 声明作者可有可无
8 MODULE_AUTHOR("TOPEET");
9
10 // 3、
11 static int hello_init(void)
12 {
13 // KERN_EMERG表示终端无论是什么权限 都可以打印出来后面字符串
14 // 七种打印方式,调试的时候可能会用到
15 printk(KERN_EMERG "HELLO WORLD enter!\n");
16 return 0;
17 }
18 static void hello_exit(void)
19 {
20 printk(KERN_EMERG "HELLO WORLD exit!\n");
21 }
22
23 //1、 入口函数module_nint
24 module_init(hello_init);
25 module_exit(hello_exit);
3、编写Makefile文件
#!/bin/bash
#通知编译器我们要编译模块的哪些源码
#这里是编译Mhello.c这个文件编译成中间文件Mhello.o
obj-m += Mhello.o
#源码目录变量,这里用户需要根据实际情况选择路径
#作者是将Linux的源码拷贝到目录/home/topeet/下并解压的
KDIR := /home/topeet/Andord/iTop4412_Kernel_3.0
#当前目录变量
PWD ?= $(shell pwd)
#make命名默认寻找第一个目标
#make -C: 指定内核源码所在的目录。
#$(KDIR)Linux源码目录,作者这里指的是/home/topeet/iTop4412_Kernel_3.0
#$(PWD)当前目录变量
# M: 指定Makefile和源文键Mhello.c所在的目录
#modules要执行的操作
all:
make -C $(KDIR) M=$(PWD) modules // 这里的空格一定要使用linux下的Tab键
#make clean执行的操作是删除后缀为o的文件
clean:
rm -rf *.o // // 这里的空格一定要使用linux下的Tab键
4、编译模块
make // 执行make命令

执行make后,进入Linux内核所在的源码目录,编译出Mhello.o,再运行MODPOST生成临时的Mhello.mod.c,再根据这个文件生成Mhello.mod.o文件,最后再链接
Mhello.o和Mhello.mod.o生成Mhello.ko文件。
其中生成的Mhello.mod.c产生了Linux可执行、可连接的ELF文件的第二个节点信息。
5、验证
将生成的mini_linux_module.ko文件拷贝到U盘中,在开发板上运行;
mount /dev/sda1 /mnt/disk // 挂载U盘
insmod /mnt/disk/mini_linux_module.ko // 加载模块
lsmod // 查看模块第一种方法
cat /proc/modules // 查看运行模块第二种方法
rmmod mini_linux_module.ko // 卸载模块,卸载模块不需要添加路径,否则有可能无反应,而卸载失败
--------------------------剩下的仅供参考----------------------------------
6、关于rmmod模块无法卸载问题总结
rmmod mini_linux_module.ko 执行无法找到某些文件,根据提示,添加文件即可;
rmmod mini_linux_module.ko命令执行,提示没有某些文件,根据提示,添加也可以;
rmmod mini_linux_module.ko命令执行成功,但是没有打印退出消息,但是没有报错,lsmod查看模块还在,
rmmod mini_linux_module.ko执行失败原因总结
执行时,不要加U盘路径 rmmod /mnt/disk/mini_linux_module.ko
进入Ul盘里面执行:rmmod mini_linux_module.ko 不要加后缀ko,执行rmmod mini_linux_module
若提示需要添加文件3.0.15类似文件,使用uname -r 查看 xxx
mkd /lib/modules/xxx
执行结果:
[root@iTOP-4412]# insmod /mnt/disk/mini_linux_module.ko
[ 421.102380] HELLO WORLD enter!
[root@iTOP-4412]# lsmod
mini_linux_module 700 0 - Live 0xbf008000
[root@iTOP-4412]# rmmod mini_linux_module
[ 431.513047] HELLO WORLD exit!
7、加载模块:
insmod mini_linux_module.ko // 加载模块 lsmod // 查看模块 rmmod mini_linux_module // 卸载模块
8、需要注意:.config
linux中使用.config来确认哪些模块驱动代码编译进内核,可以使用基于文本菜单的配置界面make menuconfig来配置.config文件,是否需要将设备驱动,编译进内核中,然后再make zImage,生成相应的内核镜像文件;
字符设备一般在Character device驱动中;
9、linux内核裁剪
make menuconfig配置模块的三种属性:
<> 不编译状态;
<M> 对应的部分编译成模块
<*> 将对应的代码编译进内核
vim driver/char/Kconfig
找到LEDS注册的驱动代码(/LEDS ),仿照LEDS 代码,增加HELLO_CTL模块
config HELLO_CTL
tristate "Enable HELLO config"
default y
help
Enable HELLO config
//bool :只可以编译或者不编译
// tristate 可以编译进内核,或者不编译进内核,也可以编译成模块
make menuconfig // 在里面找打HELLO_CTL模块,选择<M>编译成模块,可以查看.config文件变化;
10、在make menuconfig中,取消LEDS驱动编译进内核,声称zImage镜像,烧写进来,查看LEDS驱动是否存在,并查看HELLO_RTL 模块
11、Makefile 、Kconfig、.config三者之间关系
在执行make menuconfig后,执行当前目录下的scripts脚本scripts Kconfig,在这里Kconfig是该脚本的输入文件,那么.config就是该脚本的输入文件。
这有点类似去饭店吃饭一样,Kconfig是饭店的菜单,我们可以选择或者不选择这个菜(也就是编译或者不编译进内核,或者编译成模块),选择好了后,服务员记
录了我们点的菜的菜单(这个菜单就是.config),饭店根据这份菜单做出一大堆饭菜(在编译时,内核根据每一级的.config文件编译出一个定义好的新内核)。
12、Linux内核编译
在Linux内核源码根目录下,执行make zImage,在arch/arm/boot目录下生成,zImage镜像文件。
为什么会生成镜像文件在这个目录下?
因为在这个目录下的Makefile文件中定义了,在当前目录生成zImage目标文件,虽然在其他路径下makefile也有目标文件,但都是中间临时的目标文件。

浙公网安备 33010602011771号