基於AM335x的U-Boot/SPL 的CCS 調試

原文來自德儀中文在線,需要的直接去下原文吧


在基於Linux的AM335x軟件開發流程中,第一步就是U-Boot/SPL(Second Program Loader)的移植。在移植中遇到問題比較常見,而U-Boot/SPL的調試手段比較簡陋,不便於迅速找到問題。利用仿真器可以單步調試的特點,就可以迅速定位到出問題的代碼所在位置,加速移植的調試過程。本文主要介紹如何用CCS+emulator調試基於AM335x的U-Boot/SPL。

 

1.    AM335x  Linux啓動過程以及U-Boot/SPL調試代碼的準備

1.1 AM335x Linux的啓動過程

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的兩個階段。這裏分爲兩個階段的原因是, ROMcode中不會配置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中加入調試編譯選項,從而加入調試信息:

278 ALL_AFLAGS = $(AFLAGS)$(AFLAGS_$(BCURDIR)/$(@F)) $(AFLAGS_$(BCURDIR))–g

 

279 ALL_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主要用AM335x Linux啓動的兩個階段,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信息,可以找到各函數入口的地址

 

2.    調試環境的準備

調試環境主要包含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的多個開發板。其中BeagleBoneStarter KitICE上配置了基於FT2232的xds100v2。而GPEVMIDK上引出了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 仿真器的連接

     對於 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 TargetConfiguration.

       iii.       新建一個叫做AM335_EVM的target.

      iv.       Connection中選擇 Spectrum DigitalXDS560V2 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接口所停住

3.3 SPL的調試

     調試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中,就不需要加載 SPL image了。

如果選擇SPL image通過CCS下載,鼠標左鍵選擇CortxA8 core , 然後在CCS菜單中,Tools -> Load Memory, 選擇編譯好的SPL image U-Boot-spl.bin,如下圖所示:

      選擇加載的地址。由於加載的U-Boot-spl.bin 是RAW data,所以需要指定load address,這個地址就是SPL的入口地址

對於AM335x,SPL的入口地址是 0x402F0400,對應的宏定義爲CONFIG_SPL_TEXT_BASE, 該宏定義在include/configs/am335x_evm.h中。通過編譯出的map文件U-Boot-spl.map也可以查到,是__start symbol對應的地址。

     設定加載image內型。 由於所有的代碼都是運行在ARM(32bit)模式下。所以Type-size也要設成32bit。設置界面如下:

      最後點擊Finish,SPL就會被load到片上RAM中了。如果在console窗口中有錯誤信息,需要把SPL image重新加載 一遍。

 

     B.     加載 symbol。

在上一步裏,只是加載了RAW image,還沒有加載調試所需要的帶有調試信息的symbol。

    可以通過Run -> Load -> Load Symbols 加載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 -> AddSymbols, 加載的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等調試。

 在基於Linux的AM335x軟件開發流程中,第一步就是U-Boot/SPL(SecondProgram Loader)的移植。在移植中遇到問題比較常見,而U-Boot/SPL的調試手段比較簡陋,不便於迅速找到問題。利用仿真器可以單步調試的特點,就可以迅速定位到出問題的代碼所在位置,加速移植的調試過程。本文主要介紹如何用CCS+emulator調試基於AM335x的U-Boot/SPL。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章