前言
自從開始玩 Raspberry Pi 就發現,對於學習使用Linux系統而言,這實在是一個好東西。
想想以前為了安裝Linux系統,都要準備一台不能太新的電腦,然後還要確定上面的硬體都可以找到驅動程式才行。
不然就得弄成雙系統,還常常要重開機切來切去,搞得很麻煩。更不要說是Driver沒寫好結果把系統搞當掉要花時間重新開機了。
雖然之後有virtual box之類的虛擬系統可以使用,但畢竟隔了一層,特別是在要外接USB或是其他I/O裝置的時候就會血壓上升了。
現在,有了Pi一切都不一樣了。
小小一片系統板配上SD或microSD卡,要備份系統就直接製作SD卡映像檔,要重灌就燒回去。實在是太方便了。
而把系統搞當掉,重新開機也不過一分鐘的事情。
這樣小小一個系統,在上面該有的開發工具也都沒有少,要什麼就直接 apt-get 上網安裝。
網路環境?驅動程式已經預設安裝好了,不用再煩惱有的沒有。
開發環境
就學程式語言來說,一開始要做的第一件事情就是準備開發環境。
一般來說,開發Linux Driver的時候,要先搞清楚等一下寫出來的Driver是要放在什麼地方跑? 再來就是要搞清楚,我們要在那邊程式碼在要哪邊寫,寫完後要在哪裡進行編譯的工作?
但是一開始就搞這麼多有的沒的實在是會讓初學者暈頭轉向。所以在還沒有熟悉整個開發流程的時候,先要把整個事情給簡化。
我們要在Pi的Linux系統裡面,編寫、編譯 Driver 程式碼,並且執行編譯出來的Driver
等到之後熟悉整個事情的來龍去脈之後,就可以開始把編寫和編譯Driver程式碼的工作轉移到效能比較好的桌上型電腦Linux系統上去進行。
要編譯Linux Driver必須要有和當前運行的kernel相同版本的Kernel Source 和 當初編譯此kernel時相同版本的gcc編譯器。
這邊強烈建議 自行編譯一次Linux kernel,並使用該kernel做Linux Driver開發。
至於Pi板的核心編譯,可以參考下面的連結
https://www.raspberrypi.org/documentation/linux/kernel/building.md
Quick guide for building Raspberry Pi kernel 4
或是你手上的是最新的 Raspberry Pi 2 (ARM-7) 的板子,可以參考一下小弟的這篇文章:
http://blog.ittraining.com.tw/2015/02/raspberry-pi2-kernel.html
這邊特別說明一下,如果成功編譯並安裝好kernel,開機之後。Kernel Source也放好位置了...如果沒有跑到 Kernel Source 的位置執行過下面這個指令的話,還是不能編譯核心的。
make modules_prepare
記得編譯安裝完核心之後,記得kernel source的目錄下執行一下這一行指令。
所以,在開始hello world之前,確認一下。先進去Pi的linux 系統裡面,看一下/proc/version這個檔案裡面的內容, 可以知道你現在用的kernel版本和當初是編譯這kernel的gcc版本。
cat /proc/version
然後看一下現在預設的gcc版本是不是一致:
gcc --version
筆者在寫這文章的時候編譯核心時用的是gcc 是4.8.3的cross-compiler版本,而Raspbian裡面用apt-get install能裝到最新的gcc版本是4.8.2。 雖然有點小差異,但是目前用起來還沒發現什麼大問題。
來編譯 Hello World 吧
撰寫程式程式碼
Makefile裡面的內容如下:
說明一下,上面make 所用的參數 "-C" 後面是要接 kernel source tree 的存放路徑。
以我的 Pi2 系統上面而言,上面 "$(shell uname -r)" 的部份會變成 "3.18.9-v7+",所以我自行編譯好的 kernel source tree 可以在這個目錄底下找到 "/lib/modules/3.18.9-v7+/build",然而這個檔其實只是個連結,連結到我放kernel source tree 的地方(我喜歡放在我的家目錄底下 "~/rpi2/linux/",這要去看一些code的內容比較方便)。
hello.c的內容如下:
編譯程式碼
在這個目錄下面直接執行:
make
然後就會產生一堆檔案,其中有一個hello.ko的檔就是Linux Driver(驅動程式),或是說Linux Module(模組)檔會比較適合。
載入/卸載 驅動程式(模組)
載入
執行insmod來載入驅動程式:
sudo insmod hello.ko
用dmesg指令看一下系統訊息,是不是在最後一行有顯示出 insmod: Hello World.! 的系統訊息,有的話表示載入成功了。
也可以用 lsmod 指令列出系統中已經載入的驅動程式(Module)有哪些,其中應該會看到 hello 在其中。
lsmod
卸載
執行rmmod來載入驅動程式:
sudo rmmod hello.ko
用dmesg指令看一下系統訊息,是不是在最後一行有顯示出 rmmod: Hello World.! 的系統訊息,有的話表示該模組被卸載了。
執行 lsmod 應該會看到 hello 已經不在其中了。
這樣子就成功跑過一次 hello world 的範例了,而其中最麻煩的部份其實就是準備開發環境要自行編譯過一次kernel,這過程很複雜難搞。
為了充份利用Pi板的特性並降低這個過程痛苦的程度,我們之後會事先編譯好完整的開發環境並且整個打包成一個映檔。
初學者只需要準備一個8G的microSD卡,並把映像檔抓下來燒進去,放進去raspberry pi B+的板子上就可以開始學習開發Linux Driver了。
這樣就不用經歷前面那麼痛苦的過程了。(真是功德無量,功德無量阿~~~哈哈哈...)
(或許這件事情應該放在這篇文章的開頭及早說明...)
--------------- 一切都不如想像中的美好分隔線 ---------------
後來發現搞出來的 8G 映像檔太大,就算壓縮之後還是有3G大小。要讓人下載這麼大的檔案想想實在是不大實際。
所以之後打算只把整個 compile 完的 kernel source 打包成一個檔(大約200多MB),讓人下載解壓縮之後,再在自已的Pi板上面,建立 compile module 的環境。
之後的文章會開始慢慢的進入程式碼和系統運作的講解...。
所以.....待續...
之後的例子會進行到一些和硬體上的溝通行,會需要一些電路和IC的組合。
艾鍗樹莓派子卡非常適合想要學習Linux Driver的人
http://blog.ittraining.com.tw/2016/10/raspberry-pi-io-shield-v30.html
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5G_rNkPmfnE2OeZUKeyoSajq4J1jnjB5okNErIXy0mjO39b162Q-e4Yh3EeovyfBzhTG7rrJ0dT77n69UaBeY-FK8cafQ_q3kdNTHPsrSNXuh-sxsYdZueHg9VTm0LZMRAMwZ-cT4Lw/s280/e_linux_728x90.jpg)
請教一個問題
回覆刪除就是如果我用官方網站的NOOBS
直接裝卡上,安裝執行後
要如何編譯並執行 MODULE 例如 hello.c
是不是一定要先自行編譯一次 Linux kernel
之後才能自己寫 MODULE 例如 hello.c
並執行(insmod.ko)呢?
不一定需要自行編譯一次 Linux Kernel。要編譯 Linux 模組需要配合運行中的 kernel 相同版本的 header 檔和相對應的 gcc 版本。使用官方網站上的 NOOBS 或是其他Linux 發行版的方式所安裝完成的環境,可以試著抓網方維護的 linux-header 檔試看看。如果是要學習 Linux 驅動程式撰寫的話,通常建議去抓 kernel source 下來自行進行跨平台編譯並建置編譯環境。
刪除可以參考一下這個blog的另一篇有關編譯raspbian kernel source的文章: http://blog.ittraining.com.tw/2015/02/raspberry-pi2-kernel.html
歡迎多多討論。
我自行編譯了一份kernel source code 並且打包放在網路上了,可以參考下面這篇,試著裝看看。
刪除http://blog.ittraining.com.tw/2015/03/raspberry-pi-kernel-module.html
作者已經移除這則留言。
回覆刪除想請問一下,M=(shell pwd)代表的意思是什麼呢?我參考過別的文章[1],裡面用的是M=$(PWD)而且後續也沒有加V=1 ARCH=arm。還有就是我的Makefile中把"shell pwd"解譯為
回覆刪除"/home/pi/svn/kernel/SourceCode/trunk/KernelAPI/driver-example/testdriver"
但是實際是我的程式碼放置的位置為"/home/pi/code/testdriver",這是為什麼呢?
請問有推薦的書可以知道嗎?我目正在閱讀"Essential Linux Device Drivers",還有LDD3.pdf
如果是這兩本書有推薦的章節嗎?抱歉問題有點多。
[1]http://rswiki.csie.org/dokuwiki/_media/courses:100_2:lab10_doc.pdf
M=(shell pwd) 及M=$(PWD)都是Makefile 取得你現在compile driver source code的地方, 如果不一樣那就真得有點太其怪了..還是"/home/pi/code/testdriver 其實是一個symbolic link ?!
回覆刪除LDD3 應該有寫, 應該在在前兩章.
另外, 可以參考kernel source tree的文件說明 Documentation/kbuild/modules.txt
感激不盡,正在詳細閱讀中。
刪除