设备平台:Xilinx Zynq 7010s
架构:Arm Cortex-A9
嵌入式操作系统:FreeRTOS
现象:只要在程序中(不管是中断还是普通线程)执行浮点数操作(乘除),另一个线程里面的 TCP/IP 协议栈缓存区数据就会中等概率被破坏。
使用的平台有双精度 FPU ,并且在 g++ 里面已经启用,尝试修改 g++ 关于 FPU 的编译参数,无效。
1
CEBBCAT 2022-03-07 16:43:59 +08:00
嗯……换个板子呢?
|
2
villivateur OP @CEBBCAT 一样的
|
3
3dwelcome 2022-03-07 16:50:29 +08:00 via Android
编译成 wasm 运行一下呢,应该没问题。
|
4
3dwelcome 2022-03-07 17:01:07 +08:00
忘了说,这里的 wasm 是指编译成后端微服务模式,不是浏览器里的模式。
就是在普通操作系统里可运行,类似于 arm 版本服务器的虚拟机模式来运行。 |
5
duke807 2022-03-07 17:08:46 +08:00 via Android
這種問題要靠自己慢慢查,多解決幾次,你才能成為高手
嵌入式不建議用 c++,查底層問題比較麻煩 你先對比一下 開與不開 硬浮點的現象是否相同。 |
6
yehoshua 2022-03-07 17:15:35 +08:00 via Android
嵌入式…很多时候出问题和你的板子 /平台有关系,特别是这种固定大概率出现的问题。
|
7
villivateur OP @duke807 很遗憾,我这个 FreeRTOS 平台没法关闭硬 FPU ,但我试过 -mfloat-abi=softfp 和 -mfloat-abi=hard 都不行
|
8
shyrock 2022-03-07 17:21:01 +08:00
当初放弃 C++的一个原因就是觉得内存管理太浪费精力。
一般来说这种高复现率的问题我会推荐用代码屏蔽大法,先屏蔽 50%,看看能不能复现,不能则再屏蔽剩下的 50%,最后你就会发现破坏内存编辑的操作是哪个。 |
9
geekzjj 2022-03-07 17:22:21 +08:00 via Android 1
同样的平台,不同的系统,以前遇到过差不多一样的坑。。当时规避的方式的方法是,做浮点的时候禁用一切引起上下文切换的操作,包括禁中断😂
|
10
villivateur OP @shyrock 已经用了这个方案了,最后定位到是浮点数运算的问题
|
11
Hconk 2022-03-07 17:34:50 +08:00 1
这个问题和你遇到的情况有没有关系,https://support.xilinx.com/s/article/71079?language=en_US
|
12
shyrock 2022-03-07 17:36:00 +08:00
@villivateur #10 到了这一步,可以找到被破坏的堆栈地址,单步执行看看浮点运算前后这个地址的数据有什么变化。。。
|
13
3dwelcome 2022-03-07 17:37:31 +08:00
@geekzjj 真有那么神奇吗?是不是驱动设计存在问题。
以前 dx 开发时,也遇到过需要设置_controlfp FPU 的地方,gcc 里是 control87 ,但最多是浮点计算错误,并不会把给内存给打乱。 如果内存乱,不是堆栈渗出,就是数学库的问题(比如 int64 计算都是需要额外库的,也许没考虑多线程)。 真灵异事件还是少见。话说 gcc 是真难用,clang 从各方面秒杀。 |
14
3dwelcome 2022-03-07 17:43:23 +08:00 5
“Some GCC libraries optimise memory copy and memory set (and possibly other) functions by making use of the wide floating point registers. Therefore, by default, any task that uses functions such as memcpy(), memcmp() or memset(), or uses a FreeRTOS API function such as xQueueSend() which itself uses memcpy(), will inadvertently corrupt the floating point registers.”
还真是 GCC 的锅。。。 |
15
Hconk 2022-03-07 17:43:33 +08:00 1
|
16
ciichen 2022-03-07 19:39:26 +08:00 via Android
是不是正在计算浮点数的时候,刚好发生了 systick 线程切换,但是线程切换过程中,没有保存 /恢复浮点寄存器?
可以在浮点数运算中,停掉所有中断再看看有没有问题。 |
17
polaa 2022-03-07 19:51:13 +08:00
这种不是应该上 gdb 动态调试么
|
18
joshu 2022-03-07 20:06:35 +08:00
如果不考虑浮点数,我一般怀疑的方向有两个
内存访问越界,破坏了栈结构 在多线程上利用了 x86 上理所当然的 store-store 有序特性来做一些同步的操作,但 arm 上面我印象中 store-store 的执行并不是必然严格有序的(但单线程上保证结果正确) |
19
geekzjj 2022-03-07 20:38:34 +08:00 via Android
@3dwelcome 我遇到的也是在 zynq 上,不过是另一个比较少见的实时操作系统。问题是浮点计算结果概率性为 0 ,也不知道是“打乱内存”,还是计算错误导致的。。
|
20
vance123 2022-03-07 22:02:51 +08:00
用过一个板子,调用 sprintf 就会清除内存,最后手写了一个 sprintf ,垃圾嵌入式
|
21
LANB0 2022-03-08 15:14:00 +08:00
之前碰到过类似问题,64 位平台 tx1 设备上,某一特定位置,只要一操作指针类型转换就崩溃,前面加条 printf 打印就正常。后来排查是内存非对齐访问触发了对齐异常
|
22
kingcanfish 2022-03-08 16:15:05 +08:00
@shyrock 经典二分了属于是
|