7. AD17N的内核异常管理单元

异常管理单元开启后,会在MCU异常时触发中断,并复位或者打印出异常信息并断言;

1.调用函数 emu_init 后异常开始工作。

2.异常断言

1//内核异常打印,为1时会断言,开发调试时可改为1,量产时必须为0
2const u8 config_asser = 0;

备注

config_asser = 1时,异常触发后断言,并在DEBUG打印控制开启的情况下会打印出异常信息;
config_asser = 0时,异常触发后芯片复位。
** 量产时,请将config_asser = 0,否则死机后不能复位。**

3.异常断言打印

1const char log_tag_const_i_DEBUG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(1);
2const char log_tag_const_d_DEBUG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(1);
3const char log_tag_const_e_DEBUG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(1);
4const char log_tag_const_c_DEBUG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(1);

上面四行代码为异常断言打印信息的开关,默认时开启状态。

7.1. 异常示例(非对齐访问):

config_asser = 1 并开启了断言打印的情况下,触发异常有会有打印信息,以下以非对齐访问为例解释。

非对齐访问是指CPU尝试从非其数据类型自然边界(如4字节数据不从4的倍数地址开始)的内存地址读取或写入数据,这通常会导致硬件异常或性能损失。

 1  <Error> [DEBUG]
 2  -----Err: function:exception_analyze() @line:478
 3
 4  <Error> [DEBUG]_EMU_CON : 0xc000001f
 5  <Error> [DEBUG]_EMU_MSG : 0x1
 6  <Error> [DEBUG]usp  : 0x34524b0
 7  <Error> [DEBUG]ssp  : 0x4a1fbd9b
 8  <Error> [DEBUG]sp   : 0x3f020fc
 9  <Error> [DEBUG]Stack: 0x3f021d0
10  <Error> [DEBUG]rets : 0x400b12e
11  <Error> [DEBUG]reti : 0x400b13e
12  <Error> [DEBUG]rete : 0x0
13  <Error> [DEBUG]psr  : 0x8
14  <Error> [DEBUG]icfg : 0x7010a80
15
16  <Error> [DEBUG]--reti---
17  0x0400B11E
18  FC E1 9F B4 01 E1 30 0D 20 E4 20 D6 FC E1 3F B4
19  A0 4F 20 E4 21 D4 60 E7 10 05 40 D0 A0 6F A0 4F
20  60 E8 4A FE C0 80 FF E1 8F 00 18 80 FF E1 5F 00
21  40 E9 0A 19 21 93 38 81 0A 80 FE E1 AF FE 00 E9
22
23  <Error> [DEBUG]--rets---
24  0x0400B10E
25  61 48 20 E4 20 D9 FC E1 EF B4 A1 48 20 E4 20 D8
26  FC E1 9F B4 01 E1 30 0D 20 E4 20 D6 FC E1 3F B4
27  A0 4F 20 E4 21 D4 60 E7 10 05 40 D0 A0 6F A0 4F
28  60 E8 4A FE C0 80 FF E1 8F 00 18 80 FF E1 5F 00
29
30  <Error> [DEBUG]-- sp ---
31  0x03F020FC
32  3B 22 0B 9C E4 23 F0 03 17 0C 01 04 03 C0 FF FF
33  10 08 EE 03 01 00 00 00 18 25 F0 03 60 24 F0 03
34  00 60 00 00 14 30 ED 03 00 00 00 00 AC 24 F0 03
35  24 47 F0 03 14 03 ED 03 F0 24 F0 03 3E B1 00 04
36  00 00 00 00 2E B1 00 04 08 00 00 00 9B BD 1F 4A
37  80 0A 01 07 B0 24 45 03 D5 33 D1 47 A7 41 D1 64
38  E7 8A 0A 6D AC 24 F0 03 30 11 81 81 00 00 00 00
39  7C C1 00 04 C0 14 F0 03 CC 14 F0 03 00 00 00 00
40  00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00
41  00 00 00 00 62 E3 26 15 2D DB 69 7C 62 E3 26 15
42  04 44 C7 EB 0F 33 57 7B 9F C3 E7 0B 2F 53 77 9B
43  00 00 00 00 00 00 00 00 D8 DE 00 04 FE FF 00 00
44  FB FF 00 00 00 00 00 00 00 10 00 00 00 D0 22 00
45  2C 10 F0 03
46
47  <Error> [DEBUG][0-CPU] emu err msg : misalign_err
48
49  <Error> [DEBUG]r0 = 0x9c0b223b
50  <Error> [DEBUG]r1 = 0x3f023e4
51  <Error> [DEBUG]r2 = 0x4010c17
52  <Error> [DEBUG]r3 = 0xffffc003
53  <Error> [DEBUG]r4 = 0x3ee0810
54  <Error> [DEBUG]r5 = 0x1
55  <Error> [DEBUG]r6 = 0x3f02518
56  <Error> [DEBUG]r7 = 0x3f02460
57  <Error> [DEBUG]r8 = 0x6000
58  <Error> [DEBUG]r9 = 0x3ed3014
59  <Error> [DEBUG]r10 = 0x0
60  <Error> [DEBUG]r11 = 0x3f024ac
61  <Error> [DEBUG]r12 = 0x3f04724
62  <Error> [DEBUG]r13 = 0x3ed0314
63  <Error> [DEBUG]r14 = 0x3f024f0

7.1.1. 第1,2行

1  <Error> [DEBUG]
2  -----Err: function:exception_analyze() @line:478

这两行打印表示进入了异常断言。

7.1.2. 第4,5行

EMU_CON:异常控制寄存器:

bit2 = 1时, 使能除0异常。
bit3 = 1时, 使能堆栈溢出异常。
bit4 = 1时, 使能PC越界异常(程序运行到代码限制范围以外)。
bit30 = 1时,使能CACHE异常。
bit31 = 1时,使能外部异常。
4  <Error> [DEBUG]_EMU_CON : 0xc000001f
5  <Error> [DEBUG]_EMU_MSG : 0x1

EMU_MSG 内核异常信息:

bit0 = 1时, 非对齐访问异常。
bit1 = 1时, 非法指令异常。
bit2 = 1时, 除0异常。
bit3 = 1时, 栈溢出异常。
bit4 = 1时, PC越界异常(程序运行到代码限制范围以外)。
bit30 = 1时,CACHE异常,程序访问到被保护的CACHE区域。
bit31 = 1时,外部异常。

7.1.3. 第6~14行 CPU瞬态

06  <Error> [DEBUG]usp  : 0x34524b0
07  <Error> [DEBUG]ssp  : 0x4a1fbd9b
08  <Error> [DEBUG]sp   : 0x3f020fc
09  <Error> [DEBUG]Stack: 0x3f021d0
10  <Error> [DEBUG]rets : 0x400b12e
11  <Error> [DEBUG]reti : 0x400b13e
12  <Error> [DEBUG]rete : 0x0
13  <Error> [DEBUG]psr  : 0x8
14  <Error> [DEBUG]icfg : 0x7010a80

这几行显示的是一个处理器在异常或中断发生时的关键上下文寄存器。它们共同记录了CPU被打断那一瞬间的状态,是调试异常、崩溃和中断的核心信息。

备注

在分析函数调用关系时,需从汇编层面入手, 因为C语言的函数在编译链接后可能被内联优化 ,导致源码层面的调用链不完整。
从汇编视角解析寄存器记录的逻辑:
1. 当函数 A 调用函数 B 时,进入 B 函数后, rets 寄存器中保存的是 A 函数中“调用指令”的下一条指令地址。此地址是 B 函数执行完毕后需要返回的位置。
2. 若 B 函数在运行过程中触发异常(如非对齐访问),CPU 在跳转至异常中断处理程序后, reti 寄存器中保存的是 B 函数中触发异常的那条指令的下一条指令地址。此地址是异常处理结束后理论上应返回的位置(但通常因错误无法直接返回)。

1.reti (0x400b13e) - 中断/异常返回地址

作用:记录了被中断的程序下一条即将执行的指令地址(PC值)。

分析:当CPU正在执行指令时(或刚执行完上一条),被异常/中断打断。处理完异常后,CPU会跳回这个地址继续执行。

调试价值:这是最重要的寄存器之一。通过反汇编这个地址附近的代码,可以精确知道是哪条指令(或前一条指令)触发了异常。

2.rete (0x400b12e) - 异常返回地址(可能)

作用:在某些架构中用于记录嵌套异常或特定类型异常(如精确的指令异常)的返回地址。值为0可能表示当前是最外层异常,或该寄存器未使用。

分析:如果 reti 和 rets 都存在,rete 有时指向导致异常(如 misalign_err)的那条故障指令本身的地址。

3.rets (0x00112402) - 子程序/状态返回地址

作用:可能记录了发生异常时,当前函数的调用者(父函数)的返回地址(即 LR 链接寄存器的值),或者是CPU在特定模式下的备用返回地址。

分析:0x00112402 这个地址很接近 reti (0x00112434),相差仅 0x32字节。这表明异常很可能发生在某个刚被调用不久的函数内部。结合这两个地址可以画出函数调用链。

4.psr (0x8) - 程序状态寄存器

作用:包含ALU状态标志(如零标志Z、进位C、负数N、溢出V),以及当前处理器模式和中断开关状态。

分析:值为0非常可疑。通常至少会有某些状态位被置位(例如Thumb状态位,在Cortex-M中必须为1)。全0可能意味着:

寄存器被意外清零(内存破坏?)。

异常发生在CPU复位后的最初状态。

这是某个特定模式下的备份PSR,其值在进入异常时被保存到了其他寄存器。

5.sp (0x3f020fc) - 当前堆栈指针

作用:最关键的寄存器之一。这是异常发生瞬间的栈指针值。所有局部变量、函数调用帧都保存在这个地址指向的内存区域。

分析:

它是异常现场的“快照”。

其值(0x1608)位于 ssp(0x2520) 和 usp(0x800) 之间。

5.Stack (0x3f021d0) - 堆栈起始位置(栈底)

这是堆栈开始的位置(最高地址),堆栈由高向低用。

7.1.4. 第16~28行 reti与rets

16  <Error> [DEBUG]--reti---
17  0x0400B11E
18  FC E1 9F B4 01 E1 30 0D 20 E4 20 D6 FC E1 3F B4
19  A0 4F 20 E4 21 D4 60 E7 10 05 40 D0 A0 6F A0 4F
20  60 E8 4A FE C0 80 FF E1 8F 00 18 80 FF E1 5F 00
21  40 E9 0A 19 21 93 38 81 0A 80 FE E1 AF FE 00 E9
22
23  <Error> [DEBUG]--rets---
24  0x0400B10E
25  61 48 20 E4 20 D9 FC E1 EF B4 A1 48 20 E4 20 D8
26  FC E1 9F B4 01 E1 30 0D 20 E4 20 D6 FC E1 3F B4
27  A0 4F 20 E4 21 D4 60 E7 10 05 40 D0 A0 6F A0 4F
28  60 E8 4A FE C0 80 FF E1 8F 00 18 80 FF E1 5F 00

这几行信息是reti与rets所在位置附近的机器码。

第17行,表示reti指向位置附近,地址0x0400B11E开始的机器码。

第24行,表示rets指向位置附近,地址0x0400B10E开始的机器码。

7.1.5. 第30~45行 sp

30  <Error> [DEBUG]-- sp ---
31  0x03F020FC
32  3B 22 0B 9C E4 23 F0 03 17 0C 01 04 03 C0 FF FF
33  10 08 EE 03 01 00 00 00 18 25 F0 03 60 24 F0 03
34  00 60 00 00 14 30 ED 03 00 00 00 00 AC 24 F0 03
35  24 47 F0 03 14 03 ED 03 F0 24 F0 03 3E B1 00 04
36  00 00 00 00 2E B1 00 04 08 00 00 00 9B BD 1F 4A
37  80 0A 01 07 B0 24 45 03 D5 33 D1 47 A7 41 D1 64
38  E7 8A 0A 6D AC 24 F0 03 30 11 81 81 00 00 00 00
39  7C C1 00 04 C0 14 F0 03 CC 14 F0 03 00 00 00 00
40  00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00
41  00 00 00 00 62 E3 26 15 2D DB 69 7C 62 E3 26 15
42  04 44 C7 EB 0F 33 57 7B 9F C3 E7 0B 2F 53 77 9B
43  00 00 00 00 00 00 00 00 D8 DE 00 04 FE FF 00 00
44  FB FF 00 00 00 00 00 00 00 10 00 00 00 D0 22 00
45  2C 10 F0 03

这几行信息是sp所在位置开始的机器码。

第31行,表示sp指向位置开始的机器码,起始地址是0x03F020FC。

7.1.6. 第47行 异常信息种类

47  <Error> [DEBUG][0-CPU] emu err msg : misalign_err

信息显示错误类型, misalign_err 为非对齐访问。

备注

异常信息种类

misalign_err : 为非对齐访问
illeg_err : 非法指令异常
div0_err : 除0异常
stack overflow err : 堆栈溢出异常
pc_limit : PC越界异常(程序运行到代码限制范围以外)
icache excptio : CACHE异常,程序访问到被保护的CACHE区域
sys excption : 外部异常

7.1.7. 第49~63行 通用寄存器信息

49  <Error> [DEBUG]r0 = 0x9c0b223b
50  <Error> [DEBUG]r1 = 0x3f023e4
51  <Error> [DEBUG]r2 = 0x4010c17
52  <Error> [DEBUG]r3 = 0xffffc003
53  <Error> [DEBUG]r4 = 0x3ee0810
54  <Error> [DEBUG]r5 = 0x1
55  <Error> [DEBUG]r6 = 0x3f02518
56  <Error> [DEBUG]r7 = 0x3f02460
57  <Error> [DEBUG]r8 = 0x6000
58  <Error> [DEBUG]r9 = 0x3ed3014
59  <Error> [DEBUG]r10 = 0x0
60  <Error> [DEBUG]r11 = 0x3f024ac
61  <Error> [DEBUG]r12 = 0x3f04724
62  <Error> [DEBUG]r13 = 0x3ed0314
63  <Error> [DEBUG]r14 = 0x3f024f0

这些是发生异常时,CPU通用寄存器在那一刻的“快照”。它们是定位软件错误的最关键线索,相当于程序的“犯罪现场指纹”。


7.2. 外部异常:

在上文中如果是外部系统异常,如下调试信息中的 misalign_err ,将会是 sys excption

47  <Error> [DEBUG][0-CPU] emu err msg : sys excption

外部异常出现时,会有如下打印信息产生。

<Error> [DEBUG] JL_CEMU->MSG0 : 0xXXXXXXX
<Error> [DEBUG] JL_CEMU->MSG1 : 0xXXXXXXX
<Error> [DEBUG] JL_CEMU->MSG2 : 0xXXXXXXX

7.2.1. 示例-AUDIO触发外部异常

以下调试信息为AUDIO触发外部系统异常。

1  <Error> [1-HCORE] hmem err msg: sys access hmem excption
2  <Error> [DEBUG] at dev
3  <Error> [DEBUG] DBG_AUDIO

第3行表示,audio模块异常,

备注

部分异常信息种类

DBG_ALNK
DBG_AUDIO
DBG_APA
DBG_SPI0
DBG_SPI1
DBG_UART0
DBG_UART1
DBG_GPADC
DBG_IIC
DBG_EQ
DBG_SRC

7.2.2. 示例-看门狗WDT触发异常

1  <Error> [2-HSB] emu err msg : watchdog time out