现在的位置: 首页 > 综合 > 正文

关于codewarrior调试出现illegal BP的问题解决过程(转载)

2018年03月16日 ⁄ 综合 ⁄ 共 1977字 ⁄ 字号 评论关闭

昨天两位工程师调试同时出现这个问题,网上对于illegal BP的解决方法讲解的很模糊,没有一个具体的指导方针。我试着阐述我们问题的解决过程,希望对大家解决类似情况可以起到抛砖引玉的作用。
    两位工程师同时出现该问题,但由于负责不同的功能,并且互相独立,可以判断是不同的问题引起的。
    通过单步运行(step over),工程师J发现当进入某个子函数时,对某个指针指向的变量清零时出错。
    func(unchar *P)
    {
      *P=0
    }
    刚开始怀疑堆栈溢出,但屏蔽了许多子函数并且检查xMAP文件,发现堆栈空间还是很多的,由于该函数多次被调用,我们逐个检查main中该函数的调用情况,发现某个地方调用该函数写为func(0),可能是工程师疏忽遗忘了。问题就在这里,0作为一个指针而不是变量被引用,在coldfire中,所指向的是单片机的初始监控堆栈指针,对它强行清零可想而知。
    工程师L的问题比较棘手,单步运行(step over)发现是退出中断时出错。我们采用标准的codewarrior中断声明格式
    void (*const vector_60)(void)  @Vfunc = isrfunc;

    我们在hiwave下查看memory窗口,发现中断向量所指向的中断处理函数地址完全正确。在汇编Assembly窗口下单步运行(single step)观察,发现执行到返回指令RTS后,程序跑飞。coldfire中地址寄存器A7作为堆栈指针使用,我们继续追查A7所指向的堆栈地址,发现在堆栈中插入了一个不是地址的数据。
    比如
    0x1000  正确的存储地址
    0x0FFC  非地址数据

    每次退出堆栈时,当堆栈指针指向0x0FFC时,PC就指向了这个非地址数据,于是程序跑飞。不论我们如何单步运行,都不能把插入该非地址数据和中断处理分离开。也就是说,这个非地址数据是进入中断时推入堆栈的,而不是其他指令产生的。我们在这里纠结了很久。后来偶然发现中断函数的写法有问题。
    工程师L的写法是
    void isrfunc(void)
    {
       asm
       {
          JMP func_ISR;
       }
    }

     void (*const vector_60)(void)  @Vfunc = func_ISR;

     但codewarrior的默认写法是
     __interrupt void isrfunc(void)
    {
        asm
        {
          JSR func_ISR;
        }
    }

    void (*const vector_60)(void)  @Vfunc = func_ISR;

    原来是JMP搞的鬼,JMP是直接跳转,而JSR是保存现场至堆栈后再跳转。修改JSR后发现debug仍旧出现illegal BP提示,查看堆栈,发现那个非地址数据插在两个地址中间,即
    0x1000  正确的存储地址
    0x0FFC  非地址数据
    0x0FF8  正确的存储地址
    难道是__interrupt的问题?老老实实补充完整后运行OK。没有illegal BP提示。检查汇编指令发现返回指令由RTS变为了RTE了。RTS功能仅仅是将PC从堆栈中取出,而RTE作为异常返回,不仅取出PC,还有SR。原来那个非地址数据是中断前的状态寄存器,恍然大悟。仔细比较了中断前后两个SR,差别仅仅是包含了中断优先级。
    由于做了中断向量声明,所以在进入中断时(使用JSR),保存了PC和SR至堆栈中。但有无__interrupt声明却决定了返回时是作为普通子函数返回,还是中断返回。难道codewarrior编译时已经判断了进入中断,退出中断时还可以有另一种方式?
    我在网上Google了illegal BP,发现所有程序运行异常都可能会提示,包括:中断处理不正确、堆栈溢出、程序跑飞(硬件或者软件导致该问题),所以解决该问题的建议步骤如下:
    1、单步运行追踪问题发生的具体位置;
    2、充分利用编译软件的汇编、存储窗口等功能,追踪程序运行跳转的各个细节;

    知识浅薄,欢迎指正。

 

 

ILLEGAL_BP总结

 

开始以为硬件问题,后来检查后排除了这种可能。于是上论坛看看别人的解决方法,论坛大致有以下几个答案:

 

1.重新下载。

2.在调试过程中非法设置断点。(从名字来看,这个命令应该是报ILLEGAL_BP错误~)

3.堆栈溢出。因为片上资源有限,而如果用到的临时变量太多,会导致片上堆栈溢出。

 

第四种方法,解决了我的问题:

4.程序中中断设置错误。程序中设置了开中断,但是却没有中断处理函数,就会报错。
   解决办法:要么写中断处理函数,要么别开中断。

ILLEGAL_BP总结

 

抱歉!评论已关闭.