一、驱动程序存在的形式
1、将驱动编译成一个ko,ko是一个独立的module
驱动程序安装:#insmod led_drv.ko
驱动程序卸载:#rmmod led_drv.ko
2、如何开机自动安装驱动,运行应用程序。
/test/led_drv.ko /test/test
修改/etc/profile:
#vi /etc/profile
cd /test
insmod led_drv.ko
./test &
cd /
3、将驱动程序编译到linux内核中,使驱动程序和linux内核成为一个整体。
当linux内核启动的过程中,会自动的安装驱动。
内核的编译过程:
Image(未压缩的内核映像)—>zImage(压缩)—>mkimage(uboot生成工具)将zImage加个头—>uImage---->ext4文件系统打包,生成boot.img
二、如何将一个驱动程序编译进内核
1、将驱动程序放入内核源码
/kernel/drivers/char/leds/led_drv.c
2、创建一个Kconfig文件
/kernel/drivers/char/leds/Kconfig
menu "GEC6818 LED Driver"
config GEC6818_LEDS
tristate "led drivers for gec6818"
depends on ARCH_S5P6818
default y
help
this is a driver for GEC6818, D8---GPIOC17,D9--GPIOC8
,D10--GPIOC7,D11--GPIOC12
endmenu
Kconfig作用:定义一个条件编译选项和配置菜单。当make menuconfig弹出Kconfig定义的菜单,对条件编译选项赋值。
分析Kconfig文件:
1)menu "GEC6818 LED Driver"
endmenu
----菜单的开始,菜单的名字,菜单的结束。----->make menuconfig时会看到
2)config GEC6818_LEDS
定义了一个条件编译选项,条件编译选项在使用时候会加一个前缀:CONFIG_。make menuconfig是对条件编译选项进行赋值,在Makefile编译驱动的时候,会使用条件编译选项。
3)tristate "led drivers for gec6818"
条件编译选项的值是tristate:
Y —> 驱动程序编译进内核
M —> 驱动程序不编译进内核,但是在驱动程序的源码目录下,会生成一个ko
N —> 驱动程序不编译
扩展:
tristate —> Y–<*>, M–, N–< >
bool —>Y–[*], N–[ ]
4)depends on ARCH_S5P6818
条件编译选项GEC6818_LEDS是依赖于条件编译选项ARCH_S5P6818的,只用ARCH_S5P6818的值为Y的时候,才有机会对ARCH_S5P6818条件编译选项进行赋值。
5)default y
条件编译选项的值默认是Y
6)help
this is a driver for GEC6818, D8—GPIOC17,D9–GPIOC8
,D10–GPIOC7,D11–GPIOC12
帮助说明。
3、创建一个Makefile文件
/kernel/drivers/char/leds/Makefile
obj-$(CONFIG_GEC6818_LEDS) += led_drv.o
bobey@ubuntu:~/6818GEC/kernel/drivers/char/leds$ ls
Kconfig led_drv.c Makefile
思考:我们创建的Makefile和Kconfig有和linux内核的Makefile与Kconfig联系在一起吗?
如何联系在一起?
4、修改上一级目录下Kconfig
/kernel/drivers/char/Kconfig
source "drivers/char/leds/Kconfig"
5、修改上一级目录下的Makefile
/kernel/drivers/char/Makefile
obj-y += leds/
6、配置内核
bobey@ubuntu:~/6818GEC/kernel$ cp arch/arm/configs/GEC6818_defconfig .config
bobey@ubuntu:~/6818GEC/kernel$ make menuconfig
找到配置的位置:搜索条件编译选项
│ Symbol: GEC6818_LEDS [=y] │
│ Type : tristate │
│ Prompt: led drivers for gec6818 │
│ Defined at drivers/char/leds/Kconfig:3 │
│ Depends on: ARCH_S5P6818 [=y] │
│ Location: │
│ -> Device Drivers │
│ -> Character devices │
│ -> GEC6818 LED Driver
Device Drivers --->
Character devices --->
GEC6818 LED Driver --->
<*> led drivers for gec6818 (NEW)
保存、退出
7、保存配置
bobey@ubuntu:~/6818GEC/kernel$ cp .config arch/arm/configs/GEC6818_defconfig
8、编译
./mk -k
编译输出:
CC drivers/char/leds/led_drv.o
OBJCOPY arch/arm/boot/Image
Kernel: arch/arm/boot/Image is ready
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
UIMAGE arch/arm/boot/uImage
Image arch/arm/boot/uImage is ready
/home/bobey/6818GEC/out/release/boot.img
9、将boot.img烧写到emmc
1)fastboot
2)恢复卡
10、内核在启动的过程中,会自动安装驱动
比喻:
驱动源文件:/kernel/drivers/char/leds/led_drv.c ---->饭店的原材料
条件编译选项:config GEC6818_LEDS ---->一道菜的ID
tristate “led drivers for gec6818” ---->tristate —菜有三种选择:Y—在饭店吃,M—菜打包,N–菜没有点
---->“led drivers for gec6818” —>菜单上看到的菜名
default y ---->这道菜默认是点中,并在饭店吃的。
depends on ARCH_S5P6818 ---->包厢
Kconfig ---->饭店的菜谱
make menuconfig —> 点菜的过程
.config —>点菜后,下给饭店的单
GEC6818_defconfig —> .config备份
Makefile —>饭店的厨师
boot.img ---->上桌的菜
led_drv.ko —>打包的菜
关键:条件编译选项
条件编译选项在Kconfig中定义,make menuconfig对条件编译选项进行赋值,条件编译选项赋值后保存到.config中, Makefile根据条件编译选项的值来编译驱动源文件。
三、条件编译选项使用
问题1:
在linux内核源码,使用了条件编译选项:
//arch/arm/mach-s5p6818/devices.c
static struct platform_device *i2c_devices[] = {
#if defined(CONFIG_I2C_NXP_PORT0)
&i2c_device_ch0,
#endif
#if defined(CONFIG_I2C_NXP_PORT1)
&i2c_device_ch1,
#endif
#if defined(CONFIG_I2C_NXP_PORT2)
&i2c_device_ch2,
#endif
};
使用了3个条件编译选项:CONFIG_I2C_NXP_PORT0、CONFIG_I2C_NXP_PORT1、CONFIG_I2C_NXP_PORT2
如何知道这三个条件编译选项时候定义了。
知道:
条件编译选项在Kconfig中定义,make menuconfig对条件编译选项进行赋值,条件编译选项赋值后保存到.config中, Makefile根据条件编译选项的值来编译驱动源文件。
所以:通过查找.config文件,可以知道条件编译选项是否定义。
在内核源码的编译过程中,.config文件会生成一个头文件。
.config ----> kernel/include/generated/autoconf.h
将autoconf.h拷贝到source insight工程中。
问题2:
如何清除内核的编译:
bobey@ubuntu:~/6818GEC/kernel$ make clean
bobey@ubuntu:~/6818GEC/kernel$ make distclean
make clean 和meke distclean区别
make clean—>清除编译过程中生成目标文件、库文件、映像文件
make distclean —>make clean + 清除配置文件(.config)