福建星海通信科技有限公司 吳利生
近些年,伴隨著科學技術的不斷發展,計算機信息技術以及網絡通信技術得到了前所未有的發展,Linux嵌入式系統因其源碼開放、軟件豐富、內核高效穩定,已經在各個領域內得到了大量應用。同時,國內的芯片設計技術也在不斷發展追趕中,華為海思、全志、瑞芯微等芯片設計企業推出了很多優秀的芯片。在本文中,筆者將會基于全志的A40i平臺對Linux系統內核做出簡單分析,對Linux嵌入式系統驅動移植的各類場景做出初步的分析與探討,借此希望可以有效推動Linux內核的嵌入式系統驅動的提升與發展。
對比各類系統內核,Linux內核有著較為明顯的優勢,其穩定性很強,且易于實施定制方案。Linux內核在網絡通信與文件的模式與運行機制方面,有著自己完善而又健全的整套機制,并以此確立了其在計算機應用軟件領域的穩固地位。Linux內核的發展速度非常快,幾乎兩三個月都會出一個新版本,功能也在不斷豐富和完善。在Linux內核中,驅動代碼占據了整個內核代碼的絕大部分,如何快速高效的實現在指定的硬件平臺的移植是本文需要探討的課題。
在計算機領域中,計算機各個硬件之間的運行以及各個軟件的管理與控制,均由操作系統來完成。操作系統為計算機規定了完善的運行流程與模式,并且其開放兼容的系統環境,讓每一個人都可以利用計算機資源與信息實現更多的有效行為。Linux系統在互聯網領域有著絕對重要的地位,其完全開放的環境,使之不斷進行著自我完善,其優勢也在這一進程中進一步凸顯,對各類信息化平臺的有效支持,以及高效穩定的運行體系,更是讓眾多從業人員青睞。Linux不是為了某一硬件而設計的操作系統,它可以廣泛支持許多不同體系結構的硬件。如果想把一個Linux內核從一個硬件平臺上移植到另外一個硬件平臺,整個過程需要進行改動的內容極為繁雜。針對這一問題,相關人員需要對Linux內核驅動架構要有很深的了解,理解驅動軟件分層設計思想,移植過程中只修改操作硬件的部分,而不用去管其他層級的結構,這樣可以有效減小移植的工作量,也方便了移植后的調試工作,最終使得該移植后的系統能夠高效穩定的運行。
Linux操作系統的特性之一就是它的網絡協議棧,而且網絡體系結構很完整。接下來,我會以A40i平臺的網絡體系中的PHY驅動移植為例來分析Linux驅動移植的基本流程。由于A40i的CPU本身支持MAC功能,且在廠商提供BSP包中已有源碼支持。這里我們只是更換PHY芯片,而且該PHY芯片物理接口的MII接口是統一的,中斷接口也采用板子預先定義的中斷IO口。所以,設備樹文件sun8iw11p1.dtsi中有關EMac的配置可以不用修改,我只需要對PHY驅動進行開發(我們以xx83848來命名該國產PHY芯片,且該PHY芯片對應的驅動代碼也用xx83848相關的名稱去定義函數及結構體)。PHY芯片驅動的開發總體上大致有三個工作需要做:(1)編寫PHY芯片的驅動程序;(2)修改設備樹文件;(3)加入內核及編譯。
設備驅動程序是實現文件系統與硬件交互的有效橋梁,它自身是文件系統結構中的一個模塊,在與硬件交互的同時,又可以與內核進行相關管理。
2.1.1 驅動加載及初始化程序
在a40i的Linux內核源碼中,一部分的MAC驅動文件及PHY驅動文件的路徑分別為:

硬件上,我們只改動了PHY的硬件。所以,這里我們只分析PHY驅動文件。通過入口函數module_init(xx83848_init)來引導對該驅動的注冊操作,然后xx83848_init函數會把PHY驅動的注冊上去。說到這里,可能有人會問,既然驅動已經注冊上去了,那要什么時候才會加載這個驅動呢?下面的函數就至關重要了。

上面的xx83848_init(void)函數是該網卡驅動的初始化入口,在驅動初始化的時候就把xx83848_driver[]結構體進行初始化配置。上面的MODULE_DEVICE_TABLE(mdio, xx83848_tbl)函數的作用是把該PHY設備ID注冊入類型為MDIO的設備表中,系統內核啟動運行的過程中會加載MDIO設備驅動,而該MDIO設備驅動會搜索與該設備ID(即xx83848_PHY_ID)相匹配的設備驅動,匹配成功后,就動態加載該設備的PHY驅動。
2.1.2 設備的接口
Linux字符設備驅動一般是使用file_operations類似的結構訪問驅動程序的函數來完成工作,這個結構的每個成員的名字都對應著一個調用。用戶進程對設備文件進行讀寫操作的時候,系統調用通過設備文件的主設備號找到相應的設備驅動程序,然后,調用這個數據結構相應的函數指針,接著,執行該函數指針指向的驅動函數。但是,需要注意的是,在調用register_netdev之前,初始化工作必須完成。對于不同類型的設備,Linux內核提供的設備接口的結構體會有很大的差異。如,PHY設備驅動的接口結構體是struct phy_driver。其具體的結構體接口如下:

上面的函數指針需要填充相應的功能函數,這些功能函數需要開發人員自己去開發實現,各個功能實現函數最終都掛到核心層提供的統一的函數指針上。這種分層的網絡驅動軟件架構,完美的實現了MAC層和PHY層的分離,然后,通過核心層將MAC層和PHY層聯系在一起。驅動這么分層模式的設計的好處是,PHY層的驅動不用去考慮MAC層的控制方式,而MAC層的驅動也不用去關心PHY層驅動的具體實現。在Linux內核中,無數的設備驅動都采用了類似的分層的思想。
設備樹是一種描述硬件的數據結構,許多板級的硬件細節存在設備樹文件中。Linux在啟動過程中,加載并解析設備樹文件,然后,把解析出來的設備資源信息傳遞給內核,內核會將這些資源綁定給相應的設備。而這里,我們需要做的是修改設備樹文件中的MAC管腳配置。但是,A40i的硬件資源配置文件不僅有DTS設備樹文件,還多了Fex配置文件,這里假設我們設置的屏幕分辨率是800x600。它們在開發工程中的路徑都是固定的,分別為:

一般來說,外部設備的型號或類型發生了改變,相應的外設驅動對應的設備樹文件也需要做相應的修改。下面,我截取一些A40i的GMac的設備樹的一部分配置信息。

從上面的EMac的設備樹中,我們可以看到有兼容屬性、內存地址和大小、管腳分配定義、中斷地址、時鐘控制器等信息。設備樹的源文件為.dts,編譯后的文件為.dtb文件。Linux內核在展開設備樹的過程中會創建并注冊相關的設備。a40i的設備樹文件除了.dts文件,還有.fex文件,該Fex文件絕大部分內容是對IO管腳的功能進行定義,而整個工程中,最終芯片IO功能就以這里的定義為準。這里,我截取了sys_config800x600.fex配置文件中一部分有關網卡驅動的內容。

從上面的.fex配置文件中,我們可以看到芯片的IO管腳大部分都可以復用,這里把PH0~PH27的多數管腳用于網卡相關功能,上面IO口的定義規則為:Port:<端口+組內序號>、<功能分配>、 <內部電阻狀態> 、<驅動能力> 、<輸出電平狀態>。如果需要基于該平臺對IO口的功能進行修改,就需要在遵照該規則的前提下操作。
在前面的相關驅動都開發完成之后,接下來的工作就是把驅動加入內核中編譯。對此,在Linux上有一套標準的操作:(1)修改該驅動.c文件所在目錄下的Kconfig及Makefile文件;(2)在工程的Linux源碼根目錄下,運行make ARCH=arm menuconfig,在菜單中找到該驅動的配置項,選中配置,然后保存。最終該配置信息會保存在內核工程目錄下的.config文件中;(3)在A40i工程中,編譯該內核的方法也比較簡單,只要在Lichee目錄下,運行./build.sh-m kernel指令即可實現對Linux內核的編譯。
縱觀整個Linux內核驅動開發,你會發現開發的難點在于芯片驅動程序的開發和驅動程序的調試,該工作的工作量占了整個內核驅動移植的四分之三。雖然Linux的整個驅動移植過程比較復雜,但是因為其開源的特點,使得很多驅動開發有類似的驅動可供參考借鑒。而且,在掌握理解了Linux各個驅動子系統的設計思想后,驅動開發工作完全可以事半功倍。
Linux系統的廣泛應用,讓人們的生活變得更為高效快捷,日常的工作方式與各類行為方式也變得更為智能。近些年,伴隨著Linux核心技術的迅速發展,并在大量從業人員的努力下,Linux內核驅動的移植兼容性得到了極大的提高,整體技術愈發成熟,相關的設計理念以及移植方式更為先進。在可預見的未來,Linux內核必然會隨著互聯網與物聯網的不斷推進而迅速強大。
隨著嵌入式技術的不斷發展與相關應用技術的逐漸成熟,采用Linux內核的各類設備也將不斷被人們所熟知,其未來的發展前景也會迅猛擴張,而從事嵌入式Linux開發與研究也將會有更多的發展前景。