- I. 异常现象
- II. 解密异常
- III. 主动调试
- IV. 异常记录
- Undefined HWI 20
- Decoded : Hard Fault:FORCED:BUSFAULT:PERECISERR.Data Access Error.ADdress =0xc27101fa
- Hard Fault:FORCED:BUSFAULT:IMPRECISERR
- Decoded : Hard Fault: FORCED:BUSAULT:PRECISERR.Data Access Error.Address =0x20005000
- Decoded :Hard Fault:FORCED:BUSFAULT:PERECISERR.Data Access Error.Address =0xa0760000
- Decoded :Hard Fault:FORCED:BUSFAULT:PERECISERR.Data Access Error.Address =0xbebebebe
- 程序停在0x1001c482
- Decoded : Hard Fault: FORCED:BUSFAULT:IMPRECISERR
- 程序直接停在了0x1001b986
ti-rtos 异常解密
详细介绍基于ti-rtos高级调试组件rov用以cc1310/cc2640 等sdk异常主动调试。
I. 异常现象
正常的,程序会进入IDLE模式,程序会停留在(0x10001486),也就是IDLE模式;
通常的,在我们完成我们程序功能时候,不可避免会遇到程序运行至一个死循环。如下图所示:
这个时候,我们要考虑程序异常了。
II. 解密异常
提示:更多可以参考如下。
swcu117d-CC13xx, CC26xx SimpleLink Wireless MCU Technical Reference Manual.pdf
swru393c-CC2640 and CC2650 SimpleLink Bluetoothlow energy Software Stack 2.2.0.pdf
->Chapter 9.8 Deciphering CPU Exceptions Page.157
- http://docs.leconiot.com/cc2640r2f/debugging
导致异常的原因可以在 View->Registers CFSR寄存器的CPU_SCS 组中确定。最常见的异常有以下几个原因:
- 栈溢出;
- NULL 空指针被写操作应用;
- 外设模块在没有供电的情况下操作;
对于任务栈溢出,我们可以通过TI-RTOS->Task->Detailed
分析任务栈使用情况。但是IAR这里报错了。
ROV detected errors in scan of 'Detailed' tab for module ti.sysbios.knl.Task.
通过TI-RTOS->BIOS->scan for errors...
不难看出这里有个任务异常了,有两个任务堆栈溢出了。
通过 TI-RTOS->Task->Basic 确定这两个任务为优先级7和3。
也就是程序中的
UartTaskCreate(3);
Task_Handle radioHandle = RadioTaskCreate(7);
我们尝试将这两个任务的任务堆栈给增加;
再次通过TI-RTOS->Task->Detailed
查看任务细节,我们能够清楚分析每个任务的堆栈使用情况,同时可以通过以此来优化任务堆栈,多退少补。
符号 | 意义 |
---|---|
address | 任务Handle 地址; |
lable | 任务标号,用以区分任务 |
priority | 任务优先级 |
mode | 任务当前运行状态 blocked阻塞,通过后面blockOn 对应阻塞于哪个事件、信号等; |
fxn | 任务运行函数 |
arg0 | 任务函数参数0 |
arg1 | 任务函数参数1 |
stackpeck | peak(山峰,最高点),这里stackpeak 表示当前任务堆栈的最大使用情况,可以依据该值对任务堆栈 stacksize进行优化,多退少补,已达到最佳优化效果。 |
stackSize | 程序分配的任务堆栈大小 |
stacBase | 任务堆栈的基地址、首地址 |
curCoreId | |
affinity | affinity-密切关系,姻亲关系 The core which this task is to run on. Default is Task_AFFINITY_NONE |
blockedOn | 同block 对应,表示当前任务阻塞状态下的阻塞事件。 |
III. 主动调试
借助IAR CSPY和CCS ROV控件 这里尝试调试这些异常,我们在Main函数完成实现以下代码,不难发现这里直接对NULL指针进行操作,那么程序发生什么现象呢?,IDE又会告诉我们什么信息呢?
int * a=NULL;
*a =100;
TI_ROS->Hwi->Exception
从上面的ROV 信息显示来看,在Main函数里发生了IMPRECISERR异常错误,而该错误正是我们的NULL指针被操作以前的。
IV. 异常记录
Undefined HWI 20
10/4/2016 10:27:39 AM
今天发现Undefined HWI 20 是由于任务数量超过4引起的。
- 尝试更改系统堆栈
define symbol __ICFEDIT_size_cstack__ = 0x1000;
define symbol __ICFEDIT_size_heap__ = 0x1000;
- 尝试更改cfg 有关于number的配置参数,其中包括
/*
* Reduce the number of swi priorities from the default of 16.
* Decreasing the number of swi priorities yields memory savings.
*/
Swi.numPriorities = 16;
终于确定现象了,但是还需要进一步分析具体原因,我们得先从RAM的存储结构说起
.bss zero 0x20003eda 0x1 TxWorkerTask.o [1]
.bss zero 0x20003edb 0x1 driverlib_release.o [7]
- 0x20003edc 0x3234
"A4": 0x1000
CSTACK 0x20004000 0x1000 <Block>
CSTACK uninit 0x20004000 0x1000 <Block tail>
- 0x20005000 0x1000
以上是编译后存储map文件。大概结构图如下:
RAM | 备注 |
---|---|
固定地址 | 用以存放固定地址的变量 |
data | 已初始化的变量 |
bss | 未初始化变量 |
未知区域 | 就是这个未知的大小引起程序跑飞 |
castak | 栈空间大小 |
在以上图示的未知区域,前面是程序中变量大小决定,后面CStack栈空间大小是有编译器配置。但是现在看来中间必须保留一个余量用以其他用途,否则这里会出现运行时程序异常。从IAR的存储空间来观察,这里用以一个 “??PageIndex”
尝试将以上未知区域尽可能放大,上电发现这部分占用 0x200040BC-0x20004300=578 也就是我们RAM占用不能超过 20*1024-578=19902 实际测试这部分在
46 187 bytes of readonly code memory
8 002 bytes of readonly data memory
19 605 bytes of readwrite data memory
46 187 bytes of readonly code memory
8 004 bytes of readonly data memory
19 613 bytes of readwrite data memory
空闲在20480-19605 =875
从IAR上面来看,这里是存放一部分代码,具体功能暂时还不知道。
10/4/2016 7:01:45 PM
又要新发现,凡是HWI类型异常可以通过IAR TI-RTOS->Hwi->Detailed确定当前激活的中断;
Decoded : Hard Fault:FORCED:BUSFAULT:PERECISERR.Data Access Error.ADdress =0xc27101fa
10/4/2016 7:20:36 PM
Hard Fault:FORCED:BUSFAULT:PERECISERR.Data Access Error.ADdress =0xc27101fa
threadType:Hwi
threadHandle:unkonwn
激活中断为
Hard Fault:FORCED:BUSFAULT:IMPRECISERR
12/22/2016 3:13:20 PM
ThreadType 为Task
ThreadStack 表示异常任务的基地址,对应
Decoded : Hard Fault: FORCED:BUSAULT:PRECISERR.Data Access Error.Address =0x20005000
12/23/2016 4:40:58 PM
Decoded : Hard Fault: FORCED: BUSAULT:PRECISERR.Data Access Error.Address =0x20005000
threadType:Task
threadHandle:0x20003ae0
确定为Scif_task.c,然后通过断点确定在SPI 打开的时候异常。
//SPI_open - CY15B104Q_Init in CY15B104Q.c (g:\mycode\...\board) Line 156
spiHandler=SPI_open(Board_SPI0,&spiParams);
这里基本已经知道优化内存的时候把SPI相关变量spiCC26XXDMAHWAttrs
和SPI_config
在CC1310DK_7XD
给注释掉了,以为用不上SPI。但是我再确定是否还能够从TI-RTOS ROV组件获取更多信息。
Decoded :Hard Fault:FORCED:BUSFAULT:PERECISERR.Data Access Error.Address =0xa0760000
1/3/2017 10:11:42 AM
threadType : swi
threadStack: 0x20002f4c
threadStateSize : 0xc04
最后确定这里是数组操作越界
Decoded :Hard Fault:FORCED:BUSFAULT:PERECISERR.Data Access Error.Address =0xbebebebe
threadType : Task
threadStack: 0x20003c30
threadStateSize : 0x300
今天又有新发现,异常的时候可以通过PC指针确定异常代码的位置,比如该错误,通过TI-RTOS->hwi->Exception 我们能够知道 当前PC指针值;
R0 : 0xbebebebe
PC : 0x1001c5f8
分析这个位置代码:
xdc_runtime_Core_assignParams__I:
0x1001c5ec: 0xe92d 0x43f8 PUSH.W {R3-R9, LR}
0x1001c5f0: 0x4604 MOV R4, R0
0x1001c5f2: 0xf8d1 0x800c LDR.W R8, [R1, #0xc]
0x1001c5f6: 0x6808 LDR R0, [R1]
0x1001c5f8: 0xf8d8 0x6000 LDR.W R6, [R8]
0x1001c5fc: 0x461d MOV R5, R3
0x1001c5fe: 0x4617 MOV R7, R2
0x1001c600: 0xeba7 0x0905 SUB.W R9, R7, R5
0x1001c604: 0x464a MOV R2, R9
0x1001c606: 0x1b80 SUBS R0, R0, R6
0x1001c608: 0x4282 CMP R2, R0
我们不难猜出,这里在对一个参数进行校验,而此时的R0寄存器值正好为我们的异常地址值0xbebebebe
。因为以上汇编代码为ROM空间代码,所以我们怎么通过他定位到出错位置的我们应用层代码呢?
我们再通过TI-RTOS->hwi->Exception SP
指针分析出错前的压栈值;
SP : 0x20002528
0x200024c8: 0x00003ff0 DC32 0x3ff0 (16368)
0x200024cc: 0x0000ca17 DC32 0xca17 (51735)
0x200024d0: 0x1001a02a DC32 0x1001a02a (268541994)
0x200024d4: 0x21000000 DC32 0x21000000 (553648128)
0x200024d8: 0x200028c8 DC32 0x200028c8 (536881352)
0x200024dc: 0x200028c8 DC32 0x200028c8 (536881352)
0x200024e0: 0x00000000 DC32 0x0 (0)
0x200024e4: 0x00000000 DC32 0x0 (0)
0x200024e8: 0xe000e000 DC32 0xe000e000 (-536813568)
0x200024ec: 0x0000000d DC32 0xd (13)
0x200024f0: 0x20003fd4 DC32 hwiTaskAlert
0x200024f4: 0x20002530 DC32 0x20002530 (536880432)
0x200024f8: 0x00000000 DC32 0x0 (0)
0x200024fc: 0x1001a43f DC32 0x1001a43f (268543039)
0x20002500: 0x00000000 DC32 0x0 (0)
0x20002504: 0x0000001d DC32 0x1d (29)
0x20002508: 0x0000bb19 DC32 osalTaskAlertIsr
0x2000250c: 0x20002530 DC32 0x20002530 (536880432)
0x20002510: 0x00000008 DC32 0x8 (8)
0x20002514: 0xfffffffd DC32 0xfffffffd (-3)
0x20002518: 0x20002598 DC32 0x20002598 (536880536)
0x2000251c: 0x00001270 DC32 ti_sysbios_knl_Clock_Object__DESC__C
0x20002520: 0x00000000 DC32 0x0 (0)
0x20002524: 0x200025d0 DC32 0x200025d0 (536880592)
0x20002528: 0xbebebebe DC32 0xbebebebe (-1094795586)
0x2000252c: 0xffffffff DC32 0xffffffff (-1)
因为栈是向下生长型,我们分析栈历史录,发现这里进行了一次ti_sysbios_knl_Clock_Object__DESC__C 函数压栈。结合刚刚更改代码增加了对语音数据发送超时,已经能够大概知道出错位置,但是我们再次尝试深入挖掘。
最后确定为构造始终的时候Clock_construct
,这里传入了一个NULL指针,其中clockObj 为0;
Clock_construct(Clock_struct(clockObj), ClockCBFxn, SC_VOICE_TX_TIMEOUT, &clockParams);
程序停在0x1001c482
从死循环位置的最近的标号来看是在创建什么资源。
从TI-RTOS->HeapMem->Detailed
来看,可能存在堆分配溢出。
1/2/2017 12:07:57 PM
Concentrator再次出现改情况,可以断定的是,Concentrator在连续收到Node的语音程序后进入该异常。
Decoded : Hard Fault: FORCED:BUSFAULT:IMPRECISERR
12/25/2016 4:28:03 PM
threadType : Swi
htreadHandle : 0x20000914
通过对应TI-RTOS->Task->Detailed
分析整个程序运行的逻辑,定位到UartTask被Create了两次。
12/26/2016 3:47:52 PM
threadType : Hwi
threadHandle : 0x20030c0
对于Hwi错误,可以通过 TI-RTOS->Hwi->Detailed
找到以上threadHandle 对应的中断服务程序;
static void ScifCtrlReadyCallback(void) {
Event_post(scifTaskEnv.hEvnt, EVT_TASK_SIGNAL | EVT_SCIF_CTRL_READY);
}
程序直接停在了0x1001b986
10/18/2017 4:26:26 PM
日了狗了,程序直接停在了这里。
Target memory read failed at address: 0x20002b9c, length: 76
This read is at an INVALID address according to the application's section map. The application is likely either uninitialized or corrupt.
通过Rov->Hwi->Exception 居然扫描不出来错误,最后通过排除法大概确定是IO冲突,怀疑是操作了一个被初始化成串口的TX的IO进行Input 读操作,或者是把串口的TX重新初始化成了输入。
还不快抢沙发