打印

指定地址跳转后 B指令导致hard fault

[复制链接]
4653|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
bigfacecat|  楼主 | 2009-11-4 09:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
由于特殊用途,我程序分成了两片区域
区域1:0x8000000~
区域2:0x8050000~

区域1,写了一个函数指针,直接指定地址0x8050000跳转后
0x8050000是一条B指令跳到一个函数
但是该B指令一执行就导致hard fault
个人感觉原理上没有问题
请高手们帮忙分析下
沙发
香水城| | 2009-11-4 10:00 | 只看该作者
请确认那条B指令确实烧写到指定的地址,而且跳转到的函数也确实烧写到指定的地址。

用单步调试看看。

使用特权

评论回复
板凳
vigia| | 2009-11-4 10:03 | 只看该作者
跳转到0x8050000之前要先把堆栈设好。

使用特权

评论回复
地板
bigfacecat|  楼主 | 2009-11-4 10:04 | 只看该作者
本帖最后由 bigfacecat 于 2009-11-4 10:14 编辑

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

使用特权

评论回复
5
bigfacecat|  楼主 | 2009-11-4 10:06 | 只看该作者
3# vigia

麻烦说的仔细点,需要怎么设置堆栈
因为我觉得堆栈空间没有变化的,不需要设置吧?

使用特权

评论回复
6
bigfacecat|  楼主 | 2009-11-4 10:09 | 只看该作者
感觉其实只是程序空间跨度大了点
和正常的函数调用应该是一样的吧
不知道差在哪里了

使用特权

评论回复
7
bigfacecat|  楼主 | 2009-11-4 10:16 | 只看该作者
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……

使用特权

评论回复
8
vigia| | 2009-11-4 10:18 | 只看该作者
执行B之前,看看core寄存器,有异常吗?

使用特权

评论回复
9
bigfacecat|  楼主 | 2009-11-4 10:21 | 只看该作者
core寄存器?
LR是正常的
其他也没有发现什么异常
我这些代码原来在ARM7下都是正常跳转的
但是移到ST cortex-M3的核就不行了

使用特权

评论回复
10
vigia| | 2009-11-4 10:54 | 只看该作者
跳转之前的代码有没有开什么中断?

把memory fault, bus fault和usage fault都打开,看看是什么造成的hard fault

使用特权

评论回复
11
bigfacecat|  楼主 | 2009-11-4 11:08 | 只看该作者
没有开中断
memory fault, bus fault和usage fault这些应该都没关
我没有配置过这些中断
反正就是会产生hard fault中断

使用特权

评论回复
12
vigia| | 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"); /* 开中断 */

使用特权

评论回复
13
bigfacecat|  楼主 | 2009-11-4 11:38 | 只看该作者
int (*func)(void *);


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

        return func(p);
我加了一句关中断,可是跳到0x8005000之后,B指令的执行结果还是hard fault

使用特权

评论回复
14
bigfacecat|  楼主 | 2009-11-4 11:49 | 只看该作者
我又试了下
把0x8050000的B指令改成了几个NOP
结果执行第一个NOP时发生了hard fault
现象是一样的
也就是说和0x8050000放的指令没有关系

也许是其他的什么东西不对

使用特权

评论回复
15
bigfacecat|  楼主 | 2009-11-4 11:54 | 只看该作者
我在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

使用特权

评论回复
16
vigia| | 2009-11-4 16:20 | 只看该作者
没有开中断
memory fault, bus fault和usage fault这些应该都没关
我没有配置过这些中断
反正就是会产生hard fault中断
bigfacecat 发表于 2009-11-4 11:08


memory, bus和usage这些fault如果你没有配置,那么一旦产生了这些fault,都会掉到hard fault里面去。所以我让你把这些fault都开启了,然后就可以看到,到底是什么fault。

如果没有其他中断,仅仅执行NOP都会导致fault,应该还是内核寄存器里有什么异常了。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
bigfacecat + 1
17
bigfacecat|  楼主 | 2009-11-4 19:47 | 只看该作者
我已经找到原因了
只要把所有跳转的地址+1即可
因为cortex 用的thumb2指令要求所有对PC的地址赋值最低位要为1

使用特权

评论回复
18
desert_hawk| | 2009-11-4 20:10 | 只看该作者
声明一下 void API_FUNC_TABLE(void *);
然后  func = API_FUNC_TABLE;
        func(p);
就行了。这样编译器会自己处理+1的问题,直接跳转是会有你所说的现象,有时容易让人摸不着头脑。

使用特权

评论回复
19
bigfacecat|  楼主 | 2009-11-4 20:44 | 只看该作者
18# desert_hawk

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

但是现在我是要用绝对地址对PC赋值

使用特权

评论回复
20
desert_hawk| | 2009-11-4 21:23 | 只看该作者
为什么一定要用绝对地址对PC赋值呢?
其实函数名就是一个地址,你在汇编里已经写了API_FUNC_TABLE,在C里完全可以当函数名用的,而且这个函数的地址就是0x8005000.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

46

帖子

0

粉丝