spring boot 如何调试在AM335x上调试u-boot

-------------
新增文件夹...
新增文件夹
(多个标签用逗号分隔)
学习笔记之 AM335x Linux 的uboot工作流程.doc
一、AM335x的启动过程AM335x的启动主要包括ROM,SPL,U-Boot和kernel四个启动步骤:ROMcode ROMcode是固化在芯片内部的代码,当上电时序正确,而且晶振等芯片启动所需的条件都具备时,AM335x会从ROMcode开始运行。ROMcode首先会读取sys_boot引脚上的配置,以确定存放SPL的存储器,或者可以获取SPL的外设。
一、AM335x的启动过程AM335x的启动主要包括ROM,SPL,U-Boot和kernel四个启动步骤:ROMcode ROMcode是固化在芯片内部的代码,当上电时序正确,而且晶振等芯片启动所需的条件都具备时,AM335x会从ROMcode开始运行。ROMcode首先会读取sys_boot引脚上的配置,以确定存放SPL的存储器,或者可以获取SPL的外设。 &&
加载中...!如果长时间没有加载,请刷新页面
下载本文档需要登录,并付出相应积分()。
文件大小:59.50 KB
所需积分:& 4
相关资讯  — 
相关讨论话题  — 
浏览:21927次&& 下载:22次
收藏:12人
上传时间: 22:18:07
同类热门文档
0次浏览 &4次下载
5753次浏览 &7次下载
11793次浏览 &3次下载
6204次浏览 &4次下载
0次浏览 &6次下载
0次浏览 &5次下载
相关经验 -
& 0人评&8页
& 4人评&7页
& 0人评&30页
& 0人评&16页
& 1人评&9页
OPEN-OPEN, all rights reserved.AM335x(TQ335x)学习笔记——u-boot-2014.10移植 - 【DSP】 - 电子工程世界-论坛
后使用快捷导航没有帐号?
请完成以下验证码
查看: 2013|回复: 3
AM335x(TQ335x)学习笔记——u-boot-2014.10移植
在线时间0 小时
TA的帖子TA的资源
一粒金砂(初级), 积分 1, 距离下一级还需 4 积分
一粒金砂(初级), 积分 1, 距离下一级还需 4 积分
最近移植了下u-boot-2014.10到TQ335x,如果基于am335x evm进行移植,需要修改的地方并不多。由于TI的am335x evm开发使用了一个eeprom保存了板载配置信息,用来区分不同板子的型号的,而TQ335x没有这个eeprom,因此,需要修改eeprom相关的部分,使u-boot适应TQ335x开发板。使用source insight查看代码,很容易发现,所有获取板载配置的部分都是通过读取eeprom获得的,因此,首选修改read_eeprom(board/ti/am335x/board.c)函数,具体的修改如下:static int read_eeprom(struct am335x_baseboard_id *header)&& {&& #if 1&& & & strcpy(header-&name, &TQ335x&);&& #else&& & & /* Check if baseboard eeprom is available */&& & & if (i2c_probe(CONFIG_SYS_I2C_EEPROM_ADDR)) {&& & && &&&puts(&Could not probe the EEPROM; something fundamentally &&& & && && && &&wrong on the I2C bus.\n&);&& & && &&&return -ENODEV;&& & & }&& && & & /* read the eeprom using i2c */&& & & if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 2, (uchar *)header,&& & && && && & sizeof(struct am335x_baseboard_id))) {&& & && &&&puts(&Could not read the EEPROM; something fundamentally&&& & && && && && wrong on the I2C bus.\n&);&& & && &&&return -EIO;&& & & }&& && & & if (header-&magic != 0xEE3355AA) {&& & && &&&/*
& && && &* read the eeprom using i2c again,
& && && &* but use only a 1 byte address
& && && &*/&& & && &&&if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 1, (uchar *)header,&& & && && && && &&&sizeof(struct am335x_baseboard_id))) {&& & && && && &puts(&Could not read the EEPROM; something &&& & && && && && & &fundamentally wrong on the I2C bus.\n&);&& & && && && &return -EIO;&& & && &&&}&& && & && &&&if (header-&magic != 0xEE3355AA) {&& & && && && &printf(&Incorrect magic number (0x%x) in EEPROM\n&,&& & && && && && && &&&header-&magic);&& & && && && &return -EINVAL;&& & && &&&}&& & & }&& #endif&& && & & return 0;&& }&&复制代码通过上述修改,u-boot不去读取eeprom,而是直接将header的name赋值为&TQ335x&,后面可以根据这一配置区分是否为TQ335x开发板。
然后是修改get_dpll_ddr_params(board/ti/am335x/board.c)函数,具体的修改内容如下:const struct dpll_params *get_dpll_ddr_params(void)&& {&& & & struct am335x_baseboard_&& && & & enable_i2c0_pin_mux();&& & & i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE);&& & & if (read_eeprom(&header) & 0)&& & && &&&puts(&Could not get board ID.\n&);&& && & & if (board_is_tq335x(&header) || board_is_evm_sk(&header))&& & && &&&return &dpll_ddr_evm_&& & & else if (board_is_bone_lt(&header))&& & && &&&return &dpll_ddr_bone_&& & & else if (board_is_evm_15_or_later(&header))&& & && &&&return &dpll_ddr_evm_&& & & else&& & && &&&return &dpll_&& }&&复制代码然后是修改sdram_init(board/ti/am335x/board.c)函数,具体的修改内容如下:void sdram_init(void)&& {&& & & __maybe_unused struct am335x_baseboard_&& && & & if (read_eeprom(&header) & 0)&& & && &&&puts(&Could not get board ID.\n&);&& && & & if (board_is_evm_sk(&header)) {&& & && &&&/*
& && && &* EVM SK 1.2A and later use gpio0_7 to enable DDR3.
& && && &* This is safe enough to do on older revs.
& && && &*/&& & && &&&gpio_request(GPIO_DDR_VTT_EN, &ddr_vtt_en&);&& & && &&&gpio_direction_output(GPIO_DDR_VTT_EN, 1);&& & & }&& && & & if (board_is_evm_sk(&header) || board_is_tq335x(&header))&& & && &&&config_ddr(303, &ioregs_evmsk, &ddr3_data,&& & && && && && &&ddr3_cmd_ctrl_data, &ddr3_emif_reg_data, 0);&& & & else if (board_is_bone_lt(&header))&& & && &&&config_ddr(400, &ioregs_bonelt,&& & && && && && &&ddr3_beagleblack_data,&& & && && && && &&ddr3_beagleblack_cmd_ctrl_data,&& & && && && && &&ddr3_beagleblack_emif_reg_data, 0);&& & & else if (board_is_evm_15_or_later(&header))&& & && &&&config_ddr(303, &ioregs_evm15, &ddr3_evm_data,&& & && && && && &&ddr3_evm_cmd_ctrl_data, &ddr3_evm_emif_reg_data, 0);&& & & else&& & && &&&config_ddr(266, &ioregs, &ddr2_data,&& & && && && && &&ddr2_cmd_ctrl_data, &ddr2_emif_reg_data, 0);&& }&&复制代码然后添加board_is_tq335x函数的具体实现,参考其它类似函数实现即可,由于我们的read_eeprom仅读到了name,其内容是&TQ335x&,故可如下实现,在board/ti/am335x/board.h中添加如下内容:static inline int board_is_tq335x(struct am335x_baseboard_id *header)&& {&& & & return !strncmp(header-&name, &TQ335x&, HDR_NAME_LEN);&& }&&复制代码最后是修改enable_board_pin_mux(board/ti/am335x/mux.c)函数,具体的修改内容如下:void enable_board_pin_mux(struct am335x_baseboard_id *header)&& {&& & & /* Do board-specific muxes. */&& & & if (board_is_bone(header) || board_is_tq335x(header)) {&& & && &&&/* Beaglebone pinmux */&& & && &&&configure_module_pin_mux(i2c1_pin_mux);&& & && &&&configure_module_pin_mux(mii1_pin_mux);&& & && &&&configure_module_pin_mux(mmc0_pin_mux);&& #if defined(CONFIG_NAND)&& & && &&&configure_module_pin_mux(nand_pin_mux);&& #elif defined(CONFIG_NOR)&& & && &&&configure_module_pin_mux(bone_norcape_pin_mux);&& #else&& & && &&&configure_module_pin_mux(mmc1_pin_mux);&& #endif&& & & } else if (board_is_gp_evm(header)) {&& & && &&&/* General Purpose EVM */&& & && &&&unsigned short profile = detect_daughter_board_profile();&& & && &&&configure_module_pin_mux(rgmii1_pin_mux);&& & && &&&configure_module_pin_mux(mmc0_pin_mux);&& & && &&&/* In profile #2 i2c1 and spi0 conflict. */&& & && &&&if (profile & ~PROFILE_2)&& & && && && &configure_module_pin_mux(i2c1_pin_mux);&& & && &&&/* Profiles 2 & 3 don't have NAND */&& #ifdef CONFIG_NAND&& & && &&&if (profile & ~(PROFILE_2 | PROFILE_3))&& & && && && &configure_module_pin_mux(nand_pin_mux);&& #endif&& & && &&&else if (profile == PROFILE_2) {&& & && && && &configure_module_pin_mux(mmc1_pin_mux);&& & && && && &configure_module_pin_mux(spi0_pin_mux);&& & && &&&}&& & & } else if (board_is_idk(header)) {&& & && &&&/* Industrial Motor Control (IDK) */&& & && &&&configure_module_pin_mux(mii1_pin_mux);&& & && &&&configure_module_pin_mux(mmc0_no_cd_pin_mux);&& & & } else if (board_is_evm_sk(header)) {&& & && &&&/* Starter Kit EVM */&& & && &&&configure_module_pin_mux(i2c1_pin_mux);&& & && &&&configure_module_pin_mux(gpio0_7_pin_mux);&& & && &&&configure_module_pin_mux(rgmii1_pin_mux);&& & && &&&configure_module_pin_mux(mmc0_pin_mux_sk_evm);&& & & } else if (board_is_bone_lt(header)) {&& & && &&&/* Beaglebone LT pinmux */&& & && &&&configure_module_pin_mux(i2c1_pin_mux);&& & && &&&configure_module_pin_mux(mii1_pin_mux);&& & && &&&configure_module_pin_mux(mmc0_pin_mux);&& #if defined(CONFIG_NAND)&& & && &&&configure_module_pin_mux(nand_pin_mux);&& #elif defined(CONFIG_NOR)&& & && &&&configure_module_pin_mux(bone_norcape_pin_mux);&& #else&& & && &&&configure_module_pin_mux(mmc1_pin_mux);&& #endif&& & & } else {&& & && &&&puts(&Unknown board, cannot configure pinmux.&);&& & && &&&hang();&& & & }&& }&&复制代码另外,这个版本的u-boot有个bug,需要修改fat_register_device(fs/fat/fat.c)函数:int fat_register_device(block_dev_desc_t *dev_desc, int part_no)&& {&& & & disk_partition_&& && & & /* First close any currently found FAT filesystem */&& & & cur_dev = NULL;&& && & & /* Read the partition table, if present */&& & & if (get_partition_info(dev_desc, part_no, &info)) {&& & && &&&/*if (part_no != 0) {
& && && && &printf(&** Partition %d not valid on device %d **\n&,
& && && && && && &&&part_no, dev_desc-&dev);
& && && && &return -1;
& && &&&}*/&& && & && &&&info.start = 0;&& & && &&&info.size = dev_desc-&&& & && &&&info.blksz = dev_desc-&&& & && &&&info.name[0] = 0;&& & && &&&info.type[0] = 0;&& & && &&&info.bootable = 0;&& #ifdef CONFIG_PARTITION_UUIDS&& & && &&&info.uuid[0] = 0;&& #endif&& & & }&& && & & return fat_set_blk_dev(dev_desc, &info);&& }&&复制代码至此,u-boot就已经可以启动了,但是有多余的步骤和log,不过可以去掉,修改file_fat_read_at(fs/fat/fat.c)函数:long file_fat_read_at(const char *filename, unsigned long pos, void *buffer,&& & && && && &&&unsigned long maxsize)&& {&& & & debug(&reading %s\n&, filename);&& & & return do_fat_read_at(filename, pos, buffer, maxsize, LS_NO, 0);&& }&&复制代码最后,TQ335x是MLO启动u-boot,然后u-boot去启动内核,故可以去掉配置项CONFIG_SPL_OS_BOOT,具体的修改文件include/configs/ti_armv7_common.h:#if defined(CONFIG_SPL_OS_BOOT_ENABLE)&& #define CONFIG_SPL_OS_BOOT&& #endif&&复制代码至此,u-boot的移植工作就完成了,编译方法如下:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- am335x_evm_defconfig&& make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j8&&复制代码其中,arm-linux-gnueabi-需要根据自己的交叉编译工具链前缀进行修改。完成u-boot的移植工作后我们来研究如何启动内核。源码下载地址:
(9.95 MB, 下载次数: 34)
12:00 上传
点击文件名下载附件
<p id="rate_09" onmouseover="showTip(this)" tip="很给力!&芯币 + 1 枚
" class="mtn mbn">
在线时间3565 小时
威望5161分
芯币12162枚
E金币387枚
TA的帖子TA的资源
不错 写的很详细!
生活就是油盐酱醋再加一点糖,快活就是一天到晚乐呵呵的忙
===================================
做一个简单的人,踏实而务实,不沉溺幻想,不庸人自扰
在线时间146 小时
TA的帖子TA的资源
一粒金砂(中级), 积分 24, 距离下一级还需 176 积分
一粒金砂(中级), 积分 24, 距离下一级还需 176 积分
U-Boot 2014.10 與 U-Boot
(sdk6.0) 主要差異是什麼?
SDK7.0,SDK 8.0 已改為Device Tree , Uboot要改什麼嗎?
在线时间7 小时
TA的帖子TA的资源
一粒金砂(初级), 积分 0, 距离下一级还需 5 积分
一粒金砂(初级), 积分 0, 距离下一级还需 5 积分
EEWORLD 官方微信
EE福利 唾手可得
Powered byU-Boot for AM335x (10) u-boot.img如何驱动SD卡
调试SPL的阶段貌似进行得非常顺利,主要是它的功能并不多,除了初始化GPIO、UART0、PMIC、DRAM之外,还有就是把u-boot.img搬进DRAM运行。在这个阶段里面,MMC(SD卡)是被自动识别的,用户不需要任何设置,MLO就会被从SD卡中读取到内部的DRAM中运行,然后才有后续的一系列操作。
SPL里面初始化SD卡的代码在:
arch/arm/cpu/armv7/omap-common/boot-common.c
函数名是:
int board_mmc_init(bd_t *bis);
int omap_mmc_init(int dev_index, uint host_caps_mask, uint f_max, int cd_gpio,
&&&&&&&&&&&&&&& int wp_gpio);
在u-boot.img运行的时候,也会使用SPL里面初始化的MMC,默认就可以读取数据。有时候会发现这样的提示:
Card did not respond to voltage select!
这是因为AM335x默认会初始化MMC0/MMC1两个设备,而MMC1并不能检测到卡的存在,并不影响MMC0的使用。
实际上在u-boot.img的board_init_r函数中,又出现了MMC的初始化函数:
mmc_initialize(gd-&bd);
它同样会调用board_mmc_init,但是这个board_mmc_init被mmc_initialize所在的文件:
driver/mmc/mmc.c
使用关键字weak alias将函数变成了什么都不做,而是直接返回-1:
int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias(&__def_mmc_init&)));
int board_mmc_init(bd_t *bis) __attribute__((weak, alias(&__def_mmc_init&)));
虽然使用默认的配置也能工作,但是完整的SD卡引脚还定义了WP和CD,即写保护和状态检测,它们在SPL的初始化中被认为是-1和-1,这里给它赋上合适的值。在board_init_r中会调用函数board_init,用户可以填写自己的target代码,因此在这里加上:
configure_module_pin_mux(mmc0_pin_mux);
omap_mmc_init(0, 0, 0, 6, 114);
定义MMC0的MUX:
static struct module_pin_mux mmc0_pin_mux[] = {
&&&&&&& {OFFSET(mmc0_dat3), (MODE(0) | RXACTIVE | PULLUP_EN)},& /* MMC0_DAT3 */
&&&&&&& {OFFSET(mmc0_dat2), (MODE(0) | RXACTIVE | PULLUP_EN)},& /* MMC0_DAT2 */
&&&&&&& {OFFSET(mmc0_dat1), (MODE(0) | RXACTIVE | PULLUP_EN)},& /* MMC0_DAT1 */
&&&&&&& {OFFSET(mmc0_dat0), (MODE(0) | RXACTIVE | PULLUP_EN)},& /* MMC0_DAT0 */
&&&&&&& {OFFSET(mmc0_clk), (MODE(0) | RXACTIVE | PULLUP_EN)},&& /* MMC0_CLK */
&&&&&&& {OFFSET(mmc0_cmd), (MODE(0) | RXACTIVE | PULLUP_EN)},&& /* MMC0_CMD */
&&&&&&& {OFFSET(mcasp0_aclkr), (MODE(4) | RXACTIVE)},&&&&&&&&&& /* MMC0_WP */
&&&&&&& {OFFSET(spi0_cs1), (MODE(5) | RXACTIVE | PULLUP_EN)},&& /* MMC0_CD */
&&&&&&& {-1},
6和114的意义是GPIO0_6/GPIO3_18。
重新编译运行,在U-Boot命令提示符下输入fatls:
U-Boot# fatls mmc 0
&&& 78092&& mlo
&& 316860&& u-boot.img
& 3450576&& uimage
&& 316796&& u-boot.bin
&&&&&&&&&&& .trash-1000/
在U-Boot命令提示符下输入fatload命令(将uImage拷贝进相同的目录):
U-Boot# fatload mmc 0 0x uImage
reading uImage
3450576 bytes read in 333 ms (9.9 MiB/s)
U-Boot# bootm 0x
运行uImage:
U-Boot# bootm 0x
在U-Boot命令提示符出现之前,会有一个从MMC中读取reading uEnv.txt的步骤,在TI官网上的下面这篇文章里,给出了uEnv.txt建议的内容:
bootargs=console=ttyO0, root=/dev/mmcblk0p2 mem=128M rootwait
bootcmd= fatload mmc 0 0x uI bootm 0x
uenvcmd=boot
它的格式必须是unix format,文件末尾必须加一个空行。将uEnv.txt和uImage拷贝进SD卡,设置AM335x从SD卡启动,此时就会发现熟悉的kernel解压信息出现啦
Importing environment from mmc ...
Running uenvcmd ...
reading uImage
3450576 bytes read in 333 ms (9.9 MiB/s)
## Booting kernel from Legacy Image at
&& Image Name:&& Linux-3.2.0
&& Image Type:&& ARM Linux Kernel Image (uncompressed)
&& Data Size:&&& 3450512 Bytes = 3.3 MiB
&& Load Address:
&& Entry Point:&
&& Verifying Checksum ... OK
&& Loading Kernel Image ... OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
[&&& 0.000000] Linux version 3.2.0 (root@adu-pc) (gcc version 4.5.3
(prerelease) (GCC) ) #1 Thu Jan 23 09:54:20 CST 2014
[&&& 0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), cr=10c53c7d
[&&& 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[&&& 0.000000] Machine: am335xevm
(到目前为止,虽然顺利的从SD卡启动和解压Linux kernel,但是还是存在Linux kernel解压到一半卡住的问题。貌似在网上经常看到类似的帖子描述这个问题。anyway,这个等后面再解决,下一步先完善U-Boot的eth驱动。)
与非门科技(北京)有限公司 All Rights Reserved.
京ICP证:070212号
北京市公安局备案编号: 京ICP备:号原文来自德仪中文在线,需要的直接去下原文吧。
的U-Boot/SPL 的CCS 调试
&&& 在基于Linux的AM335x软件开发流程中,第一步就是U-Boot/SPL(Second Program Loader)的移植。在移植中遇到问题比较常见,而U-Boot/SPL的调试手段比较简陋,不便于迅速找到问题。利用仿真器可以单步调试的特点,就可以迅速定位到出问题的代码所在位置,加速移植的调试过程。本文主要介绍如何用CCS&#43;emulator调试基于AM335x的U-Boot/SPL。
1.&&&&AM335x &Linux启动过程以及U-Boot/SPL调试代码的准备
1.1 的启动过程
AM335x Linux的启动主要包括ROM,SPL, U-Boot 和kernel四个启动步骤:
A.&& ROM code
ROM code是固化在芯片内部的代码,当上电时序正确,而且晶振等芯片启动所需的条件都具备时,AM335x会从ROM code开始运行。
ROM code首先会读取sys_boot引脚上的配置,以确定存放SPL的存储器,或者可以获取SPL的外设。
具体可以参考AM335x 中的第26章 Initialization。
ROM code会从相应的地方读取/获取SPL,并运行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类&#20284;,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发布:
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))
279 ALL_CFLAGS = $(CFLAGS)$(CFLAGS_$(BCURDIR)/$(@F)) $(CFLAGS_$(BCURDIR))
B.&& 去掉 CFLAG中的编译选项, -O2(U-Boot中默认是-O2)
61 HOSTCFLAGS& = -Wall-Wstrict-prototypes -O2 -fomit-frame-pointer
编译过程可以参考
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&#26684;式,是调试时需要的image。
C.&& U-Boot.map这个文件里面存储了U-Boot的memory map信息,可以找到各函数入口的地址
2.&&&&调试环境的准备
调试环境主要包含3个部分,仿真器,集成调试环境和开发板。下面将逐一介绍:
2.1 仿真器(emulator)
目前支持AM335x的仿真器的型号比较多,有XDS560v2, XDS510,XDS100v2, XDS100v3,等,比较常见的是XDS560v2和XDS100v2。
& & & &XDS560v2,性能好,速度快,具有trace功能,但是价&#26684;偏贵。 &XDS100v2价&#26684;比较便宜。&其具备和XDS560v2 一样的基本调试功能,只是XDS100v2的速度相对略慢。
&&&&& XDS560v2和XDS100v2在PC机上的驱动(Windows, Linux)都已经包含在CCS中了,所以安装了最新版的CCS,就会安装相应的驱动。
2.2 集成开发环境
TI有自己的集成开发环境(IDE)CCS.目前最新的版本是基于Eclipse IDE架构的,界面新颖方便。
&& 下载地址&。
&& &CCS有Windows版本和Linux 版本,后面会在介绍调试过程中具体介绍两者的差异。
2.3 开发板
目前,针对不同的应用,TI发布了基于AM335x的多个开发板。其中,和上配置了基于FT2232的xds100v2。而和上引出了接口。
这里选择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配置等几部分:
& & &对于 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的&#20540;设为0x402f0400。可以通过View-&Registers中设置PC指针的&#20540;即可, 界面如下,将红色框里面的改为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代码中设置断点,进行调试了。有两点&#20540;得注意:
&&&&&&&&&&&&&&&&&&&&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调试过程是类&#20284;的,这里主要说明不同的几点:
A.&& 从AM335x的启动过程可知,U-Boot是运行在DDR中的,而DDR是由SPL来初始化的,所以,加载U-Boot前,先加载并运行SPL。
B.&& 加载U-Boot 的image是 U-Boot。 这里U-Boot 是ELF&#26684;式的, 其包含了加载地址, symbol等信息,所以使用CCS 菜单 Run-& Load-& LoadProgram, 加载U-Boot 即可。加载成功后, 如下图所示:
&&&&& 如图所示, PC直接指到0x地址了,也就是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&#43;emulator对AM335x的U-Boot/SPL的调试就介绍完了。这里介绍的方法,包含了CCS&#43;emulator调试的基本原则,不仅仅可以运用于U-Boot/SPL调试,也可以运用于Starterware,Kernel等调试。
&在基于Linux的AM335x软件开发流程中,第一步就是U-Boot/SPL(SecondProgram Loader)的移植。在移植中遇到问题比较常见,而U-Boot/SPL的调试手段比较简陋,不便于迅速找到问题。利用仿真器可以单步调试的特点,就可以迅速定位到出问题的代码所在位置,加速移植的调试过程。本文主要介绍如何用CCS&#43;emulator调试基于AM335x的U-Boot/SPL。
1.&&&&AM335x &Linux启动过程以及U-Boot/SPL调试代码的准备
1.1&的启动过程
AM335x Linux的启动主要包括ROM,SPL, U-Boot 和kernel四个启动步骤:
A.&& ROM code
ROM code是固化在芯片内部的代码,当上电时序正确,而且晶振等芯片启动所需的条件都具备时,AM335x会从ROM code开始运行。
ROM code首先会读取sys_boot引脚上的配置,以确定存放SPL的存储器,或者可以获取SPL的外设。
具体可以参考AM335x&中的第26章 Initialization。
ROM code会从相应的地方读取/获取SPL,并运行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类&#20284;,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发布:
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
编译过程可以参考
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&#26684;式,是调试时需要的image。
C.&& U-Boot.map这个文件里面存储了U-Boot的memory map信息,可以找到各函数入口的地址
2.&&&&调试环境的准备
调试环境主要包含3个部分,仿真器,集成调试环境和开发板。下面将逐一介绍:
2.1 仿真器(emulator)
目前支持AM335x的仿真器的型号比较多,有XDS560v2,XDS510,XDS100v2, XDS100v3,等,比较常见的是XDS560v2和XDS100v2。
& & & &XDS560v2,性能好,速度快,具有trace功能,但是价&#26684;偏贵。 &XDS100v2价&#26684;比较便宜。&其具备和XDS560v2一样的基本调试功能,只是XDS100v2的速度相对略慢。
&&&&& XDS560v2和XDS100v2在PC机上的驱动(Windows,Linux)都已经包含在CCS中了,所以安装了最新版的CCS,就会安装相应的驱动。
2.2 集成开发环境
TI有自己的集成开发环境(IDE)CCS.目前最新的版本是基于Eclipse IDE架构的,界面新颖方便。
&& 下载地址&。
&&&CCS有Windows版本和Linux 版本,后面会在介绍调试过程中具体介绍两者的差异。
2.3 开发板
目前,针对不同的应用,TI发布了基于AM335x的多个开发板。其中,和上配置了基于FT2232的xds100v2。而和上引出了接口。
这里选择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配置等几部分:
& & &对于 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的&#20540;设为0x402f0400。可以通过View-&Registers中设置PC指针的&#20540;即可, 界面如下,将红色框里面的改为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代码中设置断点,进行调试了。有两点&#20540;得注意:
&&&&&&&&&&&&&&&&&&&&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调试过程是类&#20284;的,这里主要说明不同的几点:
A.&& 从AM335x的启动过程可知,U-Boot是运行在DDR中的,而DDR是由SPL来初始化的,所以,加载U-Boot前,先加载并运行SPL。
B.&& 加载U-Boot 的image是 U-Boot。 这里U-Boot 是ELF&#26684;式的, 其包含了加载地址, symbol等信息,所以使用CCS 菜单 Run-& Load-& LoadProgram, 加载U-Boot 即可。加载成功后, 如下图所示:
&&&&& 如图所示, PC直接指到0x地址了,也就是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&#43;emulator对AM335x的U-Boot/SPL的调试就介绍完了。这里介绍的方法,包含了CCS&#43;emulator调试的基本原则,不仅仅可以运用于U-Boot/SPL调试,也可以运用于Starterware,Kernel等调试。
本文已收录于以下专栏:
相关文章推荐
在基于Linux的AM335x软件开发流程中,第一步就是U-Boot/SPL(SecondProgram Loader)的移植。在移植中遇到问题比较常见,而U-Boot/SPL的调试手段比较简陋,不便...
他的最新文章
讲师:王哲涵
讲师:王渊命
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)}

我要回帖

更多关于 uboot 调试 ram中运行 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信