1. 程式人生 > >《11.uboot的移植-從三星官方uboot開始移植》

《11.uboot的移植-從三星官方uboot開始移植》

《11.uboot的移植-從三星官方uboot開始移植》

第一部分、章節目錄
2.11.1.移植前的準備工作
2.11.2.ubuntu14.04上網及安裝openssh
2.11.3.移植初體驗
2.11.4.時鐘和DDR的配置移植
2.11.5.DDR地址另外配置
2.11.6.DDR地址另外配置2
2.11.7.inand驅動問題的解決
2.11.8.一些小問題的修補
2.11.9.網絡卡驅動移植1
2.11.10.網絡卡驅動移植2
2.11.11.網絡卡驅動如何工作
2.11.12.使用自己移植的uboot啟動核心

第二部分、章節介紹
2.11.1.移植前的準備工作
本節介紹uboot移植工作正式開始前的準備工作,主要是環境搭建和必備工具的使用。
2.11.2.ubuntu14.04上網及安裝openssh
本節詳細介紹ubuntu14.04的網路配置問題,然後安裝openssh-server,最後用sshsecureshell登入。
2.11.3.移植初體驗
本節開始進行uboot移植,先使用三星移植版本的uboot直接編譯燒寫執行,再根據結果去分析問題,逐步展開移植工作。
2.11.4.時鐘和DDR的配置移植
本節對配置檔案中的時鐘設定和DDR初始化資訊、DDR配置資訊做更改移植。
2.11.5.DDR地址另外配置
本節我們將對DDR進行另外配置,將DDR地址修改到30000000開始的區域。通過本次修改讓大家進一步熟悉uboot的移植。
2.11.6.DDR地址另外配置2
本節接上節來繼續解決DDR重新配置的問題,主要是發現問題定位問題並解決問題的思路引導和實踐。
2.11.7.inand驅動問題的解決
本節我們通過分析和思考來解決iNand初始化不成功的問題,通過本實驗讓大家進一步認識到uboot移植的實質。
2.11.8.一些小問題的修補
本節對一些小細節問題進行修補,包括網路相關的環境變數的預設值、修改控制檯使用的串列埠、修改行提示符等。
2.11.9.網絡卡驅動移植1
本節對uboot進行網絡卡驅動的移植,其實主要是網絡卡初始化函式的分析和更改。
2.11.10.網絡卡驅動移植2
本節進行網絡卡移植的程式碼實戰,讓大家看到網絡卡驅動移植前後的實驗現象的差別,明白移植並不是一件困難的事情。
2.11.11.網絡卡驅動如何工作
本節以ping命令為例講述uboot中的網絡卡驅動的工作原理,試圖讓大家對網絡卡晶片多一些瞭解,降低網路通訊的神祕感。
2.11.12.使用自己移植的uboot啟動核心
本節對uboot最一些更改和移植,使這個uboot可以用來啟動核心。

第三部分、隨堂記錄
2.11.1.移植前的準備工作
2.11.1.1、三星移植過的uboot原始碼準備
(1)三星對於S5PV210的官方開發板為SMDKV210,對應的移植過的uboot是:網盤/2.uboot和linux核心移植(努力更新中)\資源下載\三星官方為210移植過的uboot和kernel/android_uboot_smdkv210.tar.bz2
(2)這個原始碼網上是下載不到的,三星官方是不會把這些東西放在官網上下載的。這些東西都是隨著官方的開發板一起流出的。

2.11.1.2、SourceInsight準備
(1)移植的時候最重要的工作就是看程式碼、改程式碼然後編譯執行測試。
(2)編譯程式碼必須在linux中(windows共享資料夾中配置uboot不行的),那麼看程式碼和改程式碼可以在linux中(vim、gedit)也可以在windows中(Sourceinsight)。
(3)我一般習慣的方式是:在windows中解壓一份uboot原始碼,在linux中也解壓一份,注意這兩份程式碼原始情況是一模一樣的。然後移植的時候是在windows中這一份中去看程式碼、改程式碼;在linux中這一份去編譯燒寫。這種做法需要在windows中和linux中2份程式碼之間保持同步(直白點說就是windows中改過了後要把改過的原始碼複製到linux中那一份去覆蓋linux中那一份裡面的同目錄同文件)。
(4)問題來了,怎麼在windows中和linux中同步程式碼?通過共享資料夾在linux中進行復制(cp /mnt/hgfs/winshare/xxx.c ./);通過一些專用工具,譬如sshsecureshell。

2.11.1.3、便捷的檔案傳輸工具sshsecureshell
(0)windows中安裝sshsecureshell客戶端。
(1)虛擬機器上網。不同的ubuntu版本中網絡卡重啟的命令不同,在ubuntu10.04中網絡卡重啟使用:/etc/init.d/networking restart 或者 service network restart就可以;但是在ubuntu14.04中這兩個都不行了,要重啟網絡卡需要使用:ifdown eth0 然後ifup eth0即可。

2.11.2.ubuntu14.04上網及安裝openssh
2.11.2.1、ubuntu14.04上網問題
(1)虛擬機器上網有2種模式,NAT和橋接。
(2)虛擬機器上網配置要注意這幾個地方:第一個要注意選擇NAT還是橋接模式;第二個要注意ubuntu中網路配置檔案/etc/network/interfaces,這個檔案中是配置網絡卡資訊的(譬如靜態ip還是dhcp,靜態ip地址是多少等);第三個如果是橋接模式要注意橋接到哪個網絡卡上(一般筆記本都有2個網絡卡,一個是有線網絡卡一個是無線網絡卡),如果是NAT模式沒關係。
(3)ubuntu14.04中重啟網絡卡的命令變了。
(4)演示:NAT方式下上網配置過程。
前提是主機windows通過無線wifi上網了(或者windows通過有線上網也可以)。然後在虛擬機器中配置2點:第一選擇NAT方式,第二配置/etc/network/inerfaces檔案中使用dhcp方式;然後重啟網絡卡,確認ip地址得到後即可上網。
(5)演示:橋接方式上網配置過程。
前提是主機windows通過無線wifi上網了(主機通過有線網絡卡上網的配置方式有不同)。然後虛擬機器中配置注意三點:第一選擇橋接方式,第二配置橋接到無線網絡卡(如果主機windows是通過有線上網的,則橋接到有線網絡卡);第三配置/etc/network/inerfaces檔案中使用dhcp方式;然後重啟網絡卡,確認ip地址得到後即可上網。
(6)演示:虛擬機器要ping通開發板的配置過程。
前提是開發板和電腦之間通過網線連線好。然後虛擬機器中配置注意三點:第一選擇橋接方式,第二配置橋接到有線網絡卡(如果配置為自動或者配置橋接到無線網絡卡則肯定無法ping通開發板);第三配置/etc/network/inerfaces檔案中使用static方式,ip地址配置保證和主機windows、開發板三者處於同一網段;然後重啟網絡卡,確認ip地址得到後即可ping通開發板。
(7)windows系統中有一個bug,如果windows沒有檢測到有線網絡卡連線了外部網路則windows中本地連線是不工作的,網絡卡不工作。解決方案是用網線隨便連線一個有聯網能力的東西即可,譬如網線連線你的電腦到旁邊兄弟的電腦上,譬如插上你的開發板(開發板中運行了linux系統),譬如插上路由器埠。
2.11.2.2、搭建openssh環境
(1)安裝ssh-server。(sudo apt-get install openssh-server)如果報錯提示依賴錯誤,可以參考:

http://www.cnblogs.com/mliudong/p/4094519.html

(2)securecrt登入
(3)sshsecureshell登入
ssh登入不上,要修改/etc/ssh/sshd_config,參考:http://blog.sina.com.cn/s/blog_5f435c130102v6pv.html。 修改完重啟時如果/etc/init.d/ssh restart不起作用,可以使用:ps -e | grep ssh,看sshd的程序號,然後kill -9 程序號殺死ssh程序以達到重啟的目的,或者直接重啟ubuntu系統

2.11.3.移植初體驗
2.11.3.1、直接編譯三星移植版uboot嘗試執行
(1)複製到linux的源生目錄下,然後解壓開。
(2)檢查Makefile中的交叉編譯工具鏈
(3)配置時使用:make smdkv210single_config,對應include/configs/smdkv210single.h標頭檔案。
(4)配置完成後直接make編譯,編譯完成後就進入燒錄步驟。
(5)uboot/sd_fusing目錄下有sd_fusing.sh指令碼,用來燒錄。

2.11.3.2、程式碼分析&問題查詢
執行結果是:第一,串列埠無輸出;第二,開發板供電鎖存成功。
分析執行結果:uboot中串列埠最早的輸出在"OK",在lowlevel_init.S中初始化串列埠時打印出來的;串列埠無輸出"O"說明在列印"O"之前程式碼已經死掉了;開發板供電鎖存在lowlevel_init.S中,開發板供電鎖存成功說明這個程式碼之前的部分是沒問題的。兩個結合起來得到結論:錯誤在開發板供電鎖存程式碼和串列埠初始化列印"O"程式碼之間。

(1)Windows下建立SourceInsight工程
(2)順藤摸瓜去找可能出問題的地方
整個程式執行是從start.S開始的,看程式碼也從這裡開始。
實際上只要遮蔽掉bl PMIC_InitIp 這一行程式碼,然後重新編譯,整個uboot就啟動起來了。但是很多配置資訊是有問題的,很多功能應該也是不能用的,都要去一一查驗。

2.11.4.時鐘和DDR的配置移植
2.11.4.1、更改CONFIG_IDENT_STRING為" for ASTON210",然後同步到ubuntu中的一份程式碼,然後 make distclean; make smdkv210single_config,然後make,然後燒錄執行,檢查打印出來的banner資訊是否如我們改動的那樣。

2.11.4.2、確認時鐘部分的配置
(1)時鐘部分的執行結果本來就是對的,時鐘部分的程式碼在lowlevel_init.S中的bl system_clock_init呼叫的這個函式中。函式的程式碼部分是沒任何問題的,根本不需要改動,要改動的是暫存器寫入的值,這些值都在配置標頭檔案(smdkv210single.h)中用巨集定義定義出來了。如果時鐘部分要更改,關鍵是去更改標頭檔案中的巨集定義。
(2)三星移植時已經把210常用的各種時鐘配置全都計算好用巨集開關來控制了。只要開啟相應的巨集開關就能將系統配置為各種不同的頻率。

2.11.4.3、DDR配置資訊的更改
(1)從執行資訊以及bdinfo命令看到的結果,顯示DRAM bank0和1的size值都設定錯了。
(2)使用md和mw命令測試記憶體,發現20000000和40000000開頭的記憶體都是可以用的,說明程式碼中DDR初始化部分是正確的,只是size錯了。
(3)記憶體部分配置成:
#define CONFIG_NR_DRAM_BANKS 2 /* we have 2 bank of DRAM /
//#define SDRAM_BANK_SIZE 0x20000000 /
512 MB /
#define SDRAM_BANK_SIZE 0x10000000 /
256 MB */

#define PHYS_SDRAM_1 MEMORY_BASE_ADDRESS /* SDRAM Bank #1 /
#define PHYS_SDRAM_1_SIZE SDRAM_BANK_SIZE
//#define PHYS_SDRAM_2 (MEMORY_BASE_ADDRESS + SDRAM_BANK_SIZE) /
SDRAM Bank #2 */
#define PHYS_SDRAM_2 0x40000000
#define PHYS_SDRAM_2_SIZE SDRAM_BANK_SIZE

2.11.5.DDR地址另外配置
2.11.5.1、目標:將DDR埠0地址配置為30000000開頭
(1)更改有2個目的:第一是讓大家體驗記憶體配置的更改過程;第二是3開頭的地址和DRAM bank1上40000000開頭的地址就連起來了。這樣我們就得到了地址連續的512MB記憶體,而原來我們得到的512MB記憶體地址是斷續的。

2.11.5.2、DDR初始化引數更改
(1)根據裸機中講DDR初始化部分的課程,和uboot前面分析uboot中DDR初始化部分的程式碼的課程,得出結論就是:DDR的初始化程式碼部分是在lowlevel_init.S中寫的,是不動的。程式碼部分就是對相應暫存器做相應值的初始化;要動的是值,而uboot為了具有可移植性把值都巨集定義在include/configs/xxx.h中了。因此我們只需要去這個配置標頭檔案中更改配置值即可。
(2)更改內容是:#define DMC0_MEMCONFIG_0 0x20E01323改為:
#define DMC0_MEMCONFIG_0 0x30E01323 注意20改為30了。

2.11.5.3、smdkv210single.h中相關巨集定義修改
(1)暫存器的值改了後相當於是硬體配置部分做了更改。但是uboot中DDR相關的一些軟體配置值還沒更改,還在原來位置,所以要去更改。
(2)#define MEMORY_BASE_ADDRESS 0x20000000改為:
#define MEMORY_BASE_ADDRESS 0x30000000

2.11.5.4、虛擬地址對映表中相應修改
(1)uboot中開啟了MMU對記憶體進行了段式對映,有一張記憶體對映表。之前課程中分析過,分析方法是一樣的。
(2)經過實際分析,發現這個記憶體對映只是把20000000開始的256MB對映到C0000000開頭的256MB。我們更改方法是將2改成3.
(3)為了安全起見,再去配置標頭檔案smdkv210single.h中查一遍,看看有沒有其他的巨集定義值和記憶體配置有關聯的。

重新配置編譯,燒錄執行檢視結果。

2.11.6.DDR初始化引數更改2
2.11.6.1、修改DMC0的配置引數
(1)修改DDR中DMC0的memconfig_0暫存器的配置值,將
#define DMC0_MEMCONFIG_0 0x30E01323 改為:
#define DMC0_MEMCONFIG_0 0x30F01323
(2)然後重新同步、編譯燒寫執行,發現uboot第二階段運行了,但是整個uboot還是不成功。
(3)分析問題,尋找解決方案。分析方法有2種:第一種靠經驗、靠發現能力、靠直覺去找;第二種就是在整個程式碼中先基本定位錯誤地方,然後通過在原始碼中新增列印資訊來精確定位出錯的程式碼,然後找到精確的出錯位置後再去分析錯誤原因,從而找到解決方案。

2.11.6.2、修改修改虛擬地址到實體地址的對映函式
(1)修改uboot/board/samsung/smdkc110/smdkc110.c中的virt_to_phy_smdkc110,將其中的20000000改為30000000即可。
(2)同步程式碼,然後重新編譯燒錄執行。

2.11.6.3、總結:牽一髮而動全身

2.11.7.inand驅動問題的解決
2.11.7.1、先從現象出發定位問題
(1)解決問題的第一步,是定位問題。所謂定位問題就是找到原始碼當中導致這個問題的那一句或者那幾句程式碼。有時候解決這個問題需要修改的程式碼和直接導致這個問題的程式碼是不同的。我們這裡說的定位問題指的是定位到出問題的程式碼處,也就是運行了這一句程式碼時發生了這個錯誤。
(2)定位了問題之後,實際修改程式解決問題不一定改的是這一句程式碼。但是肯定和這一句程式碼有關聯,我們要通過自己分析來找到這種關聯,從而從定位的錯誤點找到真正需要修改的點,然後去修改他。
(3)實戰方法:從打印出來的錯誤休息中挑選一個關鍵詞,然後去原始碼中搜索這個關鍵字,通過這種搜尋的方法定位問題。通過搜尋將問題定位在drivers/mmc/mmc.c的818行。
(4)然後就是解決問題了。

2.11.7.2、網路搜尋解決方案
(1)初步的解決方案是自己先瀏覽一遍這個問題點周邊程式碼上下文。通過瀏覽程式碼上下文,發現這個函式是在讀取SD/iNand的ext_csd暫存器的值。通過瀏覽程式碼結合出錯地方,可以判斷出:從卡端讀取ext_csd暫存器是成功的,並且從讀取結果中拿到了卡的版本號資訊。然後程式碼對版本號進行了判斷,並且如果版本號大於5就會報錯並且函式錯誤退出。這就是問題所正。
(2)問題就是:我們使用的iNand卡的版本號大於5,而uboot程式碼本身不處理版本號大於5的卡,因此出錯了。
(3)怎麼解決?第一可能,換卡;第二可能,軟體修復。
(4)網路搜尋錯誤關鍵字,然後逐個去查閱,看看哪個可以給我們提供解決問題的思路和方法。http://blog.csdn.net/wang_shuai_ww/article/details/22308853

2.11.7.3、嘗試修改程式碼解決問題
(1)解決方法就是修改uboot中的程式碼,把判斷的5改成更大的數字。譬如8,然後跳過這個錯誤。

2.11.7.4、推測和實驗驗證(SD卡和iNand的區別)
(1)當前板子上有一個iNand接在SD0上,有一個外接SD卡接在SD2上。那uboot中初始化的這個是iNand而不是SD卡。也就是說uboot中實際用的是SD0而不是SD2.
(2)大家可以嘗試,使用外接SD卡時,這個版本號的問題不會出現。從這裡可以推測出SD卡和iNand的區別,至少從一個角度可以看出:SD卡版本低,iNand的版本比較高。

2.11.8.一些小問題的修補
2.11.8.1、控制檯串列埠更換為串列埠0
(1)uboot中預設使用串列埠2來做控制檯輸入輸出的。
(2)SOC中一共有4個串列埠(串列埠0、1、2、3),開發板X210上用DB9介面引出了2個串列埠,分別是串列埠2和串列埠0.(靠邊的是串列埠2,靠裡那個是串列埠0)。
(3)三星公司推薦使用串列埠2來作為除錯串列埠,所以在三星移植的uboot和核心版本中都是以串列埠2預設為控制檯串列埠的。
(4)有時候專案需要將除錯串列埠修改為另外的串列埠(譬如串列埠0),這時候需要修改uboot的程式碼,做移植讓uboot工作在串列埠0的控制檯下。
(5)uboot中真正去硬體初始化串列埠控制器的程式碼在lowlevel_init.S中的uart_asm_init中,其中初始化串列埠的暫存器用ELFIN_UART_CONSOLE_BASE巨集作為串列埠n的暫存器的基地址,結合偏移量對暫存器進行定址初始化。所以uart_asm_init中到底初始化的是串列埠幾(從0到3)?取決於ELFIN_UART_CONSOLE_BASE巨集。這個巨集的值又由CONFIG_SERIALn(n是從1到4)來決定
(6)同步程式碼、編譯燒錄執行,發現串列埠線插在串列埠2上,crt上只打印:SD checksum error.(這個是內部iROM打印出來的,內部iNand校驗失敗的資訊);然後將串列埠線改插到串列埠0上,啟動,所有的資訊出現。實驗成功。

2.11.8.2、修改預設網路地址設定
(1)修改配置標頭檔案smdkv210single.h中的CONFIG_IPADDR等巨集,則可以修改uboot的預設環境變數。
(2)更改完成後如果環境變數還是原來的,正常。因為原來uboot執行過saveenv,因此環境變數已經被儲存到iNand中的ENV分割槽中去了。uboot啟動後校驗時iNand的ENV分割槽中的環境變數是正確的,因此會優先載入。我們在uboot原始碼中修改的只是預設的環境變數。解決方案是擦除掉iNand中的那一份環境變數,然後迫使uboot啟動時使用uboot程式碼中自帶的預設的這一份環境變數,就可以看到了。
(3)可以使用mmc write 0 30000000 11# 32(表示將DDR的0x30000000開頭的一段記憶體中的內容寫入iNand中的第17個扇區開始的32個扇區內,寫入長度是32個扇區長度(16KB))

2.11.8.3、修改行提示符
(1)#define CFG_PROMPT "ASTON210 # "

2.11.8.4、總結
(1)結論就是對uboot的整體結構和過程瞭解之後,移植非常簡單。

2.11.9.網絡卡驅動移植1
2.11.9.1、網絡卡晶片與開發板的連線方式
(1)SoC的SROM bank和網絡卡晶片的CS引腳(SROM就是SRAM/ROM)。SoC的SROMController其實就是SoC提供的對外匯流排式連線SRAM/ROM的介面。如果SoC要外部外接一些SRAM/ROM類的儲存晶片(或者偽裝成SROM介面的晶片,譬如網絡卡晶片)就要通過SROM Controller來連線。網絡卡接在SROM中好處就是網絡卡晶片好像一個儲存晶片一樣被擴充套件在SoC的一個地址空間中,主機SoC可以直接用一個地址來訪問網絡卡晶片內部暫存器。
(2)網絡卡晶片內部暫存器使用相對地址訪問。網絡卡晶片內部很多暫存器有一個地址,這個地址是從00開始的,但是實際上我們SoC不能用0地址去訪問這個網絡卡的晶片內部暫存器。SoC訪問網絡卡晶片00暫存器時的地址應該是:起始地址+00這裡的起始地址就是網絡卡晶片對應接在SROM bankn中的bankn對應的基地址。
(3)主機SoC上網,其實就是通過操控網絡卡晶片內部的暫存器、緩衝區等資源來上網的。也就是說其實SoC是通過網絡卡晶片來間接上網的。
(4)總結:實際上也是一種匯流排式連線方式。優勢是SoC內部不需要內建網絡卡控制器,所有的SFR全都在外部網絡卡晶片中,而且還可以通過地址直接訪問(IO與記憶體統一編址),不用像Nand/SD介面一樣使用時序來訪問。
(5)從邏輯上來看,網絡卡更像是串列埠,而不像是SD/Nand。

2.11.9.2、原理圖瀏覽
(1)210的SROM控制器允許8/16bit的介面,我們實際使用的是16位介面。
(2)網線有8根線,但是實際只有4根有效通訊線,另外4根都是GND,用來抗干擾的。4根通訊線中管傳送的有2根(Tx-和Tx+),管接收的有2根(Rx+和Rx-)。因為網線上傳輸的是差分訊號。
(3)網絡卡晶片有個CS引腳,(CS就是chip select,片選訊號,主機向CS傳送有效訊號則從機晶片工作,主機向CS傳送無效訊號則從機晶片不工作。),這個引腳要接主機SoC的片選訊號引腳,主機S5PV210的每一個SROM bank中有一個片選訊號CSn(n=0-5),從原理圖可以看出,我們X210上將DM9000的CS引腳接到了CSn1上,對應SROM bank1(推斷出DM9000的匯流排地址基地址是0x88000000)。
(4)DM9000的CMD引腳接到了S5PV210的ADDR2引腳上。DM9000為了減少晶片引腳數,資料線和地址線是複用的(DATA0到DATA15這16根線是有時候做資料線傳輸資料,有時候做地址線傳輸地址的。什麼時候做什麼用就由CMD引腳決定。)通過查詢資料手冊知道:當CMD為高電平時對應傳輸是DATA,當CMD為低電平時對應傳輸為INDEX(offset,暫存器地址)。

註明:這些引腳上的電平變化都是控制器自動的,不需要程式設計師手工干預。程式設計師所需要做的就是在配置暫存器值時充分考慮到硬體電路的接法,然後給相應暫存器配置正確的數值即可。

2.11.10.網絡卡驅動移植2
2.11.10.1、網絡卡驅動檔案介紹
(1)uboot中本來就提供了很多網絡卡晶片的驅動程式,在uboot/drivers/net/dm9000x.c和dm9000x.h。這個驅動來自於linux kernel原始碼。所以我們uboot中是移植而不是編寫。
(2)要想徹底看懂這個驅動,必須對linux的驅動模型中網路裝置驅動有一定的理解才可以。因為我們還沒學驅動,因此這個原始碼就不用看了。
(3)這個驅動是linux核心中做好的,根本不用動可以在uboot中直接使用的。而且因為linux驅動設計的很合理(資料和程式碼是分開的,這裡驅動主要是程式碼,資料是由硬體開發板中的接法決定的,資料由一定的資料結構來提供。),所以驅動本身具有可移植性。這個就決定了我們移植DM9000驅動時這個驅動檔案dm9000x.c和h不用動,要動的是資料。
2.11.10.2、網絡卡移植的關鍵:初始化
(1)uboot在第二階段init_sequences中進行了一系列的初始化,其中就有網絡卡晶片的初始化。這個初始化就是關鍵,在這裡的初始化中只要將網絡卡晶片正確的初始化了,則網絡卡晶片就能工作(意思是網絡卡驅動dm9000x.c和dm9000x.h依賴於這裡的初始化而工作)。
(2)網絡卡初始化程式碼地方在:
start_armboot
init_sequence
board_init
dm9000_pre_init 這個函式就是移植的關鍵
(3)dm9000_pre_init函式主要功能就是初始化DM9000網絡卡。這個初始化過程和我們開發板上DM9000網絡卡晶片的硬體連線方式有關。必須要結合開發板原理圖來分析,然後決定這個函式怎麼程式設計。
(4)原來的程式碼是三星的工程師根據三星的開發板SMDKV210的硬體接法來寫的程式,我們要根據自己的開發板的硬體接法去修改這個程式,讓網絡卡在我們的開發板上能工作。
(5)#define DM9000_16BIT_DATA這個巨集用來表示DM9000工作在16位匯流排模式下。根據上節課的硬體原理圖的分析,可以看到我們開發板上DM9000確實工作在16位模式下。
(6)從三星版本的程式碼中可以看出,它操作的是bit20-bit23,對照資料手冊中暫存器定義,可以看出三星的開發板DM9000是接在Bank5上的。而我們接在bank1上的,因此我們需要操作的bit位是bit4-bit7
(7)總結:三個暫存器的修改。主要是三星的開發板DM9000接在bank5,我們接在了bank1上,因此要做一些修改。

2.11.10.3、基地址的配置等
(1)之前說過,驅動分為2部分:程式碼和資料。程式碼不用動,資料要修改。
(2)CONFIG_DM9000_BASE是DM9000網絡卡通過SROM bank對映到SoC中地址空間中的地址。這個地址的值取決於硬體接到了哪個bank,這個bank的基地址是SoC自己定義好的。譬如我們這裡接到了bank1上,bank1的基地址是0x88000000.
(3)DM9000_IO表示訪問晶片IO的基地址,直接就是CONFIG_DM9000_BASE;DM9000_DATA表示我們訪問資料時的基地址,因為DM9000晶片的CMD引腳接到了ADDR2,因此這裡要+4(0b100,對應ADDR2)
(4)本來這樣配置就完了,重新編譯執行網絡卡就應該工作了。但是實際測試發現不工作,要怎麼樣修改呢?修改方式是將CONFIG_DM9000_BASE改成0x88000300就工作了。
問題?這個0x300從哪裡來的?我得出的感覺最靠譜的解釋是:跟DM9000網絡卡晶片型號版本有關,我認為這個0x300是DM9000網絡卡本身的問題,他本身的內部暫存器就有一個0x300的一個偏移量。

2.11.11.網絡卡驅動如何工作
2.11.11.1、網絡卡移植程式碼實踐
(1)經過實踐,網絡卡驅動移植成功。
(2)其實還可以做一些實驗。譬如說對網絡卡驅動初始化部分暫存器的設定,還有網絡卡CONFIG_DM9000_BASE也可以配成0x88000000再去試一試。

2.11.11.2、linux系統中網絡卡驅動的典型工作方式簡介
(1)在linux系統中,網絡卡算是一個裝置,這個裝置驅動工作後會生成一個裝置名叫ethn(n是0、1、2、····)(無線網絡卡名字一般叫wlan0、wlan1····)。然後linux系統用一些專用命令來操作網絡卡,譬如ifconfig命令。
(2)linux下的應用程式如何使用網絡卡驅動來進行網路通訊?最通用的方法就是socket介面。linux系統中有一系列的API和庫函式,提供了一個socket程式設計介面,linux下的應用程式都是通過socket來實現上網的,socket內部就是間接呼叫的網絡卡驅動實現網路通訊的。
(3)linux設計是非常完備的,應用層和驅動層是嚴格分離的。也就是說寫網路程式設計應用層的人根本不用管驅動,只要會用socket介面即可;寫底層驅動的人根本不用管應用層,只要面向linux的網路驅動框架模型即可。

2.11.11.3、uboot中網絡卡驅動的工作方式簡介
(1)一定要記住:uboot本身是一個裸機程式,是一個整體,沒有分層。所以uboot中根本沒有驅動和應用的概念。
(2)按照邏輯來說,ping這樣的命令實現的程式碼就是網路應用的應用程式,像dm9000x.c和dm9000x.h這樣的程式碼屬於驅動程式。所以在uboot中這些東西是揉在一起的,應用是直接呼叫驅動實現的。也就是說ping命令內部是直接呼叫了dm9000的網絡卡驅動中的函式來實現自己的。

2.11.11.4、以ping命令為例查詢程式碼驗證分析
(1)ping命令是uboot的眾多命令之一,ping命令實現的函式叫do_ping
(2)函式的呼叫關係:
do_ping
NetLoop
PingStart
PingSend
ArpRequest
eth_send(dm9000x.c中)
(3)驗證了2.11.11.3中說的uboot中應用程式(ping)呼叫驅動程式(dm9000x.c)的方式。這就是一種直接呼叫的方式。

注:lcd驅動與logo顯示,在2.13.uboot雜記-logo顯示和fastboot原理等中詳解

2.11.12.使用自己移植的uboot啟動核心
2.11.12.1、問題:當前uboot不能啟動核心
(1)用同樣的方法(使用tftp 0x30008000 zImage-qt; 然後bootm 0x30008000),分別使用我們自己移植的uboot和使用九鼎移植版本的uboot去啟動核心,發現九鼎移植版本的可以啟動,但是我們自己移植的不可以啟動。到此我們就斷定我們的uboot有問題,不能啟動核心。
(2)做基本檢查:首先懷疑是機器碼不對。經過和九鼎移植版本的uboot對比發現machid都是2456,說明機器碼沒錯。
(3)想到一個問題,我們之前做實驗時將串列埠改為了串列埠0,而核心zImage-qt的串列埠輸出在串列埠2.懷疑可能的問題是uboot使用了串列埠0而核心使用了串列埠2所以在uboot後看不到核心的啟動資訊。

2.11.12.2、解決第一步:將串列埠改回串列埠2
(1)在smdkv210single.h中修改串列埠編號即可。

2.11.12.3、根據現象分析,定位問題並試圖解決
(1)如果已經啟動了核心,那沒什麼好說的了。應該是可以直接啟動了。
(2)如何核心沒有啟動,是smdkv210single.h中沒有定義bootm傳參需要的那幾個巨集造成的。