Kinetis L系列的启动过程及其实现(二)
(7) 编译器放置 __startup 的ADDRESS 与真实程序入口点
质朴的思路就是, 作为初始代码, __startup 的 ADDRESS 应该位于 0x000000C0.
事实上不是, 我们假设这完全取决 linker 的安排, 包括运行效率, SIZE的共同优化与平衡的考虑. 实际上, 0x000000C0 是 main() 函数的首地址(见图例13).
分析的依据来源于我们生成的 Linker list 文件, 事实上它被表达为 .MAP 文件.
[图例11: .MAP 文件与各函数入口点LIST]
从源代码编译的 list 文件中, 对应的机器码为:
[图例12: 源文件编译后的 .list文件]
注意到 THUMB 的方式为 16-bit 机器码.
从 __startup 对应的地址: 0x00000129, 我们找到对应的机器码, 并进行标识(见图例13).
从 .bin 文件中, 我们读取 PC 的地址是: 0x0000181, 这说明真正的程序入口点在此,
参考 .MAP 文档, 0x00000181 address 对应程序入口点为: _iar_program_start.
[图例13: 程序入口点在 0x00000180 也就是 IAR IDE 默认生成的 _iar_program_start 函数处]
事实上, 我们进入 debug 后, 顺序执行, 我们将分析到:
_iar_program_start -> _main -> _call_main -> main 的过程.
这与我们设计的程序入口点的初衷并不一致. 我们希望程序进入的是 __startup 执行 BOOT 的过程.
(8) 修改程序入口点为 __startup
修改 Project 增加 vectors.h 与 vectors.c 文件
分析 linker 脚本语言, .intvec 被定义在 __ICFEDIT_intvec_start__ (也就是首地址 0x00000000).
分析 vectors.c 将异常中断向量表写在了 .intvec 的位置.
分析 vectors.h 决定了中断向量表中第二个量 VECTOR_001 被定义为 __startup, 也就是我们成功将 IAR 默认 _iar_program_start 为 __startup
[图例14: 从linker config 到 vector.c/vector.h]
最终的, 我们从生成的 .bin 文件中, 确认 PC 指向了新的入口点: 0x00000129, 也就是 __startup
[图例15: 新的 .bin 文件证明程序入口点现在是: __startup]
在 debug 中进行调试, 我们也确认单步调试进入了 __startup.
(9) 构建C代码 start() 函数执行 SYSTEM SETUP
在步骤(4)中, 我们完成了 .s 汇编函数 __startup, 根据 vectors.h 的定义, 指示这是 PC 指针的"入口点". (事实上, 如上对 .bin 文件和.map 文件分析, IAR 通过 _iar_program_start 实现的是真正的入口点. 我们猜测, 这里不影响我们对这个 "赝程序入口点 __startup" 的理解).
在 __startup 中, 我们清零通用寄存器, 并开启中断后, 跳转至 start() 函数, 也就进入了 SYSTEM SETUP 的过程.
(9.1) Disable watchdog
在 debug mode 下我们会没有机会喂狗, 因此 watchdog 需要disable.
如果没有做 disable, 我们将在 debug mode 下见到不断重启的提示. 进行 diable 后该现象消失.
[图例16: 在 SYSTEM BOOT 中需要 disable watchdog]
(9.2) Init RAM
包括 (a) 从 flash copy 向量表 to RAM. 我们至少能够作两个功能假定: 首先这个 copyto 过程, 能够保证我们从 RAM BOOT 成功(假设我们有从 RAM BOOT 的需求, 比如说某种机制下的 upgrade firmware). 其次可以想象 Interrupt 的响应速度增加(在 RAM 中寻址而不必从 FLASH 中读取). (b) 初始化数据从 flash copyto RAM. (c) data section 的 zero 初始化数据清零. (d) copy flash 中定义的 ram function 到 RAM(如果它们因某种加速目的或者 IAP 目的存在且被我们所定义).
[图例17: 在 Start() 中完成 Init RAM]
Tip1: 有时我们无法在C源文件中加入调试断点
我们在调试的过程中, 偶尔有问题为何可以在反汇编窗口调试, 但是 breakpoint 却无法建立在c语言的源代码中, 这里我们需要选中 IAR IDE 的 Options -> C/C++ compiler -> Output -> Check "Generate Debug Information" 即可.
可能有调试者会宣称 .out 文件(用于下载到 target board 进行调试) 会显著增加, 但是, 毕竟 .bin 文件不会因为这个 check 而发生任何变化.
用户1610239 2013-8-5 09:06