1.準(zhǔn)備工作
 
 ? 首先得安裝好gcc工具鏈,以及開發(fā)環(huán)境,可以看看我的前面的幾步。
 
 ?? 還得編譯好內(nèi)核,一般開發(fā)板都帶了,現(xiàn)在我還不知道配置內(nèi)核,只能按照開發(fā)板默認(rèn)的去編譯,編譯前需要先編譯uboot,建議像我一樣的新手先學(xué)會(huì)驅(qū)動(dòng)編寫,慢慢的去學(xué)習(xí) 內(nèi)核的配置裁剪,我覺得到時(shí)候這個(gè)肯定是非常簡單的過程,只不過沒有找到門道而已,等我會(huì)了一定和大家分享,如果有會(huì)的可以教我一下,在下感激不盡。
 
 我的嵌入式內(nèi)核編譯的路徑為:/home/cfan/linux/linux-3.0.1/? ,這個(gè)待會(huì)會(huì)用到的。
 
 今天我就教大家使用eclipse開發(fā)一個(gè)最簡單的驅(qū)動(dòng)程序,LED驅(qū)動(dòng),其實(shí)使用eclipse編譯這種簡單的驅(qū)動(dòng)可能顯得有點(diǎn)麻煩,如果是大工程我想集成開發(fā)環(huán)境的優(yōu)勢(shì)就會(huì)體現(xiàn)出來了,還有就是eclipse的編輯器界面比較友好,跟RVDS4.0一樣。
 
 
 
 
 
 2.建立驅(qū)動(dòng)工程,設(shè)置eclipse
 
 ?打開eclipse
 
 ?可以在桌面上面建立一個(gè)指向eclipse的快捷鍵,或者到eclipse的目錄執(zhí)行 ./eclipse 即可啟動(dòng),我設(shè)置了eclipse的全局變量,因此只需要在終端中輸入eclipse即可啟動(dòng),如下圖
 
 
 
 
 建議將工程目錄選擇在NFS共享的那個(gè)目錄,這樣方便從開發(fā)板加載驅(qū)動(dòng)或者執(zhí)行程序,我的就選擇在nfs6410這個(gè)共享目錄里面。
 
 新建一個(gè)C項(xiàng)目,空項(xiàng)目
 
 
 
 
 一直下一步,直到下圖位置,填好自己的arm-linux-gcc的路徑。
 
 
 
 
 設(shè)置完成后點(diǎn)擊完成。
 
 到這一步新建工程完成了,此時(shí)還有重要的一部要做,先別急著添加.c文件。在工程上面右鍵,屬性,到 C/C++常規(guī)---->Code Analysis---->路徑和符號(hào)
 
 
 
 
 
 
 點(diǎn)擊下方ExportSettings,將設(shè)置導(dǎo)出為xml文件.我的道出到桌面上面了,這個(gè)大家隨意
 
 
 點(diǎn)擊確定 應(yīng)用 退出即可。
 
 到你剛才保存的位置處打開那個(gè).xml文件,用文本編輯器打開即可,我的在桌面上面,右鍵單擊,使用文本編輯器打開
 
 
 
 
 現(xiàn)在我們還需要將autoconf.h中的宏定義加入到Eclipse中,執(zhí)行如下步驟
 
 打開內(nèi)核的這個(gè)目錄 include/generated/ 這個(gè)按個(gè)人實(shí)際情況而定,我的是 cd /home/cfan/linux/linux-3.0.1/include/generated/ ,另外打開一個(gè)終端 cd到這個(gè)目錄
 
 
 
 
 在剛剛這個(gè)終端中執(zhí)行
 
 
 
   [cpp]?view plaincopy     
 cat?autoconf.h?|grep?define?|awk?'{print?"<macro><name>"?$2?"</name><value>"?$3?"</value></macro>"}'?>?symbol.xml?? 
 
 
此時(shí)打開這個(gè)目錄/home/cfan/linux/linux-3.0.1/include/generated,會(huì)多了一個(gè)文件 
 
 
 
 
 
將 symbol.xml這個(gè)文件用文本編輯器打開 
 
 
 
 此時(shí)文本編輯器里面打開了兩個(gè)xml文件了,將之前導(dǎo)出eclipse的那個(gè)xml文件打開,需要添加一行代碼,在這兩行代碼之間(如果有兩個(gè),是下面的那個(gè))
 
 
 
   [html]?view plaincopy     
 <language?name="C?源文件">?? ?? ?? ?? </language>?? 
 
添加 
 
 
 
 
   [html]?view plaincopy     
 <macro><name>__KERNEL__</name><value>1</value></macro>?? 
 
 
如下圖 
 
 
 
 
 
 添加后
 
 
 
 
 
 
 
 再將剛剛那個(gè)symbol.xml文件里面的所有代碼復(fù)制到
 
 
 
   [html]?view plaincopy     
 <macro><name>__KERNEL__</name><value>1</value></macro>?? 
 
這行的下一行,如下圖 
 
 
 
 
 
 在上面的一個(gè)
 
 
 
   [html]?view plaincopy     
 <language?name="C?源文件">?? ?? ?? ?? </language>?? 
 
 
 
 添加
 
 
 
   [cpp]?view plaincopy     
 <includepath>/home/cfan/linux/linux-3.0.1/include</includepath>?? <includepath>/home/cfan/linux/linux-3.0.1/arch/arm/include</includepath>?? <includepath>/home/cfan/linux/linux-3.0.1/arch/arm/plat-samsung/include</includepath>?? <includepath>/home/cfan/linux/linux-3.0.1/arch/arm/mach-s3c64xx/include</includepath>?? 
 
這里面的路徑要看自己實(shí)際的內(nèi)核路徑進(jìn)行修改,也可以在工程屬性中一個(gè)一個(gè)的添加,就是添加一個(gè)linux有關(guān)的路徑而已。 
 
 
 
 
 
 保存退出即可。
 
 
 
 
 再打開eclipse的剛剛那個(gè)導(dǎo)出的位置,現(xiàn)在將導(dǎo)出的文件導(dǎo)入即可
 
 
 
 
 點(diǎn)擊完成即可,如果導(dǎo)入出問題了,仔細(xì)對(duì)照我的教程。應(yīng)用,退出即可,導(dǎo)入后會(huì)多了幾個(gè)路徑,內(nèi)核目錄里面的頭文件路徑
 
 
 
 
 
 
 
 
 
 
 然后新建一個(gè).c文件
 
 
 
 
 代碼是之前寫的
 
 
 
   [cpp]?view plaincopy     
 ? ? ? ? ? ? ? ?? ?? ?? #include?<linux/miscdevice.h>?? #include?<linux/delay.h>?? #include?<asm/irq.h>?? #include?<mach/hardware.h>?? #include?<linux/kernel.h>?? #include?<linux/module.h>?? #include?<linux/init.h>?? #include?<linux/mm.h>?? #include?<linux/fs.h>?? #include?<linux/types.h>?? #include?<linux/delay.h>?? #include?<linux/moduleparam.h>?? #include?<linux/slab.h>?? #include?<linux/errno.h>?? #include?<linux/ioctl.h>?? #include?<linux/cdev.h>?? #include?<linux/string.h>?? #include?<linux/list.h>?? #include?<linux/pci.h>?? #include?<asm/uaccess.h>?? #include?<asm/atomic.h>?? #include?<asm/unistd.h>?? ?? #include?<mach/map.h>?? #include?<mach/regs-clock.h>?? #include?<mach/regs-gpio.h>?? ?? #include?<plat/gpio-cfg.h>?? #include?<mach/gpio-bank-e.h>?? #include?<mach/gpio-bank-m.h>?? ?? ?? ?? ?? #define?DEVICE_NAME?"OK6410_LED"?? ?? ?? ?? static?long?OK6410_LED_ioctl(?? ????????struct?file?*file,?? ????????unsigned?int?cmd,?? ????????unsigned?long?arg);?? static?ssize_t?OK6410_LED_write(?? ????????struct?file?*file,?? ????????const?char?__user?*buff,?? ????????size_t?size,?? ????????loff_t?*loff);?? static?ssize_t?OK6410_LED_read(?? ????????struct?file?*file,?? ????????char?__user?*buff,?? ????????size_t?size,?? ????????loff_t?*loff);?? ?? ?? ?? ? ? ? ?? static?struct?file_operations?dev_fops?=?{?? ????????.owner??????????????=?THIS_MODULE,???????? ????????.unlocked_ioctl?????=?OK6410_LED_ioctl,?? ????????.read???????????????=?OK6410_LED_read,?? ????????.write??????????????=?OK6410_LED_write?? };?? ?? ?? static?struct?miscdevice?misc?=?{?? ????????.minor?=?MISC_DYNAMIC_MINOR,?? ????????.name?=?DEVICE_NAME,?????????????????????????? ????????.fops?=?&dev_fops,?? };?? ?? ?? struct?semaphore?led_sem;?? ?? ?? ? ? ? ? ? ? ? ? ? ? ?? static?int??__init?OK6410_LED_init(void)?? {?? ????int?ret;?? ????unsigned?int?reg;?? ?? ?????? ????reg?=?readl(S3C64XX_GPMCON);?????? ????reg?&=?(~0xffff);????????????????????? ????reg?|=?0x1111;???????????????????? ????writel(reg,S3C64XX_GPMCON);??????? ????reg?=?readl(S3C64XX_GPMDAT);?????? ????reg?|=?0xf;?? ????writel(reg,S3C64XX_GPMDAT);??????? ?? ????ret?=?misc_register(&misc);??????? ????if(ret?<?0)?? ????{?? ????????printk(DEVICE_NAME?"?can't?initialized?LED!\n");?? ????????return?ret;?? ????}?? ????init_MUTEX(&led_sem);????????????? ????printk(DEVICE_NAME?"?initialized\n");?? ????return?0;????????????????????????????? }?? ?? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? static?long?OK6410_LED_ioctl(?? ????????struct?file?*file,?? ????????unsigned?int?cmd,?? ????????unsigned?long?arg)?? {?? ????return?0;?? }?? ?? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? static?ssize_t?OK6410_LED_write(?? ????????struct?file?*file,?? ????????const?char?__user?*buff,?? ????????size_t?size,?? ????????loff_t?*loff)?? {?? ????unsigned?int?reg;?? ?? ????if(down_interruptible(&led_sem))?????? ????????return?-ERESTARTSYS;?? ????reg?=?readl(S3C64XX_GPMDAT);?? ????reg?&=?(~0xf);?? ????reg?|=?buff[0]?&?0xf;?? ????writel(reg,S3C64XX_GPMDAT);?? ????up(&led_sem);????????????????????????????? ?? ????return?0;?? }?? ?? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? static?ssize_t?OK6410_LED_read(?? ????????struct?file?*file,?? ????????char?__user?*buff,?? ????????size_t?size,?? ????????loff_t?*loff)?? {?? ????unsigned?int?reg;?? ?? ????if(down_interruptible(&led_sem))?????? ????????return?-ERESTARTSYS;?? ????reg?=?readl(S3C64XX_GPMDAT);?? ????buff[0]?=?reg?|?0xfffffff0;?? ????up(&led_sem);????????????????????????????? ?? ????return?0;?? }?? ?? ?? ?? ? ? ? ? ? ? ? ? ? ? ?? static?void?__exit?OK6410_LED_exit(void)?? {?? ????unsigned?int?reg;?? ?? ?????? ????reg?=?readl(S3C64XX_GPMCON);?????? ????reg?&=?(~0xffff);????????????????????? ????writel(reg,S3C64XX_GPMCON);??????? ????misc_deregister(&misc);??????????? }?? ?? ?? ?? ?? module_init(OK6410_LED_init);?? module_exit(OK6410_LED_exit);?? ?? MODULE_AUTHOR("cp1300@139.com");?????????????????????????? MODULE_DESCRIPTION("OK6410(S3C6410)?LED?Driver");????? MODULE_LICENSE("GPL");???? 
 
 
 
 
 
 此時(shí)會(huì)有警告,不管他。
 
 
 
 
 
 
 
 在工程屬性中將自動(dòng)生成makefile選項(xiàng)去掉
 
 
 
 
 
 
 
 3.新建一個(gè)makefile文件修改makefile,編譯驅(qū)動(dòng)文件
 
 
 
   [cpp]?view plaincopy     
 ARCH=arm?? CROSS_COMPILE=arm-linux-?? obj-m?:=?led.o?? KDIR?:=/home/cfan/linux/linux-3.0.1??? PWD?:=$(shell?pwd)?? all:?? ????$(MAKE)?-C?$(KDIR)?M=$(PWD)?modules?? clean:?? ????$(MAKE)?-C?$(KDIR)?M=$(PWD)?clean?? 
 
led.o文件就是你的編譯文件的名稱,按照自己實(shí)際情況修開 
 
 
 
 
 
 保存后按 ctrl+B編譯工程。
 
 完成后會(huì)發(fā)現(xiàn)目錄里面多了一個(gè)led.ko,這就是編譯好的LED驅(qū)動(dòng)模塊。
 
 
 4.加載驅(qū)動(dòng)
 
 在開發(fā)板上面加載驅(qū)動(dòng),沒有NFS的童鞋將led.ko復(fù)制到開發(fā)板中,不管是SD卡還是U盤,有NFS的就好辦了,在串口終端中CD到工程目錄
 
 
 
 
 執(zhí)行 insmod led.ko 加載驅(qū)動(dòng),加載成功后會(huì)發(fā)現(xiàn)LED燈都滅了,后面會(huì)添加這個(gè)驅(qū)動(dòng)的測試程序
 
 
 
 
 到這里使用eclipse編寫驅(qū)動(dòng)就完成了,新手肯定會(huì)覺得太繁瑣,其實(shí)一共就三步,只不過我寫的比較詳細(xì)而已,以后每次建立工程可以直接復(fù)制工程或者導(dǎo)入之前的那個(gè)xml文件皆可,麻煩也之麻煩這一次,希望對(duì)大家有所幫助。
 
 
 5.附加,解決OK6410驅(qū)動(dòng)無法卸載問題。
 
 ?在嵌入式驅(qū)動(dòng)開發(fā)過程中需要頻繁的加載卸載驅(qū)動(dòng),但是使用rmmod的時(shí)候你會(huì)發(fā)現(xiàn),驅(qū)動(dòng)無法卸載,如 rmmod led,卸載的時(shí)候不需要.ko,直接是模塊名,我的寫錯(cuò)了。
 
 
 
 
 這個(gè)可以看我的這篇文章:http://blog.csdn.net/cp1300/article/details/7994014
 
 解決后就可以卸載驅(qū)動(dòng)了。
                            總結(jié)
                            
                                以上是生活随笔為你收集整理的使用eclipse集成开发环境开发第一个嵌入式Linux驱动的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。