当前位置:   article > 正文

基于AM335x的U-Boot/SPL 的CCS 调试_ccs am335x uboot

ccs am335x uboot

 在基于Linux的AM335x软件开发流程中,第一步就是U-Boot/SPL(SecondProgram 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的两个阶段。这里分为两个阶段的原因是, 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信息,可以找到各函数入口的地址

 

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 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接口所停住

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中,就不需要加载 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 等调试。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/319357
推荐阅读
相关标签
  

闽ICP备14008679号