嵌入式Linux網路驅動程式的開發及實現原理

2021-07-23 16:57:29 字數 4075 閱讀 3598



0 引言

隨著人們對開放源**軟體熱情的日益增高,linux作為乙個功能強大而穩定的開源作業系統,越來越受到成千上萬的計算機專家和愛好者的青睞。在嵌入式領域,通過對linux進行小型化裁剪後,使其能夠固化在容量只有幾十兆位元組的儲存器晶元或微控制器中,成為應用於特定場合的嵌入式linux系統。linux強大的網路支援功能實現了對包括tcp/ip在內的多種協議的支援,滿足了面向21世紀的嵌入式系統應用聯網的需求。因此,在嵌入式系統開發除錯時,網路介面幾乎成為不可或缺的模組。

1 嵌入式linux網路驅動程式介紹

linux網路驅動程式作為linux網路子系統的一部分,位於tcp/ip網路體系結構的網路介面層,主要實現上層協議棧與網路裝置的資料交換。linux的網路系統主要是基於bsd unix的套接字(socket)機制,網路裝置與字元裝置和塊裝置不同,沒有對應地對映到檔案系統中的裝置節點。

通常,linux驅動程式有兩種載入方式:一種是靜態地編譯進核心,核心啟動時自動載入;另一種是編寫為核心模組,使用insmod命令將模組動態載入到正在執行的核心,不需要時可用rmmod命令將模組解除安裝。linux 2.6核心引入了kbuild機制,將外部核心模組的編譯同核心原始碼樹的編譯統一起來,大大簡化了特定的引數和巨集的設定。這樣將編寫好的驅動模組加入核心原始碼樹,只需要修改相應目錄的kconfig檔案,把新的驅動加入核心的配置選單,然後需要修改相應子目錄中與模組編譯相關的kbuild makefile,即可使新的驅動在核心原始碼樹中被編譯。在嵌入式系統驅動開發時,常常將驅動程式編寫為核心模組,方便開發除錯。除錯完畢後,就可以將驅動模組編譯進核心,並重新編譯出支援特定物理裝置的linux核心。

2 嵌入式linux網路驅動程式的體系結構和實現原理

2.1 linux網路裝置驅動的體系結構

如圖1所示,linux網路驅動程式的體系結構可劃分為4個層次。linux核心源**中提供了網路裝置介面及以上層次的**,因此移植特定網路硬體的驅動程式的主要工作就是完成裝置驅動功能層的相應**,根據底層具體的硬體特性,定義網路裝置介面struct net_device型別的結構體變數,並實現其中相應的操作函式及中斷處理程式。

linux中所有的網路裝置都抽象為乙個統一的介面,即網路裝置介面,通過struct net_device型別的結構體變數表示網路裝置在核心中的運**況,這裡既包括回環(loopback)裝置,也包括硬體網路裝置介面。核心通過以dev_base為頭指標的裝置鍊錶來管理所有的網路裝置。

2.2 net_device 資料結構

struct net_device結構體是整個網路驅動結構的核心,其中定義了很多供網路協議介面層呼叫裝置的標準方法,該結構在2.6核心原始碼樹檔案中定義,下面只列出其中主要的成員。

2.2.1全域性資訊及底層硬體資訊

name:網路裝置名稱,預設是乙太網;

*next:指向全域性鍊錶下乙個裝置的指標,驅動程式中不修改;

mem_,rmem_:傳送和接收緩衝區的起始,結束位置;

base_addr,irq:網路裝置的i/o基位址,中斷號,ifconfig命令可顯示和修改;

hard_header_len:硬體頭的長度,乙太網中值為14;

mtu:最大傳輸單元,乙太網中值為1500b;

dev_addr[max_addr_len]:硬體(mac)位址長度及裝置硬體位址,乙太網位址長度是48bit,ether_setup會對其進行正確的設定;

2.2.2 主要的操作方法

int (*init)(struct net_device *dev); 裝置初始化和向系統註冊的函式,僅呼叫一次;

int (*open)(struct net_device *dev);裝置開啟介面函式,當用ifconfig啟用網路裝置時被呼叫,註冊所用的系統資源(i/o埠,irq,dma等)同時啟用硬體並增加使用計數;

int (*stop)(struct net_device *dev);執行open方法的反操作;

*hard_start_xmit;初始化資料報傳輸的函式;

*hard_header;該函式(在hard_start_xmit前被呼叫)根據先前檢索到的源和目標硬體位址建立硬體頭。    eth_header是乙太網型別介面的預設函式;

2.3網路驅動程式的編寫及實現原理

linux網路系統各個層次之間的資料傳送都是通過套接字緩衝區sk_buff完成的,sk_buff資料結構是各層協議資料處理的物件。sk_buff是驅動程式與網路之間交換資料的媒介,驅動程式向網路傳送資料時,必須從其中獲取資料源和資料長度;驅動程式從網路上接收到資料後也要將資料儲存到sk_buff中才能交給上層協議處理。

對於實際開發乙太網驅動程式,可以參照核心原始碼樹中的相應模板程式,重點理解網路驅動的實現原理和程式的結構框架,然後針對開發的特定硬體改寫**,實現相應的操作函式。下面結合作者利用linux2.6.18核心在深圳優龍公司的fs2410開發板(samsung s3c2410處理器)上移植編寫嵌入式cs8900a網絡卡驅動程式的例項,說明網路驅動程式的實現原理。

2.3.1網路裝置初始化

網路裝置的初始化是由net_device結構中的init函式實現的,核心載入網路驅動模組後,就會呼叫初始化過程。例項中初始化函式_init cs8900_probe中主要完成的工作:

a.呼叫核心中通用的設定乙太網介面的函式ether_setup();

b.填充net_device結構體變數dev中其它大部分成員;

c.呼叫check_mem_region()檢測i/o位址空間,然後呼叫request_mem_region()申請以dev->base_addr為起始位址的16個連續的 i/o位址空間;

d.通過cs8900_read()探測網絡卡cs8900a,讀取id資訊;

e.設定cs8900a的intrq0作為中斷訊號輸出引腳;

f.將mac位址寫入cs8900a的ia暫存器中;

g.通過register_netdev()將cs8900a註冊到linux全域性網路裝置鍊錶中;

2.3.2開啟(或關閉)網路裝置

系統響應ifconfig命令時,開啟(關閉)乙個網路介面。ifconfig命令開始會呼叫ioctl(siocsifaddr)來將位址賦予介面。響應siocsifaddr由核心來完成,與裝置無關。接著,ifconfig命令會呼叫ioctl(siocsifflags)設定dev->flag的iff_up位來開啟裝置,這個呼叫會使裝置的open方法得到呼叫。(當ifconfig呼叫ioctl(siocsifflags)清除dev->flag的iff_up位時,裝置的stop方法將被呼叫)

例項中利用cs8900_start()函式開啟網路裝置,主要完成的工作:

a.通過set_irq_type()向核心註冊網路裝置的中斷處理程式;

b.通過cs8900_set()設定cs8900a網絡卡中各控制暫存器和配置暫存器;

c.通過核心中netif_start_queue()函式開啟網路介面的資料傳輸佇列;

2.3.3網路資料報的傳送

資料報的傳送和接收是網路驅動程式中實現的兩個最重要的任務。當網路裝置被啟用時,net_device結構中的open方法被呼叫,它負責開啟裝置並呼叫net_device結構中的hard_header函式指標建立硬體幀頭資訊。最後通過函式dev_queue_xmit()來呼叫net_device結構中的hard_start_xmit方法把存放在sk_buff中的資料傳送到網路物理裝置。如果傳送成功,則在hard_start_xmit中釋放sk_buff並返回0;如果硬體裝置忙暫時無法處理,則返回1。網路硬體在傳送完資料報後會產生中斷,把dev->tbusy置0,通知系統可以再次傳送。

例項中,hard_start_xmit方法即為網路裝置資料傳送函式cs8900_send_start(),該函式實現把資料傳送到乙太網上,由網路協議介面層函式dev_queue_xmit()對其呼叫。cs8900_send_start()中主要完成的工作:

a.傳送資料前關閉中斷,中止網路裝置的資料傳輸佇列;

b.向cs8900a暫存器txcmd中寫入傳送資料命令控制字,向暫存器txlength中寫入待傳送資料幀長度;

c.通過cs8900_read()反覆讀取cs8900a匯流排狀態暫存器busst資訊,直到其已經準備好接收來自主機的資料;

d.呼叫cs8900_frame_write()將待發資料送入cs8900a的sk_buff中,硬體裝置會將資料幀傳送到乙太網上;

e.記錄資料幀的傳送時刻,開啟中斷,釋放sk_buff快取,函式返回0;

嵌入式linux的驅動程式

摘至嵌入式linux裝置驅動開發詳解 1.4 嵌入式linux驅動程式 1.4.1 嵌入式linux的核心空間和使用者空間 目前,各種處理器都能防止資源的未經授權訪問,包括嵌入式處理器。一般都是給cpu劃分不同的操作模式。不同的模式有不同的作用,某些操作不允許在低級別模式使用。核心態和使用者態是在硬...

linux 嵌入式驅動程式測試例項

include include include include include include include int main fd open dev fs o rdwr if fd 0 else printf open ok nwrite write fd,buf,strlen buf if n...

嵌入式linux之按鍵驅動程式

1.寫出框架 2.硬體操作 操作虛擬位址ioremap 1.重要函式 trap init init irq asm do irq中斷總入口 分辨中斷,處理中斷,清中斷。讀一下wait event interruptible 的原始碼,不難發現這個函式先將 當前程序的狀態設定成task interru...