在基于Linux的AM335x軟件開發流程中,第一步就是U-Boot/SPL(SecondProgram Loader)的移植。在移植中遇到問題比較常見,而U-Boot/SPL的調試手段比較簡陋,不便于迅速找到問題。利用仿真器可以單步調試的特點,就可以迅速定位到出問題的代碼所在位置,加速移植的調試過程。本文主要介紹如何用CCS+emulator調試基于AM335x的U-Boot/SPL。
1. AM335x Linux啟動過程以及U-Boot/SPL調試代碼的準備
1.1 [url=]AM335x Linux[/url]的啟動過程
AM335x Linux的啟動主要包括ROM,SPL, U-Boot 和kernel四個啟動步驟:
A. ROM code
ROM code是固化在芯片內部的代碼,當上電時序正確,而且晶振等芯片啟動所需的條件都具備時,AM335x會從ROM code開始運行。
ROM code首先會讀取sys_boot引腳上的配置,以確定存放SPL的存儲器,或者可以獲取SPL的外設。
具體可以參考AM335x technical reference manual中的第26章 Initialization。
ROM code會從相應的地方讀取/獲取SPL,并運行SPL。
B. SPL
SPL 和U-Boot 是bootloader的兩個階段。這里分為兩個階段的原因是, ROM code中不會配置DDR,時鐘等最小系統,所以ROM code只能把bootloader加載到片上SRAM中,而片上SRAM對成本影響很大,所以通常很小,例如在AM335x上只有64K,不足夠放下整個U-Boot,所以將U-Boot分成兩部分,SPL和U-Boot。
SPL主要的職責就是初始化DDR,時鐘等最小系統,以讀取U-Boot,并加載到DDR中。具體來看,SPL 由ROM code加載到片上SRAM的起始位置,也就是0x402F0400。SPL會進一步對芯片進行配置,主要包括以下幾個方面以完成其主要職責:
a. 配置ARM core。 主要包括對中斷向量表,cache,MMU等的配置。
b. 配置時鐘系統,主要是PLL等。這個是配置各個功能模塊的基礎。
c. 配置UART,timer等。主要用于輸出必要的調試信息,或者提供些時鐘工具。
d. 配置I2C和PMIC。這個主要是為了配置電源管理芯片。
e. 配置DDR。
f. 配置 U-Boot所在的存儲器或者外設。
完成配置后,SPL會讀取U-Boot,并運行U-Boot。
C. U-Boot
U-Boot 主要的工作就是正確加載Kernel。和SPL類似,U-Boot也是要加載下一個階段的image,但是U-Boot提供了更多外設的支持和更多的調試工具。所以,U-Boot也要進行各個模塊的配置,上述SPL配置的部分, 除了DDR外,U-Boot也會根據需求重新配置(這里重置主要是U-Boot是一個開源工程,其要兼容某些特殊的芯片,從而需要做重載)。此外,U- Boot也會對網口,SD卡等根據需求進行配置。
U-Boot 和SPL的工作流程比有一點是有較大差異的,就是會對自身進行一次重載。這個在后面介紹U-Boot調試的時候,會有具體介紹。
完成配置后,U-Boot 會從相應的存儲器或者外設讀取Kernel,并傳遞參數給kernel,運行kernel。
D. Kernel
Kernel運行起來就代表Linux運行起來了,表明了啟動過程的結束。
1.2 U-Boot/SPL 調試代碼的準備
1.2.1下載U-Boot/SPL 代碼
U-Boot/SPL的代碼在一個包里面,通過編譯宏來分別編譯。目前TI U-Boot/SPL 代碼發布主要有兩個渠道,具體如下
A. 通過GIT開源的方式發布:
git://arago-project.org/git/projects/U-Boot-am33x.git
可以獲取最新的代碼,包含了最新的bug的修復。
B. 通過TI的官網的EZSDK發布:
http://software-dl.ti.com/dsps/dsps_public_sw/am_bu/sdk/AM335xSDK/latest/index_FDS.html
EZSDK是正式發布的軟件包,經過全面測試,性能穩定,U-Boot/SPL在board-support 目錄中。可以選擇EZSDK作為開發的基礎代碼。當有問題時, 可到GIT上查找最新的代碼是否有bug fix。
1.2.2 U-Boot/SPL的編譯
為了便于用CCS進行調試, 在編譯上需要注意兩點,其一,是要加入調試信息,就是為了加入symbol等信息;其二,去掉編譯器的性能優化編譯選項,這個主要是因為,優化后的代碼執行順序相對C代碼會有調整。
針對這兩點,在Uboot/SPL中,需要在config.mk中進行修改:
A. 在CFLAG 和 AFLAG中加入調試編譯選項,從而加入調試信息:
278ALL_AFLAGS = $(AFLAGS) $(AFLAGS_$(BCURDIR)/$(@F)) $(AFLAGS_$(BCURDIR)) –g
279ALL_CFLAGS = $(CFLAGS) $(CFLAGS_$(BCURDIR)/$(@F)) $(CFLAGS_$(BCURDIR)) –g
B. 去掉 CFLAG中的編譯選項, -O2(U-Boot中默認是-O2)
61 HOSTCFLAGS = -Wall -Wstrict-prototypes -O2-fomit-frame-pointer
編譯過程可以參考http://processors.wiki.ti.com/index.php/AM335x_U-Boot_User%27s_Guide
1.2.3 可執行文件
經過編譯后,就會生成可執行文件,也就是我們通常所說的image,這里會生成的image主要用AM335xLinux啟動的兩個階段,MLO(SPL)和U-Boot。
這里,SPL生成的image在am335/U-Boot-am33x/am335x/spl中,
A. am335/U-Boot-am33x/MLO 負責AM335x啟動的第一階段。
B. U-Boot-spl 作為帶有調試信息的image,可以在CCS中用作導入調試信息。
C. U-Boot-spl.bin 包含有調試信息,是調試時需要的image。
D. U-Boot-spl.map 這個文件里面存儲了spl的memory map信息,可以找到各函數入口的地址。
U-Boot生成的image在U-Boot-am33x/am335x中,具體如下:
A. U-Boot.img負責AM335x啟動的第二階段
B. U-Boot 包含有調試信息,屬于ELF格式,是調試時需要的image。
C. U-Boot.map這個文件里面存儲了U-Boot的memory map信息,可以找到各函數入口的地址
調試環境主要包含3個部分,仿真器,集成調試環境和開發板。下面將逐一介紹:
2.1 仿真器(emulator)
目前支持AM335x的仿真器的型號比較多,有XDS560v2,XDS510,XDS100v2, XDS100v3,等,比較常見的是XDS560v2和XDS100v2。
XDS560v2,性能好,速度快,具有trace功能,但是價格偏貴。 XDS100v2價格比較便宜。 其具備和XDS560v2一樣的基本調試功能,只是XDS100v2的速度相對略慢。
XDS560v2和XDS100v2在PC機上的驅動(Windows,Linux)都已經包含在CCS中了,所以安裝了最新版的CCS,就會安裝相應的驅動。
2.2 集成開發環境
TI有自己的集成開發環境(IDE)CCS.目前最新的版本是基于Eclipse IDE架構的,界面新穎方便。
下載地址 http://processors.wiki.ti.com/index.php/Download_CCS。
CCS有Windows版本和Linux 版本,后面會在介紹調試過程中具體介紹兩者的差異。
2.3 開發板
目前,針對不同的應用,TI發布了基于AM335x的多個開發板。其中BeagleBone,Starter Kit和ICE上配置了基于FT2232的xds100v2。而GPEVM和IDK上引出了CTI JTAG接口。
這里選擇GP EVM和 Spectrum DigitalXDS560v2 作為調試平臺。
3. CCS 調試Uboot/SPL的具體步驟
下面正式開始CCS的調試。調試的過程主要分為導入U-Boot/SPL 工程, CCS 連接AM335x,代碼調試等幾個部分。
3.1 導入CCS代碼
在CCS中, Menu File -》 Import … 選擇 Makefile 方式導入,如下圖所示:
在ezsdk中,U-Boot/SPL所對應的Makefile的具體路徑如下:
/home/sitara/ti-sdk-am335x-evm-05.05.00.00/board-support/U-Boot-2011.09-psp04.06.00.08
如前面所提到,U-Boot 和SPL的源碼在同一個文件夾的,通過不同的Makefile管理不同的編譯宏來區分的。這里導入的是U-Boot的代碼對應的Makefile,會相應的導入U-Boot對應的預編譯選項,因為其包含了所有的代碼。而對于SPL,也會相應的一起帶入,只是在CCS中看到的代碼的宏定義有些不對,但這個不影響調試。
3.2 CCS 連接 AM335x.
主要分成仿真器的連接,target連接和Debug配置等幾部分:
3.2.1 [url=]仿真器的連接[/url]
對于 AM335x GP EVM選用Spectrum DigitalXDS560v2 的20 pin的接口板,連在baseboard的J2口上即可,注意pin腳的順序,不要把JTAG 接口插反了。
對于beaglebone,StarterKit,ICE等,這些板子已經把XDS100v2 仿真器集成到板子上了,所以直接用usb線連到PC機上即可。
A. CCS的配置
CCS的配置主要包括Target的配置和連接兩部分。
a. Target 配置
Target的配置包含兩個部分,一個是仿真器(XDS560v2),另一個就是SOC(AM335x)。具體操作如下:
i. View -》 Target Configurations
ii. 點右鍵選擇New Target Configuration.
iii. 新建一個叫做AM335_EVM的target.
iv. Connection中選擇 Spectrum Digital XDS560V2 STM USB Emulator.
v. 對于XDS100v2 , 可以選擇 Texas InstrumentsXDS100v2 USB Emulator.
vi. 在Board or Device 中選擇AM335x.
vii. 點擊Save 保存。
viii. 點擊Test Connection 看是否能夠正常連接。
配置target成功后,會看到如下界面
3.2.2 Target 連接
A. 右鍵選中Target Configurations中已配置好的target,AM335x_EVM.ccxml, 在右鍵菜單中選擇Launch SelectedConfiguration,連接成功后,可以得到下圖
此時,PC 和仿真器以及仿真器和SOC的JTAG連接成功,但是ARM core還沒有連上。從圖中可以看到,有多個core的配置選項,由于U-Boot/SPL,Linux 運行在ARM coretex-A8 core上,這里只關注ARM core。
B. 在Debug窗口中,右鍵點擊CortxA8 core, 選擇Connect Target. 連接成功后,如下圖所示:
此時,已經成功連上AM335x的Cortex-A8 core了。
3.2.3 Debug配置
這里的debug配置,是對emulator連上core后行為的設置。 可以通過鼠標右鍵點擊properties,得到以下界面:
在該頁配置中,在調試過程需要調整的就是Auto RunOptions,可以根據需要設置,當加載了image后,core自動運行到指定的symbol,并且被JTAG接口所停住
調試U-Boot/SPL的方式有兩種,主要涉及如何加載image:一種是把image通過JTAG下載到片上RAM或者DDR中,然后導入 symbol,重置 PC指針到image的入口處,進行調試;另一種,把image燒到SD卡或者其他啟動存儲器上,啟動板子,通過JTAG停住core的PC指針,導入 symbol,重置 PC指針到image的入口處,進行調試。
下面會在具體步驟中說明這兩種方式如何操作:
A. 下載SPL image到AM335x中。
如果AM335x是從SD卡方式啟動,此時 SPL image已經被ROM code成功讀到片上 RAM中,就不需要加載 SPLimage了。
如果選擇SPL image通過CCS下載,鼠標左鍵選擇CortxA8core , 然后在CCS菜單中, Tools -》 Load Memory, 選擇編譯好的SPL image U-Boot-spl.bin,如下圖所示:
選擇加載的地址。由于加載的U-Boot-spl.bin是RAW data,所以需要指定loadaddress,這個地址就是SPL的入口地址
對于AM335x,SPL的入口地址是0x402F0400,對應的宏定義為CONFIG_SPL_TEXT_BASE, 該宏定義在include/configs/am335x_evm.h中。通過編譯出的map文件U-Boot-spl.map也可以查到,是 __startsymbol對應的地址。
設定加載image內型。 由于所有的代碼都是運行在ARM(32bit)模式下。所以Type-size也要設成32bit。設置界面如下:
最后點擊Finish,SPL就會被load到片上RAM中了。如果在console窗口中有錯誤信息,需要把SPL image重新加載 一遍。
B. 加載 symbol。
在上一步里,只是加載了RAW image,還沒有加載調試所需要的帶有調試信息的symbol。
可以通過Run -》 Load -》 LoadSymbols 加載symbol信息,界面如下:
這里選擇的是帶有symbol信息的U-Boot-spl.
C. 設置Cortex-A8 core到ARM狀態。
ARM core 啟動后,默認在Thumb(16bit)模式下,如前面所說,需要將其切換到ARM(32bit)下。具體做法是,View-》Registers, 展開CPSR寄存器,把T位設置為0。界面如下:
D. SPL的單步調試。
a. 從SPL編譯的memory map可知,SPL從0x402f0400開始執行,所以首先就要把寄存器PC的值設為0x402f0400。可以通過 View-》Registers中設置PC指針的值即可, 界面如下,將紅色框里面的改為0x402f0400即可。
b. 點擊Debug窗口(view-》debug)上tool bar中的匯編單步按鈕,如下圖所示,就開始調試了。
這時,在反匯編窗口(view-》disassembly)中,如下圖所示,看到的是匯編代碼,而且在編輯窗口這邊看不到源碼。這是由于開始執行的代碼在/arch/arm/cpu/armv7/start.s 中,反匯編和匯編一樣,所以沒有顯示源碼。
同時,可以看到PC指針運行到0x402f0458處。這里只是單步執行了一條指令,為什么跳過了這么大塊地址?這里的單步運行,指令地址空間跳轉了n指令,而不是一條指令,這是因為0x402f0400處存放的是異常中斷向量表,通過默認啟動的入口跳到reset symbol對應的地址了,也就是在0x402f0400處跳轉到0x402f0458了,具體代碼(arch/arm/cpu/armv7 /start.S)如下:
_start: b reset
reset:
bl save_boot_params
接下來,可以在C代碼中設置斷點,進行調試了。有兩點值得注意:
i. 如果編譯的時候,交叉編譯器的性能優化選項是開著的,那么優化后編譯生成的代碼,其執行循序和C源碼有差別,這時設置斷點時,其實際的位置不會很準。所以,這里可以根據需要,決定是否關閉-O2選項。
ii. 在CCS中,把core停下來時,CCS會根據image中調試信息所包含的源碼路徑,找到對應的源碼和symbol。由于U-Boot/SPL是在 Linux中編譯,所以其路徑都是Linux下的路徑,所以Linux版本的CCS可以直接找到對應的源碼,而對于Windows版本的CCS不能直接找到,需要通過手動找到源碼,但是找到一個文件的源碼后,CCS會根據相對路徑找到其他文件。除了這點外,Linux和Windows的CCS配置使用是一樣的。
3.4 U-Boot的調試
總體來說, U-Boot的調試過程和SPL調試過程是類似的,這里主要說明不同的幾點:
A. 從AM335x的啟動過程可知,U-Boot是運行在DDR中的,而DDR是由SPL來初始化的,所以,加載U-Boot前,先加載并運行SPL。
B. 加載U-Boot 的image是 U-Boot。 這里U-Boot 是ELF格式的, 其包含了加載地址, symbol等信息,所以使用CCS 菜單 Run-》 Load-》 LoadProgram, 加載U-Boot 即可。加載成功后, 如下圖所示:
如圖所示, PC直接指到0x80100000地址了,也就是U-Boot的起始地址(入口)了,該地址是CCS從頭ELF頭里面得到的,其定義在CONFIG_SYS_TEXT_BASE(include/configs/am335x_evm.h)中。
C. 相對 SPL 的調試, U-Boot有個地方不同,即有代碼的重載(code relocation), 重載后代碼的在SOC上的memory map和編譯出的memory map會有個偏移。這個過程是在函數relocate_code()中完成的。 relocate_code()函數是在board_init_f()中調用的,如果需要調試從調用該函數開始后面的代碼,則加上偏移重載symbol。
在CCS的菜單, Run-》 Load -》 Add Symbols, 加載的image還是前面的U-Boot, data/code offset 都是0x9FF88000。 這里的offset是從gd-》relocaddr(arch/arm arch/arm/lib/board.c)得到的。設置界面如下:
注意到上述幾點,然后就可以按照SPL的調試過程對U-Boot進行調試了。
4. 總結
關于用CCS+emulator對AM335x的U-Boot/SPL的調試就介紹完了。這里介紹的方法,包含了CCS+emulator調試的基本原則,不僅僅可以運用于U-Boot/SPL調試,也可以運用于Starterware,Kernel等調試。
評論
查看更多