garfield

【原创】CodeWarrior工具秘笈第1招:停止启动

0
阅读(2609)

偶尔我会遇到一个特别令人不快的问题:通过CodeWarrior IDE,我已经将我的应用下载到我的目标板,以便用于调试,而调试器立即失去了连接(图1)。


图1.此处发生了什么?

问题是什么?为了回答这一点,理解CodeWarrior IDE(或者任何其他调试工具)启动调试对话时到底发生了什么事情会为我们提供帮助。

调试发生的事情

点击CodeWarrior IDE中Debug(调试)按钮,设置事件的顺序为运动,将探测针连接配置到目标板,将程序下载到固件之内(或者芯片或者线路板上),提前准备调试对话。更具体的步骤如下:

1. CodeWarrior IDE会将应用程序暂存在目标板中。(关于这一目标可以成功达成,调试器或者探针——例如P&E多链路探针——将小型程序下载到目标RAM中,执行实际的闪存编程。闪存编程小型程序启动。然后调试器将数据——程序代码——输入小型程序,直到所有数据都传输到闪存之中。)

2. 调试器初始化处理器的PC (程序计数器)和SP (堆栈指针)。

3. 如果配置的方式如此,调试器会设置一个临时的中断点。到达这一时刻会有更多情况。

4. 调试器发布“运行”命令。即,调试器告知处理器开始执行,从存储在PC的地址启动。

第二步(设置初始PC地址)的准确执行部分取决于微控制器(MCU)架构。此外,似乎每一个调试器处理初始化的方式也都稍有不同。尽管存在差异,通常的成果都会将PC和SP设置完成。这些数值通常被存储在向量表的某处(例如S08和ColdFire微控制器)。当重置时这些数值也会被处理器获得。通常调试器仅会单纯确认重置以便重新加载这些数值。

临时中断点

有趣的部分是第三步,即调试器设置临时中断点。临时中断点只会发生一次,然后会被清除。通常中断点设置在main()。当您启动调试器会话时的方式,调试器会让所有启动代码执行,该程序会在main()停止。这种布置会让您省略大量的启动代码行,它们是用于配置处理器寄存器并且初始化外围设备。这完全合理,因为您真正希望完成是正确利用应用代码。

这一计划可以正确运行,除非执行队列跳跃到重置地址和main()之间的某个位置,您会面对图1中的Problem Occurred(“发生问题”)的对话框。通常会发生以下问题:

  • 启动代码执行时间过长。这会导致看门狗计时器到时。看门狗在您main()中的代码可能“输入给看门狗”(重置计时器)之前会尽责重置目标。此处典型的“元凶”是启动代码必须初始化或者归零、存在大量的内存。
  • 应用输入点或初始堆栈指针不正确,导致总线访问错误。
  • 当目标冲突时,运行控制/调试连接切断。
  • 凭借您可能想象得出或想象不出的怪异问题。

启动停止

为了解决这个问题,您需要关注启动代码。这即是说,您希望告知调试器比main()更早地停止,因此您能够检查启动代码的运行。幸运的是,在调试/运行启动配置窗口(图2)中可以实现这一设置:


图2.调试器选项中“启动停止”设置

如果检查了Stop on startup at(“启动停止”)设置,调试器会设置通过下两个选项确定,设置临时中断点。否则,目标运行。出现以下选择:

  • 程序入口点:如果选定,调试器会将中断点置于程序代码(包括启动代码在内)的起点。
  • 用户指定:如果选定,此处您可以指定任意功能的名称。然后调试器会将中断点置于指定功能的起点。正如图中所示,默认功能名称为main()。

程序入口点

还有一个剩余的问题:程序入口点在何处?您很可能会想到调试器进行控制的位置,只要让您重新确定问题不在发生在探针:

**********************************************

启动部分

-------------------------------------------------------------------------

入口点:0xC004(_EntryPoint)
_startupData被分配在0xC09C,并且采用6字节

S08链接器具有ENTRY(输入)命令,可以指定程序入口点到链接器的地址。入口点采用应用ELF文件格式进行编码。但是它可以采用ELF/Dwarf阅读器(例如readelf)显示。关于面向MCU工具安装的CoreWarrior,运行{MCU10.2 Installation}\Cross_Tools\CodeSourcery_Linux\bin\m68k-linux-gnu-readelf.exe。

readelf的输出应该如下显示:

readelf -l hello.abs
Elf文件为EXEC(可执行文件)
入口点 0xc004
...

因此,当您点击Debug(调试)时,调试器应该在地址0xc004的位置停止程序。

总结

如果调试会话在下载之后出现异常情况,或者如果应用并未到达main(),则停止程序入口点的调试器,而并非位于main()。这很容易做到。

停止任务非常轻松!

Baidu
map