天天看點

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

經過兩個星期的學習,終于成功寫出了第一個驅動程式->點亮LED小燈;感覺聽上去很簡單似的,哈哈,樓主我可是經過了無數次實驗才成功移植U-boot、Linux核心、最小根檔案系統,并完成了LED控制的驅動,過程經曆了多次百度CSDN論壇,還有請教韋老師,最後能夠在開發闆上完全運作,并對Linux驅動開發有了初步的了解 ;這裡補點雞湯:發這篇文章的初心出于讓更多人了解下相關領域,讓相關專業、領域的人士知道嵌入式Linux驅動的開發流程;空間就應該多一點這種正能量的文章,學到是自己的,大學的教學很少有這種嵌入式Linux驅動的開發,不喜勿噴!

該文屬自身感受和開發過程中遇到的問題在此和大家分享一下 :

U-boot基礎:很多人可能會說,現在直接用基于windows的MDK就可以完成開發(例如:keil),那為什麼還要用基于Linux的環境開發嵌入式呢?Keil這種內建的MDK适合中小型公司開發,不适合大公司協作,它隐藏了太多的技術細節,比如:單闆上電後是如何執行程式的?是不是必須要有main函數?在C調用函數之前需要對硬體進行什麼操作?中斷服務子程式是如何執行的?等等這寫問題,我想對技術有濃厚興趣的人一定很想了解。我來依照上述問題給出自己的一些想法 ;單闆上電後從程式連結位址(依賴.lds、Makefile檔案)處執行程式,涉及到位址就要用彙編,闆子上電的啟動需要依靠start.S這個啟動檔案 ,這個檔案裡包含各硬體的初始化,如:系統時鐘初始化(如果沒設定時鐘闆子以外部晶振12M速度運作,S3C2440),關看門狗,初始化SDRAM、初始化NAND FLASH(如果為NAND啟動)、代碼重定位(從FLASH将代碼全拷貝到SDRAM,為什麼要進行代碼重定位呢?如果程式從NOR FLASH啟動,那可以直接讀取代碼到處理器,但沒進行一些操作不能寫資料到NOR FLASH,并且NOR FLASH上運作程式效率會大打折扣;如果是NAND FLASH啟動,系統上電會把NAND FLASH前4K内容拷貝到片内SRAM(stepping-stone)運作,程式小于4K還可以,那大于4K呢?豈不是要丢失程式代碼,不能實作功能,是以需要進行代碼重定位)、初始化棧指針 ldr sp, =0x34000000(棧向下增長,将棧設定到記憶體頂邊境處 C函數的調用需要進棧出棧);那上面這些有關硬體啟動的就是bootloader的第一階段,第二階段是将核心從NAND FLASH讀出到SDRAM,并設定啟動參數(向核心傳遞記憶體、指令行參數、核心入口等),最後跳轉到核心處執行。U-boot在核心啟動後便不會起作用了。U-boot是一種很強大的bootloader,它可以支援多種單闆,可以去伺服器ftp://ftp.denx.de/pub/u-boot/下載下傳壓縮包進行解壓縮、修改、裁剪配置自己的bootloader。

這裡總結一下,U-boot的最終目的為啟動核心。

核心的啟動:核心可以到官網https://www.kernel.org/下載下傳;為什麼需要啟動核心呢?Linux核心的最終目的是挂接根檔案系統,讓上層軟體開發人調用核心标準接口。首先,解壓核心

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

解壓後的源碼如下:

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

想知道核心的組成結構可以參考它的頂層Makefile、.config檔案。

将核心打更新檔:

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

直接使用廠家的配置檔案

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

在Linxu終端執行make menuconfig

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

配置完成後執行make指令

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

這裡可能會遇到上面的問題,更改配置如下

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

不要選這項

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

3.4.2版本以上的核心不必更改此項。

再執行

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

等待核心編譯完成

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

核心映像檔案在這個檔案夾内

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

核心映像檔案uImage包括64位元組頭部(包含核心版本、加載位置、大小等資訊)和zImage(真正的核心 壓縮過的核心)。這裡的vmLinux是未壓縮的核心映像,為elf格式,用于kernel-debug,不能直接加載,不可以作為啟動核心。

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

編譯出uImage後用u-boot燒寫Kernel

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

注:如果沒有燒寫根檔案系統,啟動時會卡死在核心。

制作根檔案系統:

根檔案系統的任務是運作應用程式。使用busybox制作根檔案系統,busybox是一個開源的工具,下載下傳busybox源碼并解壓

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

安裝方法:用Vi編輯器打開INSTALL文檔

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

根據文檔提示,我們知道這個安裝步驟為紅圈圈中的三步。

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

執行指令配置busybox

基于JZ2440開發闆的第一個嵌入式Linux驅動程式
基于JZ2440開發闆的第一個嵌入式Linux驅動程式
基于JZ2440開發闆的第一個嵌入式Linux驅動程式

選中Tab代碼補全功能。

在make之前修改Makefile

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

加上交叉編譯腳本,不然會出錯。

編譯完成後千萬别直接make install

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

這樣會破壞掉主機系統。

應該這樣

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

加上紅圈裡的東西再安裝。安裝完成後我們去到安裝目錄

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

下面我們需要導入glib庫,庫中包含一些動态庫和靜态庫,我們隻需要動态庫,可以從制作交叉編譯工具檔案夾下複制過來到lib目錄

基于JZ2440開發闆的第一個嵌入式Linux驅動程式
基于JZ2440開發闆的第一個嵌入式Linux驅動程式
基于JZ2440開發闆的第一個嵌入式Linux驅動程式
基于JZ2440開發闆的第一個嵌入式Linux驅動程式
基于JZ2440開發闆的第一個嵌入式Linux驅動程式

上電自動挂接檔案系統,無需手動挂載。

燒寫根檔案系統到單闆,開始編寫驅動程式:

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

驅動的核心為該結構體,驅動的架構如下:

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

實作這兩個接口,open函數為初始化LED硬體接口用,write函數為LED具體操作

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

我們寫的内容需要告訴核心,那核心怎樣才知道有這個驅動呢?這就需要寫一個驅動注冊函數和解除安裝函數

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

僅僅這樣核心也不知道該驅動是否被加載,是以還需要一個宏來實作入口和出口:

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

最後再寫出測試函數就可以運作該驅動了

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

還要編寫Makefile(Linux編譯工具)

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

這裡注意選擇linux核心版本,由于用的是2.6.22.6核心的接口,是以換成其他版本的核心可能編譯不通過,會有錯誤。

再編譯測試程式,編譯測試程式時要用和根檔案系統下lib庫所用的版本一樣的交叉編譯器編譯,最後才會順利實作。

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

我這用的是3.4.5的,由于上次用了4.3.2的交叉編譯器,導緻最後運作失敗,搞了很久才弄出來,編譯後會産生這兩個檔案 把它們拷貝到根檔案目錄下

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

最後在單闆上裝載驅動!

基于JZ2440開發闆的第一個嵌入式Linux驅動程式
基于JZ2440開發闆的第一個嵌入式Linux驅動程式

這樣就可以測試了。

注:如何修改arm-linux-gcc 交叉編譯器版本

基于JZ2440開發闆的第一個嵌入式Linux驅動程式
基于JZ2440開發闆的第一個嵌入式Linux驅動程式

紅圈部分為交叉編譯器PATH,再執行

基于JZ2440開發闆的第一個嵌入式Linux驅動程式

繼續閱讀