IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32F4使用ucosii时操作浮点数卡死的问题 -> 正文阅读

[嵌入式]STM32F4使用ucosii时操作浮点数卡死的问题

一、BUG

? 之前使用STM32F401的单片机移植了ucosii操作系统后。在编写任务函数时,在循环中调用sprintf函数时莫名卡死。后来,查找bug后发现在操作浮点数时会莫名卡死,换成printf函数也是一样。最后得出一个结论:只要在任务主循环中使用浮点数就会出现卡死的bug。

二、解决方案

2.1方案一、字节对齐(M3)

? 遇到这个bug之后,第一时间去百度了。后来在网上找到了这篇文章 UCOS-II之字节对齐问题。虽然文章里面说的是M3的,但是试过之后也是一样,没有办法消除BUG。这个方法对M4没用,但对M3有用,如果M3移植ucosii遇到这种问题可以使用文章中更改字节对齐的办法。具体细节网上有很多,可以自行百度。

可以参考这个博客:https://blog.csdn.net/weixin_43548213/article/details/90449336

2.2方案二、暴力解决

?

在Floating Point Hardware的选项选择Not Used

  • 当选择Not Used之后,编译器对浮点的处理用的是普通的MOV指令和Rn的寄存器来处理浮点数(R开头的据寄存器是内核的寄存器),选择这个是强行用CPU算。

    image-20211204170613935

  • 如果选择Single Precision,编译器对浮点的处理会使用V指令和FPU浮点寄存器(S),由于OS未设置和操作FPU的浮点寄存器(没有在上下文切换的时候保存FPU寄存器),所以在运行OS时STM32进入硬件错误中断(HardFault_Handle)。但是在裸机的时候也使用了FPU寄存器来处理浮点数,并没有任何错误。

    解决办法就是方案三,使用FPU。

    image-20211204170217933

2.3方案三、FPU

? 方案三的办法是开启F4的FPU,如果不知道什么是FPU,可以自行百度。FPU简介-CSDN博客转载

可以参考这篇博客-STM32F4之FPU设置

使能OS_CPU_ARM_FP_EN这个宏

//在os_cpu.h中
#ifndef  __TARGET_FPU_SOFTVFP
#define  OS_CPU_ARM_FP_EN                              DEF_ENABLED
#else
#define  OS_CPU_ARM_FP_EN                              DEF_DISABLED
#endif

C/C++的define里面,定义DEF_ENABLED=1,定义__TARGET_FPU_VFP,定义__FPU_PRESENT=1,定义__CC_ARM

image-20211205164745622

操作成功后如下图:

**这时候发现system_stm32f4xx.c的函数SystmInit里的421行条件编译判断成功(如果还是暗的意味着上面的步骤做错),此时FPU打开成功。**如下图:

在stm32F4的startup… .s启动文件中,找到Reset_Handler函数

添加如下代码:

;图中不够标准,用下面的汇编代码
IF {FPU} != "SoftVFP"
LDR R0,=0xE000ED88 ;使能FPU CP10 CP11
LDR R1,[R0]
ORR R1,R1,#(0XF << 20)
STR R1,[R0]
DSB
				
LDR.W R0,=0xE000EF34
LDR R1,[R0]
AND R1,R1,#(0x3FFFFFFF)
STR R1,[R0]
ISB
ENDIF

最后

任务使用FPU方法:

如果任务需要处理浮点数,在任务切换时需要保存该任务的浮点寄存器。所以调用OSTaskCreateExt接口来创建任务。
该接口的最后一个参数opt是用来选择是否保存浮点寄存器,有3个可选宏:
OS_TASK_OPT_STK_CHK:允许对该任务进行堆栈检查
OS_TASK_OPT_STK_CLR : 创建任务时清除堆栈
OS_TASK_OPT_SAVE_FP : 如果CPU有浮点寄存器,保存它们在上下文切换期间。

在创建只需要选择OS_TASK_OPT_SAVE_FP即可,OS就会对该任务保存浮点寄存器:

OSTaskCreateExt(StartTask,
                    (void*)0,
                    &start_task_stk[START_TASK_STK_SIZE-1],
                    START_TASK_PRIO,
                    0,
                    &start_task_stk[0],
                    sizeof(start_task_stk),
                    (void*)0,
                    OS_TASK_OPT_SAVE_FP|OS_TASK_OPT_STK_CHK //选OS_TASK_OPT_SAVE_FP
                    );

void  OSTaskSwHook (void) //处理浮点寄存器的函数,os_cpu_c.c
{

#if (OS_CPU_ARM_FP_EN > 0u)
    if ((OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
        OS_CPU_FP_Reg_Push(OSTCBCur->OSTCBStkPtr); //该函数在os_cpu_a.asm定义
    }

    if ((OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
        OS_CPU_FP_Reg_Pop(OSTCBHighRdy->OSTCBStkPtr);//该函数在os_cpu_a.asm定义
    }
#endif

#if OS_APP_HOOKS_EN > 0u
    App_TaskSwHook();
#endif
}

测试:在任务函数中定义一个浮点数后,在for(;;)里使用浮点数变量,如float a; a++;

参考网站:

网站一

网站二

如果还是不能解决,请在评论区留言。

t.none-task-blog-baidujs_title-1&spm=1001.2101.3001.4242)

网站二

如果还是不能解决,请在评论区留言。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-12-06 15:25:34  更:2021-12-06 15:25:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 12:12:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码