硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1494|回复: 10
收起左侧

程序调用子函数前都做了什么?

[复制链接]

98

主题

340

回帖

634

积分

金牌会员

积分
634
发表于 2020-5-18 18:01:47 | 显示全部楼层 |阅读模式
LWIP运行一段时间后总是进Hard_Fault中断,通过记录发现每次都是在调用一个内核子函数时产生的异常。就是下面这个函数msg->msg.apimsg->function(&(msg->msg.apimsg->msg)),
刚开始怀疑是传入的参数是个非法地址,于是又在这个函数前加了个函数来判断输入参数的正确性,如果不正确就直接返回了,如下:
CheackAddFun(&(msg->msg.apimsg->msg))。
但是测试发现还会出现Hard_Fault中断,中断前的地址又到了执行CheackAddFun这个函数这里。
于是猜测原因不是输入参数异常,而是调用子函数这一个动作产生的异常。
通过反汇编发现在调用子函数前程序执行了以下3条指令,每次都是在执行第3条指令的时候出现的异常。
请教硬汉哥,调用子函数前这三步指令究竟是什么意思,什么原因会让它恰好在执行第3条指令时会死机呢?
LDR  r1[sp,#0x00]
LDR  r1[r1,#0x08]
LDR  r0[r1,#0x00]   //执行这条指令的时候进入Hard_Fault
BL.W  CheackAddFun
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106726
QQ
发表于 2020-5-18 18:13:40 | 显示全部楼层
hardfault的错误类型是什么。
回复

使用道具 举报

98

主题

340

回帖

634

积分

金牌会员

积分
634
 楼主| 发表于 2020-5-18 18:52:15 | 显示全部楼层
eric2013 发表于 2020-5-18 18:13
hardfault的错误类型是什么。

总线错误,以下是错误时的各错误寄存器的值。仿真发现那3行代码好像是保存子函数的返回地址。
QQ截图20200518184827.bmp

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106726
QQ
发表于 2020-5-18 19:24:02 | 显示全部楼层
云琴箫龙 发表于 2020-5-18 18:52
总线错误,以下是错误时的各错误寄存器的值。仿真发现那3行代码好像是保存子函数的返回地址。

寄存器的看着有点不直观,

有MDK下的hardfault report图不
回复

使用道具 举报

98

主题

340

回帖

634

积分

金牌会员

积分
634
 楼主| 发表于 2020-5-18 21:17:01 | 显示全部楼层
eric2013 发表于 2020-5-18 19:24
寄存器的看着有点不直观,

有MDK下的hardfault report图不

没有那个report图,因为这个故障要联网运行好几天甚至十几天才有可能出现,所以没有带着仿真器。
但每次总是卡在同一个位置,让我觉得离真相已经很近了。
回复

使用道具 举报

98

主题

340

回帖

634

积分

金牌会员

积分
634
 楼主| 发表于 2020-5-18 21:58:59 | 显示全部楼层
eric2013 发表于 2020-5-18 19:24
寄存器的看着有点不直观,

有MDK下的hardfault report图不

对比权威指南里面,发生置位的标志位是总线错误寄存器中的PRECISERR,这个中文权威指南中的解释是“在数据访问期间的总线错误。通过 BFAR 可以获取具体的地址。发生 fault 的原因同上”,这里面的同上是指的是IMPRECISERR,它的解释是“与设备传送数据的过程中发生总线错误。可能因为设备未经初始化而引起;在用户级访问了特权级的设备,或者传送的数据单位尺寸不能为设备所接受。此时,有可能是 LDM/STM 指令造成了非精确总线 fault。”上面说可以通过BFAR获得总线错误时的具体地址,这个BFAR的值每次都是0x41B00000,这个数看着好熟悉,全局搜索一看竟然是个浮点寄存器的值,这个寄存器在创建任务时被压栈。
LWIP协议栈实际使用中虽存在删除和再创建任务的操作,但是跟LWIP相关的任务在创建的时候选项OS_OPT_TASK_SAVE_FP都没有开,也就是不会保存浮点寄存器的值。所以这点儿有个困惑。
根据对以上3行汇编代码的仿真分析,似乎是在调用子函数前,先把子函数返回地址存储到任务堆栈里面,然后再调用子函数。


回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106726
QQ
发表于 2020-5-18 22:11:40 | 显示全部楼层
云琴箫龙 发表于 2020-5-18 21:17
没有那个report图,因为这个故障要联网运行好几天甚至十几天才有可能出现,所以没有带着仿真器。
但每次 ...

把Ozone挂上就行了。

SEGGER的Ozone调试组件新增的快照功能,超级实用,解决随机性死机的利器
http://www.armbbs.cn/forum.php?m ... 4967&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106726
QQ
发表于 2020-5-18 22:16:36 | 显示全部楼层
云琴箫龙 发表于 2020-5-18 21:58
对比权威指南里面,发生置位的标志位是总线错误寄存器中的PRECISERR,这个中文权威指南中的解释是“在数 ...

这么分析就有点辛苦了。
回复

使用道具 举报

98

主题

340

回帖

634

积分

金牌会员

积分
634
 楼主| 发表于 2020-5-19 08:50:30 | 显示全部楼层
eric2013 发表于 2020-5-18 22:11
把Ozone挂上就行了。

SEGGER的Ozone调试组件新增的快照功能,超级实用,解决随机性死机的利器

Ozone内存刷新速度太慢,怕已经死机了内存还没来得及刷新。
且带了十台设备,出问题的设备很随机,得需要10台电脑同时连接长期运行,也没这个条件。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106726
QQ
发表于 2020-5-19 12:01:20 | 显示全部楼层
云琴箫龙 发表于 2020-5-19 08:50
Ozone内存刷新速度太慢,怕已经死机了内存还没来得及刷新。
且带了十台设备,出问题的设备很随机,得需 ...

刷新慢是你下载问题。
回复

使用道具 举报

210

主题

1043

回帖

1683

积分

至尊会员

More we do, more we can do.

积分
1683
发表于 2020-5-28 08:54:35 | 显示全部楼层
函数调用的过程ARM官方文档叫:Procedure Call Standard for the Arm
如参数传入用:R0-R3,返回用R0-R1,局部变量用R4-R8等。

针对楼主遇到的问题,猜测是该函数频繁被调用,低概率出问题吗?
建议先不要怀疑编译器,我估计可能是越界。你对参数值有效性做预判限制,记录非正常情况。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-2 11:37 , Processed in 0.215806 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表