這不是什麼新鮮東西,無線路由器很早前就開始使用了,不過最近才慢慢理解其原理。現在網路嵌入式裝置的功能越來越強大了,各晶片廠商的解決方案支援著這種複雜性。最近公司實習,做一個家庭網關的項目。下面的內容應該不算泄密吧,寫得隨意一點。
1.一個網路晶片架構
大家應該看得出來,這是一個DSL晶片。其網路部分由一個switch core構成核心,對外有3個交換口(粉紅色的):左側為乙太網路MAC,可外接乙太網路晶片MAC或PHY,稱為LAN端;右側為DSL的TPS子層,按照DSL標準傳輸ATM/PTM資料,成為WAN端;上面的是一個PDMA片級匯流排,與片上系統SoC通訊。
另外還有幾個額外的交換口,主要是提供額外功能的:一個QDMA用於擴充core外Mem;LTR和WTR是兩個轉換引擎,當LAN或WAN端的資料包需要一些特殊處理時(如VLAN、PPPOE頭等),會被分別交換到這兩個口進行轉換後,再發回Queue中。再另外,LAN、WAN端各有一個classifier,是預分類器,在資料包進入switch core前,先進行一個粗略的劃分,決定發往哪個連接埠。
以上的這些功能都市switch core獨立完成的,SoC系統只需對其進行簡單的配置、控制即可。所以SoC的新能並不需要太高(CPU大概是130MHz的)。注意,該switch core和一般乙太網路switch的區別,首先其連接埠類型就不同,所提供的功能也跟為複雜。
這裡給出一個簡單的乙太網路switch晶片的架構,如下圖所示,其核心就是一個register集,對它們進行配置(內部EEPROM、或外部MDIO匯流排),可以實現port-VLAN、二層filter等功能。其結構相對簡單,因為其所有連接埠都是乙太網路口。
用該晶片接在上述DSL晶片的LAN端,構成網路系統如下圖所示:
乙太網路switch可以自主實現port-VLAN功能,並通過一個trunk口與switch core相連。而switch core有很好的vlan_tag classifier功能。另外WAN端實現了8個硬體通道PVCs,且switch core也能對它進行很好的classifier。綜上,就可以實現所謂的port-mapping功能,只要一跟DSL接入線,就可在家庭裡實現IPTV、Internet、可視電話等業務的分離。
注意,所有這些功能都是switch core自動完成的,網路資料包不需要進入SoC的協議棧,這和後面講的一般的路由器是不同的。
2.嵌入式片上系統
2.1與外界的互動方式
這裡的SoC系統主要功能有:與外界使用者的互動,解析使用者指令,配置系統。
解析指令對軟體系統來說很簡單,配置系統,前面也說了,主要是讀寫一些register,也很簡單。關鍵就在於與外界使用者互動。
很容易想到的一種方式是網路,SoC也連在switch core上,有自己的IP、MAC。當然它和switch core是片上bus相連的,通訊時並不需要MAC,這裡只是把自己偽裝成一個通用的乙太網路裝置,可以被switch core和外界PC識別。
要通訊,當然就需要協議棧了,不過,這裡的SoC系統不需要處理額外(正常通訊)的資料,所以協議棧也選擇簡單的LWIP,如之前的博文所述。最常用的網路通訊方式就http了,另外還有telent等。
呵呵,串連192.168.1.1實際就是去串連其內部的SoC,一般的交換器、路由器都是這樣的,而不是什麼連接埠。當我還是一個超級菜鳥時,這個問題困擾了好久,糾結。
另外,嵌入式系統中,還有一個最常用的互動方式是串口UART。UART是一個非常簡單的I/O裝置,它通過直接讀寫管腳的電平訊號(串列的)來實現輸入輸出,沒有任何額外的中斷、控制等機制。雖然簡單,不能用以實現複雜、可靠的功能,但用作嵌入式系統的調試方法卻非常有效。
UART就像是嵌入式裝置的鍵盤/顯示器。它是一種非常簡單的硬體資源,在它之上可以構建通用的I/O裝置tty,在tty之上,就可以實現各種應用,如shell等。
硬體資源UART、虛擬層裝置tty都是系統的資源,在Uc/OS中,一般作為全域量,在其上的應用則通過task來完成。如XSHELL_TASK中,就是通過一個while(1)迴圈,不停地通過tty_get_line()讀取命令列。注意,該函數已經不是裸的硬體操作了,而是加上了一個上層操作,即識別/r/n來作為結束符,也是通過一個while(1)迴圈來作的。讀到電平為空白,則忽略,因為UART太簡單了,沒有中斷、緩衝機制等(沒有詳細區考究,只是粗略地瀏覽了一下代碼,好像是這樣的吧!)。
最後,外界使用者讀寫電平,當然不同用示波器了。呵呵,PC上裝個串口驅動,那麼PC的鍵盤/顯示器就為嵌入式板子所用啦。
2.2bootloader
這就像一個心結,你一天不理解它,就一天不能安心地開發嵌入式系統,儘管你可以把軟體寫得很出色。
傳統的PC機上電後,cpu核的指令指標(如cs:ip)會指向系統內某段固化的代碼,如BIOS,這些代碼被燒錄在rom儲存空間中,斷電也不會丟失。它們會調用我們開發的代碼(如作業系統軟體、或一些簡單的前背景程式)。
一個嵌入式怎麼啟動,其實大意和PC(所有這種代碼機器)差不多。當然不同廠商的晶片,也有各自的方式特點,以公司的這款晶片來說(注意,這裡說的是晶片上整合的SoC子系統),它有好幾種方式啟動。
首先,其晶片內整合了一個BootRom,它裡面的代碼(也就是二進位的門電路)是在晶片的一部分,即晶片生產出來就有的。晶片對外有個引腳(boot-mode_pin),把它接低,則晶片上電後的ip指向該BootRom,執行裡面的代碼。這些代碼很簡單,一般會實現BOOTP、tffp等功能,從網路上下載OS的核心到記憶體中來運行。這就是所謂的網路無盤系統的工作方式。
不過現在好像這種方式用的少了,儲存空間便宜啊。一般都會把boot-mode_pin拉高,這樣上電後ip指向外部flash。很容易想到flash和PC上的硬碟類似,是差不多,有點區別。PC上電後先執行BIOS,由BIOS裝載硬碟的bootloader扇區。而嵌入式系統一般不這麼麻煩,它直接就在flash中運行這些代碼。
現在的cpu-core一般都是32位的,即有4G物理定址空間,而嵌入式的SDRAM並不要那麼大,所有可以把外部flash和SDRAM一起編址:
系統上電後,ip指向2G處,則可以直接在flash運行初始的代碼,只是速率比較慢,所以開始的代碼往往是把後面的一個image下載到SDRAM中去,然後在SDRAM中運行。
至於flash的基址為什麼能是2G,這是由CPU的地址匯流排和flash的SPI匯流排的特殊的電路串連方式決定的,呵呵,電子出身的應該不難理解。而且,有些晶片還提高一些外部引腳pin,來為地址線加上一個offset(比如1M),那麼兩個處理晶片就可以使用同一個flash的不同的部分了(0~1M,1~2M),而其內部只覺得都是從2G地址開始的。
下面一個關鍵問題就是,flash中是什麼,怎麼來的,能改變嗎?
一般flash中的東西,是有具體應用來決定的,開頭一般都是bootloader代碼,後面有一個image檔案,公司的網路系統,需要一個啟動設定檔,也簡單的放在flash中:
Bootloaer一般放在開頭,便於執行。後面的則也可以直接這樣按照物理空間分配,複雜一點,也可以做成檔案系統fs,如嵌入式linux。主要包括一些設定檔,log資訊檔。最重要的是IMAGE檔案,一般要被載入到SDRAM中去運行,這也是我們開發系統功能應用的關鍵。
那這些內容怎麼來的呢?一般初始時,會用特定的硬體工具廠商提供的一個初始的檔案(格式就是上圖所示)燒到flash中,就像當年我們燒8051單片機一樣,再把flash焊在板子上。如果運行過程中,代碼被改死了,系統再也起不來了,那對不起,只能重新焊一個新的flash了。而一個不就的方法是在flash中準備兩個image,板子上預留一個特殊的案例,按下後啟動新的image(前面講的flash-offset方法)。還有一種方法,是通過內部bootrom啟動,無盤啟動。實現當然需要一定的硬體支援,如前面所述的那個boot-mode_pin不能焊死,用一個跳冒,或者通過一些特殊電路接在乙太網路上,乙太網路事先有資料轉送時,則使用內啟動,如組播升級。方法各不一啦。
最後,flash裡面的內容怎麼變?很簡單,它既然也在cpu的變址內,直接用cpu把資料寫到flash中不就行了。一般用http服務,client會post一個image檔案上來,server端檢查沒問題,就寫到flash中,這就是手動升級。
3.一個無線路由器的架構分析
前面提到的公司晶片解決方案,SoC子系統的功能很有限,通訊資料包一般不會到SoC的協議棧。而目前市場上的無線路由器系統,系統中的CPU功能一般很強大,RAM配置也很強大,一般都能運行大型系統軟體,如Linux。
這是一塊單獨的晶片,而其幾乎包含了一個完整的PC機主板上的所有內容,CPU的功能還是很強勁了,670MHz的MIPS核,通過橋片串連資料匯流排。這裡的sys_bus差不多相當於PC中的PCI匯流排,諸如USB控制器等都掛在其下。這裡主要看一下網路裝置,主要有兩個,一個802.11n標準的WLAN收發器,一個4FE+2GE的乙太網路交換器。
和之前介紹的DSL晶片不同,他的兩個網路介面都是接在系統匯流排上,而沒有通過一個switch-core互動。因此,CPU內必須維護一個功能完整的協議棧,而且SWC往往也被虛擬化為wan和lan口,參見下面的結構圖:
首先,先明確一個概念,在統計網路裝置的連接埠數,不要忘了還有一個連接埠串連CPU的。比如,SWC對外有4FE+2GE,而實際上它還有第七個連接埠串連到CPU。然後就能理解有些資料轉送只在這些只能得網路裝置中完成了,而有些則需要進入CPU的協議棧。更準確的概念應該是,片內CPU系統也相當於一個PC,共同接在交換裝置上。
這裡比較特殊的是這個SWC裝置,照理它的所有連接埠應該是等價的,所處網段也相同,但通過VLAN技術,把3、4、CPU連接埠化為一個VLAN,而5、CPU化為另一個VLAN,這是SWC硬體支援的port-mapping,它能只允許同一個VLAN下的機器通訊。這裡就有一個特殊的CPU連接埠,它同屬於兩個VLAN,稱為trunk,SWC硬體在trunk口下收發資料時,必須帶有vlan_tag(802.1q)。在CPU系統內,因為物理通路只有一個,只能通過軟體的方式來實現VLAN的劃分(如Linux下的VLAN)。另外,一般把wlan掛在LAN內,所以在Linux中可以用一個虛擬Bridge裝置來串連這兩個裝置。下面來看幾種資料交換的途徑:
3、4間通訊,在PC機發起的ARP協議階段,SWC也學習並記錄了MAC表,SWC可以直接交換。
1、2間通訊,也像ethernet交換器那樣,直接在wlan裝置中交換嗎?沒研究過wlan協議啊,姑且這樣認為吧。
3、1間通訊,是同一網段的,DMAC為PC1的MAC地址,在SWC中會將它從CPU連接埠發出去,當然會加上lan_vlan-tag,因此會被netdev_eth裝置接收到,而該裝置已經變成了bridge裝置的一個連接埠,因此bridge裝置會接管該pkt,並根據MAC表,從netdev_wlan裝置(已經是連接埠啦)發出,wlan裝置受到pkt後,根據802.11n協議,發給對應的PC。
5和其它通訊,不管是3、4還是1、2,都是不同網段,因此在PC的路由系統中,會將資料發往gw-IP2,即pkt的DMAC為片上CPU的MAC,那麼在SWC中會將pkt從CPU連接埠發出去,當然會打上wan_vlan-tag,因此會被netdev_eth-vlan裝置接收,並進入片上CPU系統的協議棧(注意,之前的3種情況都不會進的)。此時片上CPU系統就充當了路由功能,選擇bridge裝置下發,bridge裝置中根據MAC選擇對應連接埠下發。
其它向5通訊,和上面一樣,只是方向反過來。
片上CPU系統自身也有MAC、IP(192.168.1.1),外部PC發送資料,通過wlan、swc裝置到達CPU系統的interface,interface發現是發給自己的,則會傳遞給上層協議棧。
當然這裡只是最基本的情況,現在的路由器裝置已經整合了非常多的功能,如DHCP、NAT、DNS等等。