摘要:嵌入式操作系統(tǒng)I/O驅(qū)動(dòng)系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)是實(shí)現(xiàn)嵌入式操作系統(tǒng)應(yīng)用的關(guān)鍵問題。 文章,首先給出I/O驅(qū)動(dòng)的硬件設(shè)計(jì);其次,針對(duì)硬件給出I/O驅(qū)動(dòng)程序的模塊初始化、模塊的卸載、設(shè)備文件操作接口定義與實(shí)現(xiàn)的詳細(xì)設(shè)計(jì)過程;最后,給出驅(qū)動(dòng)模塊的加載過程與測(cè)試方法。
關(guān)鍵詞:嵌入式操作系統(tǒng);驅(qū)動(dòng)程序;內(nèi)核;系統(tǒng)調(diào)用
中圖分類號(hào):TP316文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2008)09-11742-03
Research of I/O Driver of Embedded Operating System
XIAO Yao-nan, XIAO Liao-liang
(Hunan Railway Professional-Technology College, Zhuzhou 412001, China)
Abstract: The design and implementation of driver system of EOS is the key point for the application of EOS. In this paper, Firstly, the hardware design of the I/O driver is proposed; Secondly, the design of module initialization, module exit, interface definition and implementation of the equipment file operation is presented; Finally, the process of mounding the driver and the test method is presented.
Key words: EOS; Driver; Kernel; System Call
1 引言
隨著微處理器技術(shù)的發(fā)展,嵌入式操作系統(tǒng)越來越微型化和專業(yè)化,嵌入式系統(tǒng)已經(jīng)成為計(jì)算機(jī)應(yīng)用領(lǐng)域的一個(gè)重要組成部分。根據(jù)應(yīng)用場(chǎng)景設(shè)計(jì)硬件電路,裁剪系統(tǒng)內(nèi)核,并量身定制應(yīng)用場(chǎng)景驅(qū)動(dòng)程序是目前嵌入式操作系統(tǒng)到實(shí)際應(yīng)用的關(guān)鍵技術(shù)。為此,文章對(duì)嵌入式操作系統(tǒng)I/O驅(qū)動(dòng)的硬件設(shè)計(jì)、I/O驅(qū)動(dòng)程序設(shè)計(jì)、驅(qū)動(dòng)模塊的編譯與測(cè)試三個(gè)方面進(jìn)行了一些研究。
2 嵌入式操作系統(tǒng)I/O驅(qū)動(dòng)的設(shè)計(jì)
2.1 I/O驅(qū)動(dòng)的硬件設(shè)計(jì)
本文以S3C44B0X作為控制CPU,本系統(tǒng)利用74HC574對(duì)S3C44B0X的數(shù)據(jù)端口進(jìn)行擴(kuò)展,地址線BA20~BA22通LC138擴(kuò)展,形成集成塊的片選信號(hào)。當(dāng)?shù)刂沸盘?hào)為0x10000000時(shí),I/O_CS0低電平有效,即選中IC12,當(dāng)?shù)刂沸盘?hào) 0x10200000時(shí),I/O_CS2低電平有效,將選中其它集成塊,精簡(jiǎn)I/O驅(qū)動(dòng)擴(kuò)展電路如圖1所示。
2.2 I/O驅(qū)動(dòng)程序設(shè)計(jì)
Linux操作系統(tǒng)的設(shè)備驅(qū)動(dòng)程序運(yùn)行在內(nèi)核空間[2],而應(yīng)用程序則運(yùn)行在用戶空間,通過系統(tǒng)調(diào)用或硬件中斷完成從用戶空間到內(nèi)核空間的控制轉(zhuǎn)移[3]。設(shè)備驅(qū)動(dòng)模塊的功能就是實(shí)現(xiàn)系統(tǒng)調(diào)用與中斷處理,從而擴(kuò)展操作系統(tǒng)內(nèi)核的功能[4]。
設(shè)備驅(qū)動(dòng)動(dòng)態(tài)運(yùn)行過程是首先調(diào)用入口函數(shù)init_module()實(shí)現(xiàn)驅(qū)動(dòng)的加載,即調(diào)用register_xxx()函數(shù),該函數(shù)完成設(shè)備驅(qū)動(dòng)的初始化,如寄存器置位、結(jié)構(gòu)體賦值等一系列工作,其中最重要的一個(gè)工作就是向內(nèi)核注冊(cè)該設(shè)備。注冊(cè)成功后,該設(shè)備獲得系統(tǒng)分配的主設(shè)備號(hào)、自定義的次設(shè)備號(hào),并建立起與文件系統(tǒng)的關(guān)聯(lián)。關(guān)聯(lián)建立后上層用戶程序可實(shí)現(xiàn)系統(tǒng)調(diào)用,即可對(duì)設(shè)備實(shí)施操作,比如open、read、write、ioctl等。最后通過調(diào)用unregister_xxx()卸載驅(qū)動(dòng),回收相應(yīng)的資源,使設(shè)備的相應(yīng)寄存器復(fù)位并從系統(tǒng)中注銷該設(shè)備。設(shè)備驅(qū)動(dòng)模塊動(dòng)態(tài)掛載、卸載和系統(tǒng)調(diào)用的全過程如圖2所示。
以下將針對(duì)圖1驅(qū)動(dòng)模塊硬件結(jié)構(gòu)詳細(xì)分析I/O驅(qū)動(dòng)程序的編寫方法并給出設(shè)計(jì)過程。
2.2.1 模塊初始化
模塊初始化module_init(Xiao_I/O_Opr_init)函數(shù)通過參數(shù)Xiao_I/O_Opr_init調(diào)用I/O端口驅(qū)動(dòng)模塊初始化函數(shù)static int_init Xiao_I/O_Opr_init(void),該函數(shù)利用系統(tǒng)函數(shù)void * ioremap(unsigned long offset, unsigned long size)為片選信號(hào)BA22~BA20分配內(nèi)存I/O虛擬地址,從而設(shè)備驅(qū)動(dòng)程序能訪問I/O內(nèi)存地址。同時(shí),在模塊初始化函數(shù)中,register_chrdev()函數(shù)完成字符設(shè)備在內(nèi)核系統(tǒng)中的注冊(cè),并建立與文件系統(tǒng)(Xiao_fops)的關(guān)聯(lián)。模塊初始化函數(shù)如下所示:
#define DEVICE_NAME \"Xiao_I/O_Opr\"
#define SEG_CS00x10000000 //A22,A21,A20=000 ->I/O_CS0
#define SEG_CS10x10200000 //A22,A21,A20=010 ->I/O_CS1
#define SEG_CS20x10300000 //A22,A21,A20=011 ->I/O_CS2
static int_init Xiao_I/O_Opr_init(void)
{ int ret;
cs1_address=ioremap(I/O_CS0, 4);
cs2_address=ioremap(I/O_CS1, 4);
cs3_address=ioremap(I/O_CS2, 4);
ret = register_chrdev(61, DEVICE_NAME, Xiao_fops);
if (ret < 0) {
printk(DEVICE_NAME \" can't get major number\\");
return ret;}
return 0; }
2.2.2 模塊的卸載
模塊卸載module_exit(Xiao_I/O_Opr_exit)函數(shù)從內(nèi)核卸載時(shí),通過參數(shù)Xiao_I/O_Opr_exit來識(shí)別并調(diào)用static void_exit Xiao_I/O_Opr_exit(void)函數(shù)。設(shè)備卸載時(shí)利用iounmap()回收相應(yīng)的資源,并利用unregister_chrdev()函數(shù)從內(nèi)核中注銷設(shè)備。模塊卸載函數(shù)如下所示:
static void_exit Xiao_I/O_Opr_exit(void)
{ iounmap(cs1_address);
iounmap(cs2_address);
iounmap(cs3_address);
unregister_chrdev(61, DEVICE_NAME); }
2.2.3 設(shè)備文件操作接口定義與實(shí)現(xiàn)
設(shè)備文件操作接口定義是用戶使用該驅(qū)動(dòng)設(shè)備的關(guān)鍵,合理定義接口函數(shù)有利于上層應(yīng)用程序?qū)Φ讓佑布目刂撇僮?。本系統(tǒng)驅(qū)動(dòng)模塊定義了open、write、release、ioctl四種設(shè)備文件操作,內(nèi)容如下所示:
static struct file_operatI/Ons Xiao_fops = {
open: Xiao_I/O_Opr_open,
write: Xiao_I/O_Opr_write,
release: Xiao_I/O_Opr_release,
ioctl: Xiao_I/O_Opr_ioctl,
owner: THIS_MODULE,};
根據(jù)設(shè)備文件操作接口定義,每一個(gè)設(shè)備文件操作對(duì)應(yīng)一個(gè)系統(tǒng)調(diào)用,在用戶程序中利用系統(tǒng)調(diào)用對(duì)設(shè)備文件進(jìn)行open/write/release/ioctl操作,系統(tǒng)調(diào)用通過設(shè)備文件的主設(shè)備號(hào)找到相應(yīng)的設(shè)備驅(qū)動(dòng)程序,然后獲取設(shè)備文件操作接口定義的相應(yīng)的函數(shù)指針,接著把控制權(quán)交給該操作函數(shù)。open文件操作的結(jié)構(gòu)如下所示:
static int Xiao_I/O_Opr_open(struct inode *inode, struct file *filp)
{……
/* open操作的具體實(shí)現(xiàn) */
……}
其它三個(gè)操作不再闡述。
3 驅(qū)動(dòng)模塊的編譯與測(cè)試
3.1 模塊的編譯
驅(qū)動(dòng)程序編寫完后,應(yīng)根據(jù)硬平臺(tái)編寫Makefile編譯文件,以下為驅(qū)動(dòng)模塊的Makefile內(nèi)容,應(yīng)注意交叉編譯工具變量CC和變量INCLUDEDIR的設(shè)定應(yīng)根據(jù)編譯平臺(tái)的實(shí)際路徑進(jìn)行修改。
CC = /opt/xscalev1/bin/arm-linux-gcc
INCLUDEDIR = /XSBase270/2.4/Kernel/xsbase/linux-2.4.21 /include
CFLAGS = -D_KERNEL_-DMODULE -Wall -O2
CFLAGS += -I.. -I$(INCLUDEDIR)
TARGET = XIAO_I/O_OPR
OBJ_I/O = $(TARGET).o
SOURCE_I/O= $(TARGET).c
all: $(OBJ_I/O)
$(OBJ_I/O): $(SOURCE_I/O)
$(CC) $(CFLAGS) -c -o $(OBJ_I/O) $(SOURCE_I/O)
clean:
rm -rf $(OBJ_I/O)
3.2 驅(qū)動(dòng)模塊的加載與測(cè)試
將編譯好的驅(qū)動(dòng)模塊下載到硬件平臺(tái)上,進(jìn)入硬件平臺(tái)系統(tǒng)后,利用mknod命令在/dev目錄下建立該設(shè)備的節(jié)點(diǎn)。然后利用下述步驟檢查驅(qū)動(dòng)模塊的正確性。
$insmod XIAO_I/O_OPR.o (掛載驅(qū)動(dòng))
$lsmod(查看當(dāng)前已掛載驅(qū)動(dòng)模塊,將看到驅(qū)動(dòng)XIAO_I/O_OPR)
$rmmodXIAO_I/O_OPR (卸載驅(qū)動(dòng)XIAO_I/O_OPR)
$lsmod(查看當(dāng)前已掛載模塊,XIAO_I/O_OPR驅(qū)動(dòng)被卸載)
上述過程通過后就可以編寫上層用戶應(yīng)用程序調(diào)用并測(cè)試驅(qū)動(dòng)程序邏輯。
4 結(jié)束語
嵌入式操作系統(tǒng)I/O驅(qū)動(dòng)系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)是實(shí)現(xiàn)嵌入式操作系統(tǒng)應(yīng)用的關(guān)鍵問題。 文章,首先系統(tǒng)地介紹了Linux操作系統(tǒng)驅(qū)動(dòng)程序的結(jié)構(gòu);其次,給出了I/O驅(qū)動(dòng)的硬件設(shè)計(jì);再次,針對(duì)硬件給出了模塊初始化、模塊的卸載、設(shè)備文件操作接口定義與實(shí)現(xiàn)的計(jì)詳細(xì)設(shè)計(jì)過程;最后,給出驅(qū)動(dòng)模塊的加載與測(cè)試方法。文章針對(duì)嵌入式操作系統(tǒng)I/O驅(qū)動(dòng)系統(tǒng)的設(shè)計(jì)過程為拓展嵌入式操作系統(tǒng)內(nèi)核研究搭建了一個(gè)良好的平臺(tái)。
參考文獻(xiàn):
[1] Michael K Johnson. Writing Linux Device Drivers[R]. DECUS'95 inWashington,1995.
[2] 程曉宇,畢篤彥. 基于Linux的MPEG-4視頻壓縮卡驅(qū)動(dòng)程序[J].計(jì)算機(jī)工程,2007,(8):270-271.
[3] 梁金千,張躍,甄成. Linux設(shè)備驅(qū)動(dòng)程序架構(gòu)的研究[J].計(jì)算機(jī)工程與應(yīng)用,2002,(8):119-122.
[4] 杜博,方向忠. 嵌入式Linux系統(tǒng)下I2C設(shè)備驅(qū)動(dòng)程序的開發(fā)[J].微計(jì)算機(jī)信息,2006,(4):31-33.