你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

F767板子使用UCOSIII+FPU出现浮点运算错误的问题

[复制链接]
大树树 提问时间:2018-8-23 19:14 /
本帖最后由 大树树 于 2018-8-23 19:18 编辑

项目采用F767芯片,使用了UCOSIII系统,实际运行中出现浮点计算数据异常的问题,后仔细排查发现输入值正常的情况下,计算结果出现了特别大的值。
后来将FPU关闭之后计算数值一切正常。
计算代码示意如下,其他值都正常,结果错的离谱。
  1. traj_PATH_y = q_3*powf(traj_PATH_x,3)  + q_4*powf(traj_PATH_x,4)+  q_5 *powf(traj_PATH_x,5);
  2. traj_PATH_theta = 180.0f/Pi*atanf((traj_PATH_y - traj_PATH_y0)/((traj_PATH_x - traj_PATH_x0)));
复制代码
每次出现错误的地方是随机的,只要是计算的数都有概率会错。
以下是几处配置的地方,不知有没有问题

1、option->target 选项中选择了use single precision
2、c/c++ 的define 中只添加STM32F767xx,USE_HAL_DRIVER
3、stm32f767xx.h中__FPU_PRESENT 设置为1

所有UCOS的任务都加入了OS_OPT_TASK_SAVE_FP选项,任务堆栈也都设置的很大,基本都是1024的。
没有用arm_math.h中的函数,只用了math.h的函数,按理讲应该只影响效率不影响结果的。

实在是搞不定了,在网上搜了好久也没有找到合理的解释。
现在怀疑两个方面的问题:
1、FPU配置的问题,不知道有没有不合适的地方;
2、UCOS运行会不会影响FPU的结果,没有找到相关的解释。

求大神指点,万分感激~~
收藏 评论23 发布时间:2018-8-23 19:14

举报

23个回答
废鱼 回答时间:2018-8-27 10:13:57
楼主的看一下是否增加了.s的代码,我以前用到float时,会发生死机的情况。
; Reset handler
Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  SystemInit
                IMPORT  __main

                                LDR     R0, =SystemInit
                                BLX     R0
                                IF {FPU} != "SoftVFP"
                                                                                                ; Enable Floating Point Support at reset for FPU
                                LDR.W   R0, =0xE000ED88         ; Load address of CPACR register
                                LDR     R1, [R0]                ; Read value at CPACR
                                ORR     R1,  R1, #(0xF <<20)    ; Set bits 20-23 to enable CP10 and CP11 coprocessors
                                ; Write back the modified CPACR value
                                STR     R1, [R0]                ; Wait for store to complete
                                DSB

                                                                                                ; Disable automatic FP register content
                                                                                                ; Disable lazy context switch
                                LDR.W   R0, =0xE000EF34         ; Load address to FPCCR register
                                LDR     R1, [R0]
                                AND     R1,  R1, #(0x3FFFFFFF)  ; Clear the LSPEN and ASPEN bits
                                STR     R1, [R0]
                                ISB                             ; Reset pipeline now the FPU is enabled
                                ENDIF

                                LDR     R0, =__main
                                BX      R0
                                ENDP

评分

参与人数 2ST金币 +2 蝴蝶豆 +3 收起 理由
小黑111 + 2 感谢层主,试了有用,不死机了.
zero99 + 3

查看全部评分

小黑111 回答时间:2018-9-14 23:14:17
这个问题我在半年前遇到过,我的临时解决方法是所有的浮点数全部替换成整型处理了。
我认为这个问题的根本原因OS_CPU_A.ASM这个文件的问题,现在网上所有的这个文件都是用的cortex-m4的,
这个文件包含多个函数用于任务切换,其中包括多个与浮点数寄存器堆栈有关的函数,它只支持single precision,显然stm32f767(cortex-m4)的double precision是不兼容的。

这个文件本应该是官方发布(可惜一直没发),由于本人水平有限,不懂汇编,还请高人参照数据手册实现函数,为民造福

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

大树树 回答时间:2018-8-24 07:58:09
要是F7方式FPU简直是太丢人了,求帮助
馒头弟 回答时间:2018-8-24 09:27:25
本帖最后由 馒头弟 于 2018-8-24 09:28 编辑
大树树 发表于 2018-8-24 07:58
要是F7方式FPU简直是太丢人了,求帮助

有没有可能被其他任务打断了。我上次遇到的更奇怪,keil中跑裸机,使用const u16 Val = 64;时这个Val居然会变化。。。然后改成#define Val 64 就没问题,也搞不懂。。而且,上下文定义的const常量,有的变了有的没变。。

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

wolfgang 回答时间:2018-8-24 11:20:59
确定计算结果是单精度?

评分

参与人数 1蝴蝶豆 +1 收起 理由
zero99 + 1

查看全部评分

大树树 回答时间:2018-8-24 13:21:28
馒头弟 发表于 2018-8-24 09:27
有没有可能被其他任务打断了。我上次遇到的更奇怪,keil中跑裸机,使用const u16 Val = 64;时这个Val居然 ...

被打断也有可能,可加了OS_OPT_TASK_SAVE_FP选项不是应该可以保存浮点寄存器值的么,难道这还需要加临界区?
大树树 回答时间:2018-8-24 13:23:22
wolfgang2015 发表于 2018-8-24 11:20
确定计算结果是单精度?

输出结果的变量定义的是float,运算中就算有double,结果也应该是把超出精度部分舍去不是么
大树树 回答时间:2018-8-25 09:45:12
馒头弟 发表于 2018-8-24 09:27
有没有可能被其他任务打断了。我上次遇到的更奇怪,keil中跑裸机,使用const u16 Val = 64;时这个Val居然 ...

昨天调试发现计算的时候关中断就不出错了。
但按道理讲创建任务时候加了OS_OPT_TASK_SAVE_FP选项的,可结果来看好像浮点寄存器出入栈的时候出了问题。
不懂还有什么地方有问题的。
大树树 回答时间:2018-8-27 09:29:29
别沉啊,高手来讨论一下
党国特派员 回答时间:2018-8-27 10:39:01
在任务初始化(OSTaskStkInit)的时候,跟一下。看浮点寄存器有没有入栈。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

馒头弟 回答时间:2018-8-27 16:41:59
大树树 发表于 2018-8-25 09:45
昨天调试发现计算的时候关中断就不出错了。
但按道理讲创建任务时候加了OS_OPT_TASK_SAVE_FP选项的,可结 ...

计算耗时多少啊,关中断计算完再开→_→
大树树 回答时间:2018-8-27 19:58:46
安 发表于 2018-8-27 10:13
楼主的看一下是否增加了.s的代码,我以前用到float时,会发生死机的情况。
; Reset handler
Reset_Handler  ...

这个我看了下是有的,目前没有因为计算死机,就是数据会错误
大树树 回答时间:2018-8-27 19:59:26
党国特派员 发表于 2018-8-27 10:39
在任务初始化(OSTaskStkInit)的时候,跟一下。看浮点寄存器有没有入栈。

好的,我试试看,谢谢
STM1024 回答时间:2018-8-27 21:03:41
有没有可能是你的计算步骤太长了,例如
q_3*powf(traj_PATH_x,3)  + q_4*powf(traj_PATH_x,4)+  q_5 *powf(traj_PATH_x,5);
只算powf的时候就被中断打断了然后切换到了其他地方?
相当于你的操作不是原子性的……?但是理论上来说,及时打断了也能恢复,但是被打断的时候,寄存器是否有被中断函数覆写?

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

大树树 回答时间:2018-8-28 07:44:59
stm1024 发表于 2018-8-27 21:03
有没有可能是你的计算步骤太长了,例如
q_3*powf(traj_PATH_x,3)  + q_4*powf(traj_PATH_x,4)+  q_5 *powf( ...

UCOS按正常来讲应该会将浮点寄存器的值入栈的,但感觉上没有正常入栈导致的问题。
12下一页

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版