函数指针调用与Thumb代码的问题

在验证一个RAM中执行函数时,遇到了MCU进入Hardfault错误的问题。

代码载入内存地址0x20003000之后,使用函数指针的方式跳转:

typedef int (*func_call)(int, char **);

void call_ram_func(void)
{
    uint32_t *fun_base;
    func_call func;
    int argc = 2;
    char *argv[] = {""};
    
    fun_base = (uint32_t*)0x20003080;
    func = (func_call)(fun_base);
    func(argc,argv);
}

上述代码在汇编级单步调试的时候,运行正常,一旦全速运行后,程序只要执行到func(argc,argv)就会进入Hardfault。最后在一步一步分析汇编的时候,发现跳转的地址0x20003080有端倪,联想到Thumb指令集与ARM指令集的区别时才恍然大悟,指令LSB即最低有效位为0时是ARM指令,为1时是Thumb代码,这里0x20003080显然被识别为ARM指令了,而整个程序使用Thumb指令集编译的,执行这条指令之前,MCU也一直处于Thumb状态,突然执行一条ARM指令所以出现了错误。明白了问题,解决办法很简单,代码按照以下方式修正:

typedef int (*func_call)(int, char **);

void call_ram_func(void)
{
    uint32_t *fun_base;
    func_call func;
    int argc = 2;
    char *argv[] = {""};
    
    fun_base = (uint32_t*)(0x20003080 + 0x1);
    func = (func_call)(fun_base);
    func(argc,argv);
}

将调用地址最低位置为1,跳转的地址就变成了Thumb指令了,再次运行一切恢复正常。

至于汇编级调试时正常,全速跑时却出现Hardfault异常的问题,有前辈解释是由于单步调试时调试器会对指令进行修正,所以错误的指令会被修正,全速运行时,没有调试器的参与,MCU就异常了。
具体可参见https://bbs.21ic.com/icview-134389-999-1.html的讨论。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值