嵌入式核心及驅動開發之學習筆記(一) 認識與使用驅動模組
應用層的程序是通過核心層驅動來訪問硬體的,Linux核心原始碼在每次編譯之後生成一個總的映象,將映象載入記憶體中執行並使用(核心在系統執行時會移植佔用核心空間)。驅動屬於核心原始碼的一部分,如果每次修改驅動都要重新編譯載入核心的話,這態麻煩了,所以我們通過模組,使驅動可以獨立於核心映象之外,並能動態的載入和解除安裝。
在搭建好開發環境之後,通過source insight我們可以方便的檢視和編輯核心原始碼,並結合交叉編譯工具鏈實現編輯--編譯--燒錄--執行 的完整開發流程。
- 物理機(Win7) 程式編輯環境
- 虛擬機器(Ubuntu14.04) 程式的編譯環境
- 開發板(FS4412) 程式的除錯執行環境
編寫驅動
建立驅動檔案hello.c,編輯原始碼
#include <linux/init.h> #include <linux/module.h> #include <linux/stat.h> static int __init hello_drv_init(void) { printk("-------%s-------------\n", __FUNCTION__); return 0; } static void __exit hello_drv_exit(void) { printk("-------%s-------------\n", __FUNCTION__); } module_init(hello_drv_init); module_exit(hello_drv_exit); MODULE_LICENSE("GPL");
這個簡單的驅動模組程式碼,沒有涉及到任何硬體,它的功能是可以在載入和解除安裝該模組時列印輸出資訊,僅此。要建立這個框架,分成4個步驟:
1.載入標頭檔案
#include <linux/init.h> 包含模組裝解除安裝函式原型宣告
#include <linux/module.h> 這裡沒有用到其實
#include <linux/stat.h> 包含printk函式的原型宣告
2.驅動模組裝載/解除安裝函式宣告
module_init(hello_drv_init); 裝載 hello_drv_init為回撥函式
module_exit(hello_drv_exit); 解除安裝 hello_drv_exit為回撥函式
3.實現函式入口(回撥函式實現)
static int __init hello_drv_init(void)
{
return 0;
}
static void __exit hello_drv_exit(void)
{
return ;
}
4.GPL宣告
MODULE_LICENSE("GPL"); 一種開源宣告
編輯Makefile的規則
用來負責驅動檔案的編譯和管理。這裡make -C引數,借用了核心原始碼根目錄中的Makefile檔案的規則來編譯驅動程式碼生成成.ko模組。
ROOTFS_DIR = /nfs/rootfs
ifeq ($(KERNELRELEASE), )
KERNEL_DIR = /mnt/hgfs/sharefolder/kernel/linux-3.14-fs4412
CUR_DIR = $(shell pwd)
all :
make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
clean :
make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
install:
cp -raf *.ko $(ROOTFS_DIR)/drv_module
else
obj-m += hello.o
endif
ROOTFS_DIR變數指定 nfs共享跟目錄
KERNEL_DIR變數指定 核心原始碼的根目錄(絕對路徑)
obj-m += hello.o 表示將hello.o這個目標檔案編譯成模組
編譯動作
Ubuntu系統中進入Makefile所在目錄
[email protected]:/mnt/hgfs/sharefolder/kernel/linux-3.14-fs4412/drivers/mydrivers/hello_drv$ make
[email protected]:/mnt/hgfs/sharefolder/kernel/linux-3.14-fs4412/drivers/mydrivers/hello_drv$ make install
載入/解除安裝模組的指令
在核心執行時
- insmod xxx.ko 裝載
- rmmod xxx 解除安裝
- modinfo 檢視
其他
對模組的傳參
有時候對原廠開發,一些程式碼叫做韌體,我們不能進入函式的內部去修改引數的預設指定。通過命令列傳參
- 手動傳遞
insmod hello.ko myname="george" myvalue=33
- 函式接收
module_param(name, type, perm)
符號表
使用 EXPORT_SYMBOL 可以將一個函式以符號的方式匯出給其他模組使用。原理類似於應用層的動態庫。 這樣就使模組與模組之間形成依賴關係(使用方依賴於匯出符號的模組),例如
EXPORT_SYMBOL(my_add); my_add是匯出的函式名
//math.c
#include <linux/module.h>
#include <linux/init.h>
int my_add(int a, int b)
{
return a+b;
}
EXPORT_SYMBOL(my_add);
MODULE_LICENSE("GPL");