Linux-uboot-學習筆記(10):移植三星官方uboot

Linux-uboot-學習筆記(10):移植三星官方uboot

前言:當我們在使用某個板卡之前,首先要找到與它對應匹配的uboot,將uboot移植到板卡上,從而實現板卡的一系列啓動。這裏我們將三星官方開發板的SMDKV210的uboot源代碼移植到S5PV210上,從而實現引到210啓動各種外設和啓動內核。

一、移植前的準備

當拿到源代碼時,首先要在window下利用SourceInsight創建一個工程,並將uboot源代碼加載到SI中,方便修改和查看函數調用。
項目->新項目->設置項目名、工程路徑->選擇整個uboot文件->添加樹 項目->同步文件(全打鉤)

接着要在linux下創建一份,因爲配置和編譯過程都需要在Linux下進行。將壓縮包通過winshare複製到linux下,並在/root/porting_x210/uboot_samsung/下解壓開,得到u-boot-samsung-dev。
在這裏插入圖片描述
這樣做的目的是爲了利用windows方便查找函數調用,並且方便修改。移植的時候是在windows中這一份中去看代碼、改代碼;在linux中這一份去編譯燒寫。這種做法需要在windows中和linux中2份代碼之間保持同步(直白點說就是windows中改過了後要把改過的源代碼複製到linux中那一份去覆蓋linux中那一份裏面的同目錄同文件)。

二、移植過程

1、關閉PMIC

問題描述: 第一,串口無輸出;第二,開發板供電鎖存成功。
問題分析: uboot中串口最早的輸出在"OK",在lowlevel_init.S中初始化串口時打印出來的;串口無輸出"O"說明在打印"O"之前代碼已經死掉了;開發板供電鎖存在lowlevel_init.S中,開發板供電鎖存成功說明這個代碼之前的部分是沒問題的。兩個結合起來得到結論:錯誤在開發板供電鎖存代碼和串口初始化打印"O"代碼之間。
在這裏插入圖片描述
解決方法: 將電源管理的宏關閉。
在這裏插入圖片描述
結果: 正常啓動。

2、確認時鐘設置

在這裏插入圖片描述
三星移植時已經把210常用的各種時鐘配置全都計算好用宏開關來控制了。只要打開相應的宏開關就能將系統配置爲各種不同的頻率。

3、修改DDR配置

問題描述: 從運行信息以及bdinfo命令看到的結果,顯示DRAM bank0和1的size值都設置錯了。並且內存地址不連續,bank0是20000000,bank1是40000000。

問題分析: 使用md和mw命令測試內存,發現20000000和40000000開頭的內存都是可以用的,說明代碼中DDR初始化部分是正確的,只是size錯了。而且DDR端口0的地址應該爲30000000開頭,這樣兩個bank0的地址就可以和bank1連接起來,從而得到地址連續的512MB內存。根據裸機中講DDR初始化部分的課程,和uboot前面分析uboot中DDR初始化部分的代碼的課程,得出結論就是:DDR的初始化代碼部分是在lowlevel_init.S中寫的,是不動的。代碼部分就是對相應寄存器做相應值的初始化;要動的是值,而uboot爲了具有可移植性把值都宏定義在include/configs/==smdkv210single.h中了。因此我們只需要去這個配置頭文件中更改配置值即可。

解決方法:

(1)修改DDR的大小。
在這裏插入圖片描述
(2)修改每片DDR的起始位置(涉及到虛擬地址映射問題)。
在這裏插入圖片描述
(3)附加:修改兩處打印信息:
在這裏插入圖片描述
(4)編寫配置編譯腳本,並燒錄。
在這裏插入圖片描述
結果:
在這裏插入圖片描述

4、inand驅動解決

問題描述: 從運行信息來看,SD卡驅動和iNand驅動設置有誤,SD卡打印出無法識別的版本信息,iNand打印出來0MB。
在這裏插入圖片描述

問題分析: 從打印出來的錯誤信息中挑選一個關鍵詞EXT_CSD,然後去源代碼中搜索這個關鍵字,通過這種搜索的方法定位問題。通過搜索將問題定位在drivers/mmc/mmc.c的818行。初步的解決方案是自己先瀏覽一遍這個問題點周邊代碼上下文。通過瀏覽代碼上下文,發現這個函數是在讀取SD/iNand的ext_csd寄存器的值。通過瀏覽代碼結合出錯地方,可以判斷出:從卡端讀取ext_csd寄存器是成功的,並且從讀取結果中拿到了卡的版本號信息。然後代碼對版本號進行了判斷,並且如果版本號大於5就會報錯並且函數錯誤退出。這就是問題所正。

解決方法: 修改uboot中的代碼,把判斷的5改成更大的數字。譬如8,然後跳過這個錯誤。
在這裏插入圖片描述
同時在cp.sh腳本中,將該文件所在位置添加進去。
在這裏插入圖片描述
結果: 卡初始化成功。我們這裏SD0接的是iNand,SD2接的是SD卡,因此這裏SD/MMC打印出來的是iNand的信息。
在這裏插入圖片描述

4、修改環境變量中的網絡IP地址

問題描述: 通過在uboot中print打印出環境變量來看,IP地址信息是正確的,我們需要先破壞掉原始環境變量,並通過uboot將新的環境變量自動加載上去。

問題分析: 爲什麼啓動後環境變量是對的?這是因爲原來通過save將正確的環境變量保存到iNand中的ENV分區去了,uboot啓動後校驗時iNand的ENV分區中的環境變量是正確的,因此會優先加載。我們在uboot源代碼中修改的只是默認的環境變量。解決方案是通過mmc write 0 30000000 11# 32(將DDR的0x30000000開頭的一段內存中的內容寫入iNand中的第17個扇區開始的32個扇區內,寫入長度是32個扇區長度(16KB))擦除掉iNand中的那一份環境變量,然後迫使uboot啓動時使用uboot代碼中自帶的默認的這一份環境變量,就可以看到了。

解決方法: 修改配置頭文件smdkv210single.h中的CONFIG_IPADDR等宏,則可以修改uboot的默認環境變量。
在這裏插入圖片描述
結果: print打印出了正確信息,即uboot提供了正確的環境變量。
在這裏插入圖片描述

5、網卡驅動移植

首先簡單介紹一下網卡驅動知識:

網卡芯片與開發板的連接方式
SoC的SROMController其實就是SoC提供的對外總線式連接SRAM/ROM的接口。如果SoC要外部外接一些SRAM/ROM類的存儲芯片(或者僞裝成SROM接口的芯片,譬如網卡芯片)就要通過SROM Controller來連接。網卡接在SROM中好處就是網卡芯片好像一個存儲芯片一樣被擴展在SoC的一個地址空間中,主機SoC可以直接用一個地址來訪問網卡芯片內部寄存器

網卡芯片內部寄存器使用相對地址訪問。網卡芯片內部很多寄存器有一個地址,這個地址是從00開始的,但是實際上我們SoC不能用0地址去訪問這個網卡的芯片內部寄存器。SoC訪問網卡芯片某個寄存器時的地址應該是:對應SROM bankn中的bankn對應的基地址+網卡寄存器相對於00的偏移量

主機SoC上網,其實就是通過操控網卡芯片內部的寄存器、緩衝區等資源來上網的。也就是說其實SoC是通過網卡芯片來間接上網的。實際上也是一種總線式連接方式。優勢是SoC內部不需要內置網卡控制器,所有的SFR全都在外部網卡芯片中,而且還可以通過地址直接訪問(IO與內存統一編址),不用像Nand/SD接口一樣使用時序來訪問。
在這裏插入圖片描述
210的SROM控制器允許8/16bit的接口,我們實際使用的是16位接口。
網線有8根線,但是實際只有4根有效通信線,另外4根都是GND,用來抗干擾的。4根通信線中管發送的有2根(Tx-和Tx+),管接收的有2根(Rx+和Rx-)。因爲網線上傳輸的是差分信號
網卡芯片有個CS引腳,(CS就是chip select,片選信號,主機向CS發送有效信號則從機芯片工作,主機向CS發送無效信號則從機芯片不工作。),這個引腳要接主機SoC的片選信號引腳,主機S5PV210的每一個SROM bank中有一個片選信號CSn(n=0-5),從原理圖可以看出,我們X210上將DM9000的CS引腳接到了CSn1上,對應SROM bank1(推斷出DM9000的總線地址基地址是0x88000000)。
DM9000的CMD引腳接到了S5PV210的ADDR2引腳上。DM9000爲了減少芯片引腳數,數據線和地址線是複用的(DATA0到DATA15這16根線是有時候做數據線傳輸數據,有時候做地址線傳輸地址的。什麼時候做什麼用就由CMD引腳決定。)通過查詢數據手冊知道:當CMD爲高電平時對應傳輸是DATA,當CMD爲低電平時對應傳輸爲INDEX(offset,寄存器地址)。

問題描述: 修改三星工程師對於三星開發板SMDKV210的uboot,使其能夠讓網卡在我們的開發板上工作。

問題分析: uboot在第二階段init_sequences中進行了一系列的初始化,其中就有網卡芯片的初始化。這個初始化就是關鍵,在這裏的初始化中只要將網卡芯片正確的初始化了,則網卡芯片就能工作(意思是網卡驅動dm9000x.c和dm9000x.h依賴於這裏的初始化而工作)。

解決方法: 找到對應初始化網卡部分,在dm9000_pre_init函數下,對應數據手冊來修改網卡的初始化參數。
#define DM9000_16BIT_DATA這個宏用來表示DM9000工作在16位總線模式下。根據上節課的硬件原理圖的分析,可以看到我們開發板上DM9000確實工作在16位模式下。
從三星版本的代碼中可以看出,它操作的是bit20-bit23,對照數據手冊中寄存器定義,可以看出三星的開發板DM9000是接在Bank5上的。而我們接在bank1上的,因此我們需要操作的bit位是bit4-bit7
在這裏插入圖片描述
CONFIG_DM9000_BASE是DM9000網卡通過SROM bank映射到SoC中地址空間中的地址。這個地址的值取決於硬件接到了哪個bank,這個bank的基地址是SoC自己定義好的。譬如我們這裏接到了bank1上,bank1的基地址是0x88000000.
DM9000_IO表示訪問芯片IO的基地址,直接就是CONFIG_DM9000_BASE;DM9000_DATA表示我們訪問數據時的基地址,因爲DM9000芯片的CMD引腳接到了ADDR2,因此這裏要+4(0b100,對應ADDR2)。
通過調試發現CONFIG_DM9000_BASE改成0x88000300就工作了。這個0x300從哪裏來的?我得出的感覺最靠譜的解釋是:跟DM9000網卡芯片型號版本有關,我認爲這個0x300是DM9000網卡本身的問題,他本身的內部寄存器就有一個0x300的一個偏移量。
在這裏插入圖片描述
結果: 通過ping虛擬機ubuntu和主機,發現都能ping通,證明網卡驅動工作正常。
在這裏插入圖片描述

補充:網卡驅動如何工作
在linux系統中,網卡算是一個設備,這個設備驅動工作後會生成一個設備名叫ethn(n是0、1、2、····)(無線網卡名字一般叫wlan0、wlan1····)。然後linux系統用一些專用命令來操作網卡,譬如ifconfig命令。
linux下的應用程序如何使用網卡驅動來進行網絡通信?最通用的方法就是socket接口。linux系統中有一系列的API和庫函數,提供了一個socket編程接口,linux下的應用程序都是通過socket來實現上網的,socket內部就是間接調用的網卡驅動實現網絡通信的。

linux設計是非常完備的,應用層和驅動層是嚴格分離的。也就是說寫網絡編程應用層的人根本不用管驅動,只要會用socket接口即可;寫底層驅動的人根本不用管應用層,只要面向linux的網絡驅動框架模型即可。
然而在uboot中沒有分層。按照邏輯來說,ping這樣的命令實現的代碼就是網絡應用的應用程序,像dm9000x.c和dm9000x.h這樣的代碼屬於驅動程序。所以在uboot中這些東西是揉在一起的,應用是直接調用驅動實現的。也就是說ping命令內部是直接調用了dm9000的網卡驅動中的函數來實現自己的。

6、啓動內核

問題描述: 將內核鏡像通過tftp加載到DDR的30008000位置(tftp 30008000 zImage-qt),而在啓動內核時(bootm 0x30008000),發現內核無法啓動。

問題分析: 做基本檢查:首先懷疑是機器碼不對。經過和九鼎移植版本的uboot對比發現machid都是2456,說明機器碼沒錯。如何內核沒有啓動,是smdkv210single.h中沒有定義bootm傳參需要的那幾個宏造成的。
在這裏插入圖片描述

解決方法: 查看.h文件中是否有那幾個宏。
結果: 成功啓動內核。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章