自從選擇了物聯網這個專業,智能XX的字樣牽動着每個學習這個專業的孩子。html
你們興致勃勃的來到了學校,結果一切想象和本身的設想並不同。想象中的各類智能般夢幻的場景變成了真實的高數/電路/模電等等諸如此類!不知道這個世界何時變得如此的浮躁,當你們的一段時間的努力看不到結果的時候就每每會不太感興趣,模電你們都沒聽懂,因而你們自我安慰tmd學這玩意到底幹什麼?本人當初也是這樣,但是到了後來接觸了單片機,接觸了應用電路的設計才知道那些課程那個沒用啊!當初仍是too young,too simple呀!linux
這個學期也將要過去了,明年就開始去實習啦!趁着如今就實現本身的物聯網夢想吧!沒錯,就是比較惡俗的智能傢俱系統。
web
考慮到單片機侷限比較大,遂向同窗借了一塊友善之臂的板子,本人第一次接觸arm,單片機系自學,文中又搞笑的地方你們笑笑就好了,若是能給予指正,那就更好了。先來實現一個比較簡單的功能,即經過web遠程控制燈光的亮滅。要實現這個功能,咱們須要在嵌入式linux的平臺上寫led的驅動,要學習驅動咱們直接寫led的驅動可能難度比較大,並且不易成功,因此咱們先用著名的helloworld來熟悉環境。模塊化
如今,愈來愈以爲和計算機打交道,要有兩條準則:1 思路要清晰 2 實現過程要一步一步。由於計算機是機器,0和1的世界,程序過程當中稍不注意就會錯誤百出。因此寫程序過程當中必定要步步爲營,一點一點測試,一點一點推動,這樣看似很慢,卻很是有效也容易成功。好了,不爲我寫hellow辯護了。其實我在寫helloworld的時候也是作準備了,那就是在pc端上已經成功的測試過了。函數
在補充一點,咱們寫的驅動程序最終都是要加載進內核的,咱們有兩種方法添加到內核中。第一種是直接編進內核裏,第二種是動態編進內核裏。動態加入內核就是咱們把本身的驅動程序當作一個模塊,而後把這個模塊加載到內核內。直接編譯進內核就是這個模塊和內核一塊兒編譯,若是有什麼這個驅動有什麼問題的話,咱們還須要調試編譯整個內核,所以剛開始學習的時候我採用了模塊化的動態加載內核。學習
下面就開發過程當中的一些地方作一些記錄:測試
1 在pc機上爲目標機編寫驅動程序的.c文件應該放在哪裏比較好? spa
這個應該放在目標機內核的目錄。好比個人是友善之臂的板子,由於helloworld是字符設備,所以hello.c就建在了/opt/FriendlyARM/mini2440/linux-2.6.32.2/drivers/char的目錄內。爲何要建在這裏,由於這樣咱們能夠藉助與char內的makefile來編譯出模塊,也就是說咱們沒必要本身單獨寫makefile,有點抱大腿的趕腳。操作系統
2 最簡單的helloworld模塊是什麼樣的?.net
1 #include <linux/kernel.h> 2 #include <linux/module.h> 3 static int __init mini2440_hello_module_init(void) 4 { 5 printk("Hello, world !\n"); 6 return 0; 7 } 8 static void __exit mini2440_hello_module_cleanup(void) 9 { 10 printk("Good-bye!\n"); 11 } 12 module_init(mini2440_hello_module_init); 13 module_exit(mini2440_hello_module_cleanup); 14 MODULE_LICENSE("GPL");
第一行和第二行就不說了,由於咱們用到了內核的相關函數以及模塊的一些東西,所以必需要聲明。
最後一行是內核2.6以上版本建議你們把模塊的lincense帶上。
在咱們動態加載和卸載模塊的時候,咱們須要init_module和exit_module這兩個函數來加載,而上面的代碼中並無。緣由在哪裏呢?
原來是module_init和module_exit在做怪。以module_init爲例,這個函數有兩個功能,一個是驗證傳入的參數是否爲正確的模塊格式,另外一個是將參數更名字爲init_module。這樣模塊就能被成功的加載了。
雖然上面的module是個空架子,可是也可讓咱們對模塊有個感官的認識。
3 編譯這個模塊前須要作那些準備?
第一步,將模塊添加到內核菜單,這樣在咱們啓動內核菜單的時候才能對咱們新添加的模塊進行配置。
1 config HELLO_MODULE 2 tristate "hello module" 3 depends on MACH_MINI2440 4 default m if MACH_MINI2440 5 help 6 hello module
這個模塊就是比照着周圍的模塊寫的,固然了,用戶手冊上也是詳細步驟的。
簡單看下這段代碼,tristate就是這個模塊在內核菜單中顯示的名字。
depends on 是依靠的平臺,下面是說若是依靠這個平臺默認的是動態加載到內核。
添加完以上的代碼,回到linux內核目錄下,make menuconfig調出內核編譯菜單。在字符設備的地方能夠找到新添加的hello模塊。
第二步,添加完代碼後,還須要將編譯文件Makefile和源碼聯繫起來,這樣執行makefile的時候才能找到源碼進行編譯。由於咱們是在內核下抱大腿寫的makefile,因此咱們沒必要從新寫makefile,只須要在字符設備的makefile文件中添加這個關係就能夠了。
1 obj-$(CONFIG_HELLO_MODULE) += hello.o
這樣一來,make的時候就能找到hello模塊的源文件啦!
4 編譯模塊和檢驗模塊
在2.6之後版本的內核中,咱們只須要在內核目錄下執行make modules即可以編譯模塊。
在編譯模塊後必定要作最重要的檢驗工做,能夠用modinfo命令查看生成的.ko文件的信息。最重要的是覈對.ko文件的vermagic: 所顯示的內核信息和你目標板的內核信息是否一致,這點灰常重要,不然即使你移植到了目標板,也不能加載成功。
5 加載測試
好了,如今咱們該檢驗結果啦,雞凍啊!在模塊當前目錄,用insmod來加載咱們的hello.ko模塊。
什麼竟然神馬也木有,心頓時涼了半截。。。。。。
還好不是神馬大問題,上面文章已經說過啦!printk是內核級別的函數,查看須要輸出:dmesg | tail
另外,也能夠採用lsmod指令來驗證模塊是否加載成功。
最後刻意驗證了這個模塊的生命週期,退出終端從新進入,查看模塊還在。從新啓動後發現模塊不見鳥。
至此,全部的工做都完成鳥。第一個在嵌入式設備上開發的第一個雞肋驅動就完成了。在整個過程當中以爲,只要一步一步來問題都是能夠解決的,機器是很是認真的,只要咱們按照機器同樣的思惟認真的去一步一步解決問題的時候,發現你就能夠hold住機器,md,之後會不會變成了一個和機器同樣的人。。。。
發現了爲何你們夥都說嵌入式入門灰常難,其實就是灰常繁,你們能夠看上面那麼多東西基本上沒有涉及到和智商有關的東西,所有都是步驟程式化的,當本身沒有走完一個流程的時候發現這玩意太難了,當走完一個流程後會以爲,nima,什麼玩意。。。。。
問題解決前先後後大概一兩天吧!發現越是糾結的時候長的問題,當結果出來那一刻會更興奮,越是容易的問題,解決後沒有一點興奮的趕腳!
又扯遠啦!立刻進入真槍實彈的驅動-led驅動啦! 加油!md,我是誰,這麼帥氣的男淫!
最後以爲linux裏面的Makefile和Kconfig真強大,linux內核是一個大工程啦,經過Kconfig一層一層的去創建菜單,經過Makefile文件來批量的去編譯,真是太強大了。這樣以來以爲linux雖然作個什麼東西都特別麻煩,可是更能讓咱們清楚的去了解系統的工做原理,linux和單片機真不愧是學習操做系統和計算機組成原理的法寶啊!
固然,過程當中還會有不少的錯誤,這裏沒有一一列出。下面推薦一些這個過程當中可能幫助咱們的一些網友 的博客:
若是你的內核菜單沒有出現你添加的模塊,請參考
http://blog.csdn.net/hadise/article/details/6222538
inti_module/exit_module的詳細分析,請參考
http://www.embedu.org/Column/Column517.htm
建議第一次接觸的朋友能夠如今pc機上的系統去實現一下,這樣過渡一下效果會更好一點,下面是pc機上實現helloworld驅動的連接:
http://www.cnblogs.com/heat-man/articles/4174899.html
最後想借此認識一些嵌入式linux的同夥,由於你們一走才能走的更歡樂,才能走的更遠!
若是那個大牛有什麼好的建議和方法,那這篇文章就賺大發啦!