Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
CmBacktrace
RT-Thread一般讨论
rt-thread 工具讲解系列(一) 之 CmBacktrace 分析
发布于 2021-09-06 09:02:03 浏览:5097
订阅该版
[tocm] ## 前言 首先,我们贴一下 CmBacktrace 宣称的主要特性: + 支持的错误包括: - 断言(assert) - 故障(Hard Fault, Memory Management Fault, Bus Fault, Usage Fault, Debug Fault) + 故障原因自动诊断:可在故障发生时,自动分析出故障的原因,定位发生故障的代码位置,而无需再手动分析繁杂的故障寄存器; + 输出错误现场的函数调用栈(需配合 addr2line 工具进行精确定位):还原发生错误时的现场信息,定位问题代码位置、逻辑更加快捷、精准。也可以在正常状态下使用该库,获取当前的函数调用栈; 以及,官方提供的两种测试: 1. 除零。 2. 内存不对齐,转整型指针。 在此基础上,我想添加几种其它情况的测试。以检验一下官方宣称的特性支持程度有多少。 1. 除零。 2. 内存不对齐,转整型指针。 3. 空指针 4. 未初始化的野指针 5. 数组索引溢出 6. 硬件引起的问题 ### 准备工作 首先,按照官方的说明添加,配置 CmBacktrace 。 然后,我的建议,将如下代码添加到 `rt_cm_backtrace_init` 函数。 ``` SCB->CCR |= SCB_CCR_DIV_0_TRP_Msk; /* bit4: DIV_0_TRP. */ SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; /* bit3: UNALIGN_TRP. */ ``` > 如有必要,cmb_port.c 中添加 board.h 头文件包含。 ### 1.除零 先从官方提供的样例程序开始: ``` int x, y, z; x = 10; y = rt_strlen(""); z = x / y; rt_kprintf("z:%d\n", z); ``` 毫无悬念的,这段代码执行到 `z = x / y;` 触发了 HardFault_Handler 。调试终端打印出来了函数调用堆栈信息。通过 `addr2line -e rtthread.axf -a -f xxxxxxxx` 轻松定位到出错函数,以及对应汇编地址。 修改一下代码: ``` z = x * 1.0 / y; ``` 或 ``` float x; int y, z; z = x * 1.0 / y; ``` > 但凡,这条除法语句中有一个浮点型数,包括常量和变量。**除零异常失灵了!!!** 虽然,带浮点型的除法运算,最后的结果是 0 ,不出现硬件异常,程序还能继续跑,但是这种非预期结果并不是我们想要的。 关于这一点儿我持保留态度,为什么整型的除零和浮点型除零不一样?有清楚原因的,请留言告知,先谢谢了。 ### 2.内存不对齐 ``` volatile int * p; volatile int value; p = (int *) 0x03; value = *p; ``` 毫无悬念的,这里是一个非对齐访问异常。进一步修改访问地址如下。 ``` p = (int *) 0xc0000000; value = *p; p = (int *) 0xc0000000-4; value = *p; p = (int *) 0x08000000; value = *p; p = (int *) 0x08000000-8; value = *p; p = (int *) 0x08000003; value = *p; ``` 0xc0000000 是外接 SDRAM 的起始地址。通过测试,可以知道,非法内存地址(0xc0000000-4),非法 flash 地址(0x08000000-8、0x08000003)都可以引起“Bus fault”。 ### 3.空指针 ``` volatile int *p = NULL; *p = 1; rt_kprintf("null ptr: %x %d\n", p, *p); ``` “写 0 地址”在 stm32f429 上是可以的,只是,这个写操作*不会引起任何修改!* ### 4.未初始化的野指针 鉴于以上几种情况的分析,*未初始化的野指针* 无非是以上几种情况的组合。或者出现不对齐访问错误,或者出现总线错误,或者是像空指针一样没有任何影响。 还有一种是,指针刚好指向了有效内存,同时,指向了很重要的内存(比如 0xC0000004,我的堆内存,)。 ``` volatile int *p = 0xC0000008; *p = 1; rt_kprintf("null ptr: %x %d\n", p, *p); ``` 这样会破坏堆结构,这种情况不知道什么时候会暴露出来问题,并不一定是写内存的时候被 CmBacktrace 发觉到。 ### 5.数组索引溢出 如果栈生长方向是从高地址向低地址,那么数组下溢访问的是未申请到的栈内存,上溢访问的是已经被申请了的,不可被破坏的栈内存。 如果数组是堆上申请的指针,无论上溢还是下溢,多数情况下都是有用的内存数据。除非申请这个数组之后没有申请内存行为。 无论是哪种情况,CmBacktrace 也并不能在非法写动作进行时“发觉”到任何异常。 ### 6.硬件问题 如果是硬件问题,程序代码中没有任何不正规操作,但是,一样会触发 `HardFault_Handler` 但是 CmBacktrace 也并不能提供给我们任何有效的信息跟踪排查故障所在。 例如,你能从下面这个调用栈信息里告诉我问题的根源在哪儿吗?(下面继续) ``` arm-none-eabi-addr2line -e xxx.axf -a -f c02708be 080327a2 08026412 0801ce2c 0801a78e 0802b3a2 0802b346 0802b12a 0802b1a6 08037dda 080212c4 08028f66 08029a28 0801e102 0801d28c 08015182 0xc02708be ?? ??:0 0x080327a2 _FillRect ../clib/../cmprslib/lz77c.c:? 0x08026412 LCD_FillRect ../clib/../cmprslib/lz77c.c:? 0x0801ce2c GUI_Clear ../clib/../cmprslib/lz77c.c:? 0x0801a78e FRAMEWIN__cbClient ../clib/../cmprslib/lz77c.c:? 0x0802b3a2 WM__SendMessageNoPara ../clib/../cmprslib/lz77c.c:? 0x0802b346 WM__SendMessage ../clib/../cmprslib/lz77c.c:? 0x0802b12a WM__Paint1 ../clib/../cmprslib/lz77c.c:? 0x0802b1a6 WM__PaintWinAndOverlays ../clib/../cmprslib/lz77c.c:? 0x08037dda _cbPaintMemDev ../clib/../cmprslib/lz77c.c:? 0x080212c4 GUI_MEMDEV_Draw ../clib/../cmprslib/lz77c.c:? 0x08028f66 WM_Exec ../clib/../cmprslib/lz77c.c:? 0x08029a28 WM_InvalidateRect ../clib/../cmprslib/lz77c.c:? 0x0801e102 GUI_Exec ../clib/../cmprslib/lz77c.c:? 0x0801d28c GUI_Delay ../clib/../cmprslib/lz77c.c:? 0x08015182 GUIDEMO_Delay D:\xxx\GUIDemo\/GUIDEMO.c:770 ``` 或者,你敢拍着胸脯说,下面的问题根源是 `GUI_GIF__DrawFromFilePointer` 函数实现有什么野指针;又或者说,在下面的函数调用栈上的某个函数引起的 blabla ... ``` arm-none-eabi-addr2line -e xxx.axf -a -f 0801e9e4 0803367a 0802ab28 0802bc2c 0801e40c 0802bc2c 0801e370 08016c44 0801d572 08016b12 08016bce 080154da 08015764 080093c8 080093d6 0800b7ae 0x0801e9e4 GUI_GIF__DrawFromFilePointer ../clib/../cmprslib/lz77c.c:? 0x0803367a _GetDataBlock ../clib/../cmprslib/lz77c.c:? 0x0802ab28 WM__GetNextIVR ../clib/../cmprslib/lz77c.c:? 0x0802bc2c _ClearUnusedPixels ../clib/../cmprslib/lz77c.c:? 0x0801e40c GUI_GIF_DrawSubEx ../clib/../cmprslib/lz77c.c:? 0x0802bc2c _ClearUnusedPixels ../clib/../cmprslib/lz77c.c:? 0x0801e370 GUI_GIF_DrawSub ../clib/../cmprslib/lz77c.c:? 0x08016c44 _ShowGIF D:\xxx/application\GUIDemo\/GUIDEMO_Bitmap.c:4829 0x0801d572 GUI_DispStringInRect ../clib/../cmprslib/lz77c.c:? 0x08016b12 _DrawScreen_BMP_GIF_JPG D:\xxx/application\GUIDemo\/GUIDEMO_Bitmap.c:5097 0x08016bce GUIDEMO_Bitmap D:\xxx/application\GUIDemo\/GUIDEMO_Bitmap.c:5191 0x080154da _Main D:\xxx/application\GUIDemo\/GUIDEMO.c:673 0x08015764 GUIDEMO_Main D:\xxx/application\GUIDemo\/GUIDEMO.c:1120 0x080093c8 rt_components_init D:\xxx/rt-thread\src\components.c:125 0x080093d6 main_thread_entry D:\xxx/rt-thread\src\components.c:190 0x0800b7ae _thread_exit ``` 这种硬件引起的,问题暴露点往往也是固定的,但是 CmBacktrace 指引我们往一个错误的方向走去。 ## 总结 经过这次梳理,可以发现 CmBacktrace 帮我们能定位的问题好像很有限。多数我们最可能遇到的情况,它都无能为力了。 PS: 以上测试部分代码仅限于我使用的芯片上,换其它芯片可能地址不一样。 相关文章: [rt-thread 工具讲解系列(一) 之 CmBacktrace](https://club.rt-thread.org/ask/article/3019.html) [rt-thread 工具讲解系列(二) 之 如何排查系统 bug](https://club.rt-thread.org/ask/article/3027.html) [rt-thread 工具讲解系列(三) 之 env scons 命令初探](https://club.rt-thread.org/ask/article/3036.html)
13
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
出出啊
恃人不如自恃,人之为己者不如己之自为也
文章
43
回答
1516
被采纳
342
关注TA
发私信
相关文章
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
ART-Pi
FinSH
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
ESP8266
I2C_IIC
WIZnet_W5500
ota在线升级
UART
cubemx
PWM
flash
packages_软件包
freemodbus
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
出出啊
1516
个答案
342
次被采纳
小小李sunny
1440
个答案
289
次被采纳
张世争
799
个答案
171
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
1
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
4
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部