redboot跑起来了,下了个hello world的ecos程序也跑起来了,我写了一个简单的ecos程序,用redboot和arm-eabi-gdb来调试它,按照下面的步骤,开始都ok.
arm-eabi-gdb test.elf -b 19200 -nw
target remote /dev/ttyS0
load
break 20
c
程序顺利运行到所设的断点处
然后gdb命令查看内存,寄存器,变量的值,反汇编等,都正常,但只要再往下运行一行语句,程序就跑飞了。
为了查找问题,首先要搞清楚redboot是怎样单步运行程序的。下面是redboot与gdb通讯过程概述。
redboot起动,进入readboot主循环。此main_loop定义在.../packages/redboot/.../src/main.c中。
当收到一个$符时,redboot即进入到调试状态,由debug_stub接管控制权,执行顺序为:
gdb_stack_sp = (CYG_ADDRESS)workspace_end;
// set up a temporary context that will take us to the trampoline
HAL_THREAD_INIT_CONTEXT(gdb_stack_sp,
breakpoint, trampoline,0);
// switch context to trampoline (get GDB stubs started)
HAL_THREAD_SWITCH_CONTEXT(&saved_context, &gdb_stack_sp);
HAL_THREAD_INIT_CONTEXT建立一个临时context, 程序运行进入trampoline函数,在trampoline执行breakpoint,
breakpoint定义在hal/arm/arch/src/hal_misc.c中, 其中安放着一条非法指令,当程序运行至breakpoint时,便发生异常,控制权交到
generic-stub.c中定义的__handle_exception, 这里也有一个主循环,接收来自gdb的数据,并处理它,大部分命令由函数__process_packet处理,当收到Continue, step, 等命令时,会在相应位置设置好断点,断点仍然而是一条非法指令,并不是swi, 然后程序会退出主循环,控制权交回到定义在vector.S中的异常处理程序,
#ifndef CYGOPT_HAL_ARM_PRESERVE_SVC_SPSR
msr spsr,r0
ldmeqfd sp,{r0-r14,pc}^
endif
这两句话可让程序进入到我们要调试的程序,因为堆栈上保存的是我们的正在调试的程序的context, 这两句话实际上是恢复了我们正在调试的程序的context. 之后当程序遇到我们所设的断点时,会再次进入到异常处理程序,从而再次把控制权交给generic-stub.c中定义的__handle_exception.
我的问题发生在
ldmeqfd sp,{r0-r14,pc}^
这句话上,当程序运行到此处时就飞了。
我改成
ldmeqfd sp,{r0-r14,pc}就可以,这说明状态寄存器有问题,打印出来看了一下,spsr的值是0x60000013, 而原先的cpsr是0x600000d3, 区别就只是有没有禁止irq和fiq, 应该是我的中断服务程序有问题。明天接着看。