热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

RTThread故障定位技术详解与应用

本文深入解析了RTThread操作系统中的HardFault_Handler机制,详细探讨了其在故障定位中的应用与实现方法,为开发者提供了有效的调试工具和策略,有助于提升系统的稳定性和可靠性。

转载:https://blog.csdn.net/suny1234/article/details/89419075

在《RTThread中HardFault_Handler分析》一文中已经分析了RTThread中对于fault中断的处理方法。接下来讲解如何根据错误输出信息对程序出现fault的位置进行定位。

rtthread_simulator_v0.1.0 工程中的main.c中的我们添加以下3行代码

void(*fp)(void) ; //1
int main(void)
{fp = 0; //2fp(); //3return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

编译后按ctrl+5进入软件仿真状态,全速运行后,UART#1窗口输出如下信息

在这里插入图片描述

由此可见运行时候发生了fault,通过《RTThread中HardFault_Handler分析》的内容我们可以知道,输出窗口中打印出来了各个


  • 寄存器的状态

    usage fault:

    psr: 0x60000000
    r00: 0x00000000
    r01: 0x20000000
    r02: 0x00000014
    r03: 0x0000000a
    r04: 0x00000000
    r05: 0xdeadbeef
    r06: 0xdeadbeef
    r07: 0xdeadbeef
    r08: 0xdeadbeef
    r09: 0xdeadbeef
    r10: 0xdeadbeef
    r11: 0xdeadbeef
    r12: 0x00000000
    lr: 0x08000151
    pc: 0x00000000

  • 出错的线程:main

    hard fault on thread: main

  • 具体的错误信息:用法 fault ,状态寄存器(UFSR) 值为 0x02 即视图切换到ARM状态

    usage fault:
    SCB_CFSR_UFSR:0x02 INVSTATE

上述寄存器信息中,lr寄存器中的值为0x08000151 ,此值为进入fault异常中断之前的lr的值。

我们知道lr为连接寄存器里面保存的是调用子程序之前的PC的值。 因为 CM3 内部 使用了指令流水线,读 PC 时返回的值是当前指令的地址+4 ,所以进入异常之前自动加载到lr的值也为调用子程序前的指令地址+4。由于PC的最低位保存ARM/Thumb 运行状态,Cortex-M3只能运行在Thumb 状态,即LSB = 1。所以我们想要找到出错误程序的指令位置, 只需要对打印出来的lr的值减去5即可。

0x08000151 减去5后为0x0800014C 说明我们程序出错位置在PC = 0x0800014C 附近。

在Disassembly窗口下,我们找到0x0800014C 指令位置

在这里插入图片描述

可以看到 0x0800014C 指令位置正好在fp()代码段内。

我们进一步分析产生错误的原因,根据打

用法 fault 状态寄存器(UFSR),地址:0xE000_ED2A

main()函数中我们将函数指针fp的值设为了0,然后去调用fp(),相当于让程序跳转到0地址处去运行。实际上真正出错的地方是0x0800014E处,这里执行了一条BLX 跳转指令,执行完将r0的值0更新到了PC,即PC=0。PC的最低位LSB被更新成了0,试图切换到ARM状态,状态寄存器(UFSR) 中的 INVSTATE 位被置位 ,因此产生了fault。


推荐阅读
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • DNN Community 和 Professional 版本的主要差异
    本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ... [详细]
  • Java 中 Writer flush()方法,示例 ... [详细]
  • 本文将介绍如何使用 Go 语言编写和运行一个简单的“Hello, World!”程序。内容涵盖开发环境配置、代码结构解析及执行步骤。 ... [详细]
  • 火星商店问题:线段树分治与持久化Trie树的应用
    本题涉及编号为1至n的火星商店,每个商店有一个永久商品价值v。操作包括每天在指定商店增加一个新商品,以及查询某段时间内某些商店中所有商品(含永久商品)与给定密码值的最大异或结果。通过线段树分治和持久化Trie树来高效解决此问题。 ... [详细]
  • Java 中的 BigDecimal pow()方法,示例 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • CMake跨平台开发实践
    本文介绍如何使用CMake支持不同平台的代码编译。通过一个简单的示例,我们将展示如何编写CMakeLists.txt以适应Linux和Windows平台,并实现跨平台的函数调用。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 本文详细介绍了IBM DB2数据库在大型应用系统中的应用,强调其卓越的可扩展性和多环境支持能力。文章深入分析了DB2在数据利用性、完整性、安全性和恢复性方面的优势,并提供了优化建议以提升其在不同规模应用程序中的表现。 ... [详细]
  • 使用Numpy实现无外部库依赖的双线性插值图像缩放
    本文介绍如何仅使用Numpy库,通过双线性插值方法实现图像的高效缩放,避免了对OpenCV等图像处理库的依赖。文中详细解释了算法原理,并提供了完整的代码示例。 ... [详细]
  • MQTT技术周报:硬件连接与协议解析
    本周开发笔记重点介绍了在新项目中使用MQTT协议进行硬件连接的技术细节,涵盖其特性、原理及实现步骤。 ... [详细]
author-avatar
小湿基_517
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有