主题中讨论的其他部件:SEGGER, HALCOGEN
问题:
我遇到了一个奇怪的问题,即在分支指令上发生数据中止。
设置:
我有
- Hercules LaunchPad TMS570LC43X通过微型USB电缆连接到我的笔记本电脑。
- 我有一个Segger JLink连接到JTAG端口并连接到我的笔记本电脑。
- 我已使用HALCoGen生成一些针对GCC工具链的驱动程序代码
流程:
我的简单引导加载程序在闪存中启动,并使用HALCoGen启动代码设置寄存器,堆栈,MPU,高速缓存,然后跳转到我的引导加载程序的主要功能。 它可以打印到UART精细。 驱动程序似乎工作正常,并且编译正确。
我设置了断点,以便在跳转到RTOS (在RAM中)之前,我可以通过JTAG加载RTOS,然后继续。 这似乎正常。 我可以跳转到RAM中的正确地址,并逐步执行指令,然后观察寄存器加载了它们应该加载的内容。
症状:
我在RTOS启动代码中找到以下点:
─────────────────────────────────────────────────────────── registers ────
$r0 : 0x8000268 → 0xe0411000 → 0xe0411000
$r1 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r2 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r3 : 0x8011c60 → 0x000000 → 0xea0018e6 → 0xea0018e6
$r4 : 0x200003df → 0x200003df
$r5 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r6 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r7 : 0x80002d5 → 0x70b508f6 → 0x70b508f6
$r8 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r9 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r10 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r11 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r12 : 0x000000 → 0xea0018e6 → 0xea0018e6
$sp : 0x8011c60 → 0x000000 → 0xea0018e6 → 0xea0018e6
$lr : 0x8000278 → 0xe59f004c → 0xe59f004c
$pc : 0x8000274 → 0xe12fff17 → 0xe12fff17
$cpsr: [negative zero carry overflow INTERRUPT FAST thumb]
─────────────────────────────────────────────────────────────── stack ────
0x8011c60│+0x0000: 0x000000 → 0xea0018e6 → 0xea0018e6 ← $r3, $sp
0x8011c64│+0x0004: 0x000000 → 0xea0018e6 → 0xea0018e6
0x8011c68│+0x0008: 0x000000 → 0xea0018e6 → 0xea0018e6
0x8011c6c│+0x000c: 0x000000 → 0xea0018e6 → 0xea0018e6
0x8011c70│+0x0010: 0x000000 → 0xea0018e6 → 0xea0018e6
0x8011c74│+0x0014: 0x000000 → 0xea0018e6 → 0xea0018e6
0x8011c78│+0x0018: 0x000000 → 0xea0018e6 → 0xea0018e6
0x8011c7c│+0x001c: 0x000000 → 0xea0018e6 → 0xea0018e6
──────────────────────────────────────────────────────── code:arm:ARM ────
0x8000268 <bsp_start_vector_table_end+296> sub r1, r1, r0
0x800026c <bsp_start_vector_table_end+300> ldr r7, [pc, #84] ; 0x80002c8 <bsp_start_hook_0_done+80>
0x8000270 <bsp_start_vector_table_end+304> add r7, r7, r1
→ 0x8000274 <bsp_start_vector_table_end+308> bx r7
0x8000278 <bsp_start_hook_0_done+0> ldr r0, [pc, #76] ; 0x80002cc <bsp_start_hook_0_done+84>
0x800027c <bsp_start_hook_0_done+4> ldr r1, [pc, #76] ; 0x80002d0 <bsp_start_hook_0_done+88>
0x8000280 <bsp_start_hook_0_done+8> cmp r0, r1
0x8000284 <bsp_start_hook_0_done+12> beq 0x8000298 <bsp_start_hook_0_done+32>
0x8000288 <bsp_start_hook_0_done+16> ldm r1!, {r2, r3, r4, r5, r6, r7, r8, r9}
─────────────────────────────────── source:../../../bsps/a[...].S+476 ────
471 ldr r1, =.Lget_absolute_pc
472 .Lget_absolute_pc:
473 sub r1, r0
474 ldr r7, =bsp_start_hook_0
475 add r7, r1
→ 476 bx r7
477
478 /* Allow bsp_start_hook_0() hooks to jump to this label */
479 bsp_start_hook_0_done:
480
481 /*
───────────────────────────────────────────────────────────── threads ────
[#0] Id 1, stopped 0x8000274 in bsp_start_vector_table_end (), reason: SINGLE STEP
─────────────────────────────────────────────────────────────── trace ────
[#0] 0x8000274 → bsp_start_vector_table_end()
这是一个GDB视图,其GEF可视化显示在单个视图中显示寄存器,源代码和反汇编代码。
如果您查看“代码”部分,下一个指令将转到“r7”中包含的地址。 "r7"寄存器包含地址0x8.0002万d5。
但是,使用GDB命令"ni"(下一个指令)可以转到abort处理程序:
─────────────────────────────────────────────────────────── registers ────
$r0 : 0xfff7e400 → 0x000000 → 0xea0018e6 → 0xea0018e6
$r1 : 0x01c200 → 0xffffd9ff → 0x000000 → 0xea0018e6 → 0xea0018e6
$r2 : 0x00e898 → ; <UNDEFINED> instruction: 0xffffffff
$r3 : 0x3000032 → 0x3000032
$r4 : 0xfff7e400 → 0x000000 → 0xea0018e6 → 0xea0018e6
$r5 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r6 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r7 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r8 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r9 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r10 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r11 : 0x000000 → 0xea0018e6 → 0xea0018e6
$r12 : 0x000000 → 0xea0018e6 → 0xea0018e6
$sp : 0x8001400 → 0x33018333 → 0x33018333
$lr : 0x003608 → 0xa00000f → 0xa00000f
$pc : 0x000010 → 0xeafffffe → 0xeafffffe
$cpsr: [NEGATIVE zero carry overflow INTERRUPT FAST thumb]
─────────────────────────────────────────────────────────────── stack ────
0x8001400│+0x0000: 0x33018333 → 0x33018333 ← $sp
0x8001404│+0x0004: 0x62266c33 → 0x62266c33
0x8001408│+0x0008: 0x62636bb3 → 0x62636bb3
0x800140c│+0x000c: 0x681b62a3 → 0x000000 → 0xea0018e6 → 0xea0018e6
0x8001410│+0x0010: 0xb94f2001 → 0xb94f2001
0x8001414│+0x0014: 0xe7b64641 → 0xe7b64641
0x8001418│+0x0018: 0x4620f7ff → 0x4620f7ff
0x800141c│+0x001c: 0xfc112001 → 0x000000 → 0xea0018e6 → 0xea0018e6
──────────────────────────────────────────────────────── code:arm:ARM ────
0x4 <undefEntry+0> b 0x4
0x8 <svcEntry+0> b 0x8
0xc <prefetchEntry+0> b 0xc
●→ 0x10 <dataEntry+0> b 0x10
0x14 <dataEntry+4> b 0xdb8 <phantomInterrupt>
0x18 <dataEntry+8> ldr pc, [pc, #-432] ; 0xfffffe70
0x1c <dataEntry+12> ldr pc, [pc, #-432] ; 0xfffffe74
0x20 <deregister_tm_clones+0> ldr r0, [pc, #24] ; 0x40 <deregister_tm_clones+32>
0x24 <deregister_tm_clones+4> ldr r3, [pc, #24] ; 0x44 <deregister_tm_clones+36>
───────────────────────────────────────────────────────────── threads ────
[#0] Id 1, stopped 0x10 in dataEntry (), reason: BREAKPOINT
─────────────────────────────────────────────────────────────── trace ────
[#0] 0x10 → dataEntry()
[#1] 0x3608 → sciSetBaudrate(sci=0xfff7e400, baud=0x1c200)
──────────────────────────────────────────────────────────────────────────
如您所见,我现在正在处理数据中止处理程序。
另一个有趣的提示是Segger GDB服务器报告:
Reading 64 bytes @ address 0x08001400 WARNING: Failed to read memory @ address 0x62266C32 WARNING: Failed to read memory @ address 0x62266C32 Reading 64 bytes @ address 0x62266C00 WARNING: Failed to read memory @ address 0x62266C00 WARNING: Failed to read memory @ address 0x62266C32 Received monitor command: cp15 6 0 0 0 Reading CP15 register (6,0,0,0 = 0x62266C32) Received monitor command: cp15 5 0 0 0 Reading CP15 register (5,0,0,0 = 0x00001008)
如您所见,它报告的地址甚至不在同一区域,它位于异步RAM部分,而我在RAM部分执行。
我觉得这种情况在分行发生,而不是在货物或商店发生,这是很奇怪的。 它每次都发生在同一个地方。
调查:
我发现一些数据中止调试文章和论坛帖子,并尝试尽可能多地遵循这些要点。
- 数据故障状态寄存器(DFSR)
- 值:0x0.1008万
- 状态[10,3:0]:0b1000
- 来源:同步外部中止
- 远期有效期:有效
- SD [12]: 0x01
- 仅对外部中止有效,即
- 1= AXI从属错误(SLVERR)或不支持的独占访问(例如使用AHB外围端口的独占访问)导致中止
- RW [11]:
- 0:读取访问导致中止
- 数据故障地址寄存器(DFAR)
- 值:0x6.2266万C32
- 这真的很奇怪,因为这是Segger GDB服务器中报告的内容,但我没有代码! 我不在那里分支,我永远看不出该地址何时在我的堆栈或寄存器中。 它来自哪里?
- 辅助数据故障状态寄存器(ADFSR)
- 值:0x0万
- CacheWay [27:24]
- 值:
- 说明:此字段中返回的值表示发生错误的缓存方式。
- 侧面[23:22]
- 值:
- 说明:此字段中返回的值表示错误的来源。
- 可恢复的错误[21]
- 值:
- 说明:此字段中返回的值表示错误是否可恢复。
- 解码:0=不可恢复的错误。
- SideExt [20]:
- 值:0b0
- 说明:此字段中返回的值表示错误的来源。 有关编码,请参见表4-32。
- 已解码:
- 与Side一起,这表示错误的来源是"Cache/Axim "
- CPSR
- 值:0x80.0003万d7
- t [5]:0
- 不在拇指模式下
- m [4:0]:0b1.0111万:
- 模式:中止模式
- SPSR_ABT
- 值:0x80.0003万df
- T[5]:0
- 不在拇指模式下
- M[4:0]:0b1.1111万
- 模式:系统模式
- CPSR和SPSR_abt告诉我,我正在从常规特权代码执行直接转到中止处理程序。
相关的MPU区域主要是从HALCoGen生成的代码中产生的,但是,我将RAM区域更改为可执行:
static const mpu_region_t tms570lc43x_mpu_regions[NUM_MPU_REGIONS] = {
{
.enabled = true,
.region_number = 0,
.start_address = 0x0,
.size = MPU_4_GB,
.type = MPU_NORMAL_OINC_NONSHARED,
.permissions = MPU_PRIV_NA_USER_NA_NOEXEC,
.disabled_sub_regions = 0xFF,
},
{
// FLASH
.enabled = true,
.region_number = 1,
.start_address = FLASH_START,
.size = MPU_4_MB,
.type = MPU_NORMAL_OIWTNOWA_NONSHARED,
.permissions = MPU_PRIV_RO_USER_RO_EXEC,
},
{
// RAM
.enabled = true,
.region_number = 2,
.start_address = RAM_START,
.size = MPU_512_KB,
.type = MPU_NORMAL_OIWTNOWA_NONSHARED,
.permissions = MPU_PRIV_RW_USER_RW_EXEC,
},
// ..... other non-relevant regions
};
我覆盖HALCoGen代码中的弱MPU初始化函数,并迭代此数组,以相同的方式设置区域。 我已使用JTAG和cp15指令来验证是否按照此处指定的方式设置了区域。
我还可以使用GDB "examy"命令查看和反汇编最初位于"r7"中的地址的代码。 所以我觉得这不是与访问内存或代码不存在相关的问题。 我被骗了。 我感觉处理器缺少一些配置,但我也找不到与数据中止和分支相关的任何信息。
欢迎使用任何提示。