開發(fā)環(huán)境
開發(fā)板:A33-Vstar
開發(fā)板系統(tǒng): Linux/arm 3.4.39 Kernel
Ubuntu版本:Ubuntu14.04
----------------------------------------------------
新增內(nèi)核驅(qū)動(dòng),并可以通過make menuconfig配置。
內(nèi)核完整路徑:~/A33-Vstar/dragonboard/linux-3.4
1. 構(gòu)建測(cè)試模塊:hello
1.1 在linux-3.4/drivers/下新建目錄hello
cd linux-3.4/drivers/
mkdir hello
1.2 在hello/下新建hello.c Makefile Kconfig三個(gè)文件
hello.c:
- #include <linux/module.h> //所有模塊都需要的頭文件
- #include <linux/init.h> // init&exit相關(guān)宏
- #include <linux/kernel.h>
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("baoli");
- MODULE_DESCRIPTION("hello world module");
- static int __init hello_init(void)
- {
- printk(KERN_WARNING "hello world.\n");
- return 0;
- }
- static void __exit hello_exit(void)
- {
- printk(KERN_WARNING "hello exit!\n");
- }
- module_init(hello_init);
- module_exit(hello_exit);
Makefile:
obj-$(CONFIG_HELLO) += hello.o
Kconfig:
- menu "HELLO TEST Driver "
- comment "HELLO TEST Driver Config"
- config HELLO
- tristate "hello module test"
- default m
- help
- This is the hello test driver --by baoli.
- endmenu
1.3 修改上一級(jí)目錄的Kconfig和Makefile
進(jìn)入linux-3.4/drivers/
1)編輯Makefile,在后面添加一行:
obj-$(CONFIG_HELLO) += hello/
2)編輯Kconfig,在后面添加一行:
source "drivers/hello/Kconfig"
注:某些內(nèi)核版本需要同時(shí)在arch/arm/Kconfig中添加:source "drivers/hello/Kconfig"
2. make menuconfig配置
1)執(zhí)行:make menuconfig ARCH=arm
2)選擇并進(jìn)入:Device Drivers選項(xiàng)
可以看到新增 HELLO TEST Driver選項(xiàng)
3)進(jìn)入 HELLO TEST Driver選項(xiàng)
可以選擇<m> <y> <n>,分別為編譯成內(nèi)核模塊、編譯進(jìn)內(nèi)核、不編譯。
3. 編譯
退出保存后進(jìn)入:cd ~/A33-Vstar/dragonboard/
執(zhí)行:sudo ./build.sh 編譯內(nèi)核
1)如果選擇編譯成模塊<m>
編譯內(nèi)核過程中,會(huì)有如下輸出:
LD drivers/hello/built-in.o
CC [M] drivers/hello/hello.o
CC drivers/hello/hello.mod.o
LD [M] drivers/hello/hello.ko
2)如果選擇編譯進(jìn)內(nèi)核<y>
編譯內(nèi)核過程中,會(huì)有如下輸出:
CC drivers/hello/hello.o
LD drivers/hello/built-in.o
編譯完成后,drivers/hello/下新增hello.o和hello.ko,并且/linux-3.4/output/lib/modules/3.4.39/下也會(huì)有hello.ko。
4. 測(cè)試
4.1 編譯成內(nèi)核模塊
下載鏡像至A33開發(fā)板,使用minicom 超級(jí)終端和開發(fā)板連接。
cd /lib/modules/3.4.39
可看到hello.ko在此路徑下。
1)inmod hello.ko
dmesg | tail 顯示hello world.
2)rmmod hello
dmesg | tail 顯示hello exit!
注:hello.ko已經(jīng)被打包進(jìn)系統(tǒng)鏡像文件,在路徑/lib/modules/3.4.39 下,所以下載安裝鏡像后不需要再重新拷貝鏡像至開發(fā)板。
4.2 編譯進(jìn)內(nèi)核
下載鏡像至A33開發(fā)板,系統(tǒng)啟動(dòng)時(shí)在超級(jí)終端上顯示加載信息:hello world.
5. 分析
5.1 source "drivers/hello/Kconfig"
在Kconfig中有類似語(yǔ)句:source "drivers/hello/Kconfig"
內(nèi)核源碼目錄樹中每一個(gè)Kconfig都會(huì)用source引入其所有子目錄下的Kconfig,從而保證了所有的Kconfig項(xiàng)目都被包含進(jìn)menuconfig中。這個(gè)也說明了:如果你自己在linux內(nèi)核中添加了一個(gè)文件夾,一定要在這個(gè)文件夾下創(chuàng)建一個(gè)Kconfig文件,然后在這個(gè)文件夾的上一層目錄的Kconfig中source引入這個(gè)文件夾下的Kconfig文件。
5.2 depends on
意思是本配置項(xiàng)依賴于另一個(gè)配置項(xiàng)。如果那個(gè)依賴的配置項(xiàng)為Y或者M(jìn),則本配置項(xiàng)才有意義;如果依賴的哪個(gè)配置項(xiàng)本身被設(shè)置為N,則本配置項(xiàng)根本沒有意義。depends項(xiàng)會(huì)導(dǎo)致make menuconfig的時(shí)候找不到一些配置項(xiàng)。所以在menuconfig中如果找不到一個(gè)選項(xiàng),但是這個(gè)選項(xiàng)在Kconfig中卻是有的,則可能的原因就是這個(gè)配置項(xiàng)依賴的一個(gè)配置項(xiàng)是不成立的。depends依賴的配置項(xiàng)可以是多個(gè),還可以有邏輯運(yùn)算。這種時(shí)候只要依賴項(xiàng)目運(yùn)算式子的結(jié)果為真則依賴就成立。
5.3 comment
用于定義一些幫助信息,出現(xiàn)在界面的第一行。
5.4 menu/endmenu menuconfig
1)menu用于生成菜單,其格式如下:
menu "Floating poing emulation"
config FPE_NWFPE
config FPE_NWFPE_XP
.............
endmenu
menu之后的Floating poing emulation是菜單名,menu和endmenu間有很多config條目,在配置界面中如下所示:
Floating poing emulation--->
[] FPE_NWFPE
[] FPE_NWFPE_XP
2)menuconfig有點(diǎn)類似menu,但區(qū)別就在于menu后面多了一個(gè)config,這個(gè)menu是可以配置的,如下圖倒數(shù)第二行,前面比 menu類型多了一個(gè)<>,通過空格可以修改這個(gè)配置項(xiàng)的選中狀態(tài)。而且從格式上來看,也是有區(qū)別的。格式如init/Kconfig中1131行:
menuconfig MODULES
tristate "Enable loadable module support"config
if MODULES
xx
endif
也就是說,配置項(xiàng)是位于if和endif中。其中的部分就是MODULES子目錄顯示的內(nèi)容。如果選中了MODULE,那么if和endif中的內(nèi)容可以顯示。如果沒有定義,就只能進(jìn)入一個(gè)空目錄。
可以認(rèn)為是menu和config的結(jié)合體,既在前面有選項(xiàng),回車后也可以展開。
5.5 config
config是構(gòu)成Kconfig的最基本單元,其中定義了配置項(xiàng)的詳細(xì)信息。
1) 每個(gè)config菜單項(xiàng)都要有類型定義: bool布爾類型、 tristate三態(tài)(內(nèi)建、模塊、移除)、string字符串、 hex十六進(jìn)制、 int整型。
例如:
config HELLO_MODULE
bool "hello test module"
bool 類型的只能選中或不選中,顯示為[ ];
tristate類型的菜單項(xiàng)多了編譯成內(nèi)核模塊的選項(xiàng),顯示為< > , 假如選擇編譯成內(nèi)核模塊,則會(huì)在.config中生成一個(gè) CONFIG_HELLO_MODULE=m的配置,假如選擇內(nèi)建,就是直接編譯成內(nèi)核鏡像,就會(huì)在.config中生成一個(gè) CONFIG_HELLO_MODULE=y的配置。
2) default:默認(rèn)值
比如config類型是tristate,則默認(rèn)值可以是y 、m、n。
5.6 Kconfig和.config文件和Makefile三者的關(guān)聯(lián)
經(jīng)過menuconfig配置之后保存,就會(huì)在內(nèi)核頂層目錄下生成.config文件。
=y表示該配置將會(huì)被編譯進(jìn)內(nèi)核,=m表示該配置需要單獨(dú)編譯成模塊。
內(nèi)核頂層makefile會(huì)調(diào)用.config文件,引用.config里的配置,進(jìn)而選擇性的編譯內(nèi)核驅(qū)動(dòng)模塊。
配置項(xiàng)被配置成Y、N、M會(huì)影響“.config”文件中的CONFIG_XXX變量的配置值?!?config”中的配置值(=y、=m、沒有)會(huì)影響最終的編譯鏈接過程。如果=y則會(huì)被編入(built-in),如果=m會(huì)被單獨(dú)連接成一個(gè)”.ko”模塊,如果沒有則對(duì)應(yīng)的代碼不會(huì)被編譯。那么這是怎么實(shí)現(xiàn)的?都是通過makefile實(shí)現(xiàn)的。
如makefile中:obj-$(CONFIG_DM9000) += dm9000.o,
如果CONFIG_DM9000變量值為y,則obj += dm9000.o,因此dm9000.c會(huì)被編譯;如果CONFIG_DM9000變量未定義,則dm9000.c不會(huì)被編譯。如果CONFIG_DM9000變量的值為m則會(huì)被連接成“.ko”模塊。
6. 問題及解決
make menuconfig 出現(xiàn) endmenu in different file than menu
1)問題描述
添加一個(gè)驅(qū)動(dòng),然后在內(nèi)核的頂層目錄進(jìn)行如下操作
make menuconfig
出現(xiàn)了如下錯(cuò)誤提示:
'endmenu' in different file than 'menu'
2)解決方案
在添加的驅(qū)動(dòng)程序目錄中,在Kconfig文件內(nèi)
menu "Test Driver" config CONFIG_TEST bool "Test support" endmenu
注:在“endmenu” 下必須留一個(gè)空行。即 "endmenu" 后輸入一個(gè)回車,保存。
聯(lián)系客服