上电之后(bootload阶段)该做什么
1、第一行程序
拿到空PCB板之后,硬件工程师首先会测试各主要线路是否通连,各焊点是否有空焊、断接或短路的情况,然后逐个模块焊接上去。之后需要验证系统上电之后,CPU与各组件的供电电压是否正常,供给CPU的震荡电路能否能够正常起振,外部存储器能否正常读写。当把我们的程序用JTAG工具下载到板子上后,在真正调试系统前需要做好以下检查:
- 利用调试工具,在程序的第一行设定断点,确定程序有停下来;
- 检查CPU的程序计数器PC是否正确;
- 检查CPU内部RAM的内容和我们下载的可执行文件是否相同;
- 程序的第一行命令为设定CPU状态寄存器,并观察CPU的状态寄存器是否如预期改变;
- 继续单步执行,确认PC寄存器是否会跟着改变,且每行命令的执行结果都是正确的。
检查完以上各项后,只能证明板子上的电源电路以及CPU是正常的,接下来要继续验证CPU与外围设备,确认板子的正确性与稳定性后,才能进行下一步测试。
2、基本硬件测试
既然Boot-Loader的责任是帮其它程序布置可运行的环境,那么就要做好以下验证:
- CPU寄存器(状态寄存器、通用寄存器、内存映射寄存器)操作测试;
// 设定SP(Stack Point)寄存器
//
asm("xld.w %r15, 0x2000");
asm("ld.w %sp, %r15");
// 设定CPU的状态寄存器
//
asm("xld.w %r15, 0x200010");
asm("ld.w %psr, %r15");
// 将寄存器0x300023的bit 1设为1
*(volatile unsigned char *)0x300023 |= 0x2;
- Stack Pointer的设置是否正确?函数调用是否正确运行?
- 中断是量表设置是否正确?中断矢量程序是否正常运行?
- 存储器初始化及其操作测试,保证所有的存储器都可以正常读写;
- 将数据段载入RAM,对bss段设定初值,并将需要在RAM中运行的程序载入到RAM。保证当主程序执行起来后,全局变量的初始值都是正确的。
只有确保以上测试通过后才能进行下一步工作。
(1)确认函数调用能否正常运行
正确设置堆栈(Stack)是函数能否成功调用的前提,在嵌入式系统开发时,系统要自行管理堆栈,如果管理不当,可能会发生函数调用或调用几层之后就死机的状况。因为C语言利用堆栈完成以下事项:
- 存储函数返回地址;
- 函数调用时的参数传递(参数较多时);
- 存储函数内部的局部变量;
- 中断服务程序执行时(发生中断时),存储CPU当前状态及返回地址。
堆栈顶点地址(Stack Point)的配置是一件很重要的事,但却极易被人忽略。主要是在Windows或Linux上编程时,操作系统在产生可执行文件时,linker会自动帮程序加上一段Startup Code,其中就包含了Stack存储器的配置。但在无操作系统的嵌入式系统中,调用任何函数之前都要先为其设置好堆栈空间(Stack Point)。
当用C语言调用了一个函数,例如fun(a,b),编译后的机器码应该包含以下动作:
- 执行指令push,将参数a和b存入Stack