指定地址跳转后B指令导致hardfault

speclcd   2009-11-4 09:47 楼主
由于特殊用途,我程序分成了两片区域
区域1:0x8000000~
区域2:0x8050000~

区域1,写了一个函数指针,直接指定地址0x8050000跳转后
0x8050000是一条B指令跳到一个函数
但是该B指令一执行就导致hard fault
个人感觉原理上没有问题
请高手们帮忙分析下

回复评论 (22)

请确认那条B指令确实烧写到指定的地址,而且跳转到的函数也确实烧写到指定的地址。

用单步调试看看。
点赞  2009-11-4 10:00
                                 跳转到0x8050000之前要先把堆栈设好。
点赞  2009-11-4 10:03


这个我是可以确定的,就是用的汇编单步调试
我如果直接把PC置为0x8050000,他就能够正常跳转
但是如果从区域1里头程序运行过来,就会fault
PC到0x8050000时还是正常的,再单步一下就fault了
点赞  2009-11-4 10:04


麻烦说的仔细点,需要怎么设置堆栈
因为我觉得堆栈空间没有变化的,不需要设置吧?
点赞  2009-11-4 10:06
感觉其实只是程序空间跨度大了点
和正常的函数调用应该是一样的吧
不知道差在哪里了
点赞  2009-11-4 10:09
0x8050000:
00 f0 1c b8 df f8 2c f0 df f8 2c f0 df f8 28 f0 df f8 24 f0 df f8 20 f0 df f8 1c f0 df f8 18 f0 df f8 14 f0 df f8 10 f0 df f8 0c f0 df f8 08 f0……
点赞  2009-11-4 10:16
                                 执行B之前,看看core寄存器,有异常吗?
点赞  2009-11-4 10:18
core寄存器?
LR是正常的
其他也没有发现什么异常
我这些代码原来在ARM7下都是正常跳转的
但是移到ST cortex-M3的核就不行了
点赞  2009-11-4 10:21
跳转之前的代码有没有开什么中断?

把memory fault, bus fault和usage fault都打开,看看是什么造成的hard fault
点赞  2009-11-4 10:54
没有开中断
memory fault, bus fault和usage fault这些应该都没关
我没有配置过这些中断
反正就是会产生hard fault中断
点赞  2009-11-4 11:08
一般这样的跳转,我这样写:

typedef void (*pFunction)(void);
long EntryAddress;
pFunction vEntry;
EntryAddress = *(vu32*) (0x08050004); /* 这里这么写是因为后面放的是一个完整的应用程序,包括中断向量表,所以在04的位置是应用程序的复位地址 */
vEntry = (pFunction) EntryAddress;
__MSR_MSP(*(vu32*) (0x08050000);  /* 在00的位置就是堆栈地址了 */ 
asm("CPSID I");  /* 关中断 */
vEntry ();  
/*******************************/

在后面的函数中再
asm("CPSIE I"); /* 开中断 */
点赞  2009-11-4 11:08
int (*func)(void *);


        func = (int (*)(void *))0x8005000;
       
        asm("CPSID I");  /* 关中断 */

        return func(p);
我加了一句关中断,可是跳到0x8005000之后,B指令的执行结果还是hard fault
点赞  2009-11-4 11:38
我又试了下
把0x8050000的B指令改成了几个NOP
结果执行第一个NOP时发生了hard fault
现象是一样的
也就是说和0x8050000放的指令没有关系

也许是其他的什么东西不对
点赞  2009-11-4 11:49
我在0x8050000地址放的是以下代码:

    MODULE  C_API

    ASEG
    ORG (0x8000000+0x40000+0x10000);定义该段绝对地址,也是模块调用API的跳转表起始地址
   
    EXPORT API_FUNC_TABLE
API_FUNC_TABLE        ;
        ;start (API_FUNC_TABLE)
        IMPORT        ClearScreen       
        NOP
        NOP
        NOP
        B  ClearScreen
点赞  2009-11-4 11:54
没有开中断
memory fault, bus fault和usage fault这些应该都没关
我没有配置过这些中断
反正就是会产生hard fault中断
memory, bus和usage这些fault如果你没有配置,那么一旦产生了这些fault,都会掉到hard fault里面去。所以我让你把这些fault都开启了,然后就可以看到,到底是什么fault。

如果没有其他中断,仅仅执行NOP都会导致fault,应该还是内核寄存器里有什么异常了。
点赞  2009-11-4 16:20
声明一下 void API_FUNC_TABLE(void *);
然后  func = API_FUNC_TABLE;
        func(p);
就行了。这样编译器会自己处理+1的问题,直接跳转是会有你所说的现象,有时容易让人摸不着头脑。
点赞  2009-11-4 20:10


如果是函数标号对PC赋值没有这个问题

但是现在我是要用绝对地址对PC赋值
点赞  2009-11-4 20:44
为什么一定要用绝对地址对PC赋值呢?
其实函数名就是一个地址,你在汇编里已经写了API_FUNC_TABLE,在C里完全可以当函数名用的,而且这个函数的地址就是0x8005000.
点赞  2009-11-4 21:23
因为我文件是用汇编写的,是从ARM7移植过来的
所以没有转为C的形式
点赞  2009-11-4 21:35
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复