This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS570LC4357:分支上的数据中止

Guru**** 2466550 points
Other Parts Discussed in Thread: SEGGER, HALCOGEN

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1101092/tms570lc4357-data-abort-on-branch

部件号:TMS570LC4357
主题中讨论的其他部件:SEGGERHALCOGEN

问题:

我遇到了一个奇怪的问题,即在分支指令上发生数据中止。

设置:

我有

  • 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"中的地址的代码。 所以我觉得这不是与访问内存或代码不存在相关的问题。 我被骗了。 我感觉处理器缺少一些配置,但我也找不到与数据中止和分支相关的任何信息。

欢迎使用任何提示。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    RTOS是否是一个单独的应用程序映像,其中包括设备/时钟/外设初始化以及它自己的中断向量,链接器cmd文件? 如果将RTOS应用程序编程为0x0万,它是否可以正确启动?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    数据4357数据故障地址寄存器(DFAR)
    • 值:0x6.2266万C32
    • 这真的很奇怪,因为这是Segger GDB服务器中报告的内容,但我没有代码! 我不在那里分支,我永远看不出该地址何时在我的堆栈或寄存器中。
    [/引述]

    堆栈视图*after *显示数据中止确实显示 0x6.2266万c33,其唯一不同之处是设置了最低有效位:

    ─────────────────────────────────────────────────────────────── 堆栈────
    0x800.14万│+0x0000:0x3301.8333万→0x3301.8333万←$sp
    0x800.1404万│+0x0004:0x6.2266万c33→0x6.2266万c33

    我不确定GDB视图和 GEF可视化是否在某种程度上取消引用指针,因为指针正在触发导致中止的读取。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    和切斯特,我必须承认,整个问题是我本人在情报方面失误的原因。

    我在GDB中使用下一个指令命令,而不是在该分支上使用步骤。 但是,当我让程序继续运行时,它仍然无法打印,这是因为串行驱动程序没有正确设置波特。

    ,你的建议让我从0x0万启动,我在同一个地方也遇到了同样的问题。 这让我对我的方法进行了更多的评估,我立即意识到我使用了错误的命令。

    问题的根源在于串行驱动程序设置的波特率错误。 我正在使用的应用程序是一个hello world应用程序,我相信它会在完成后导致中止。

    感谢大家的参与!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    切斯特

    很棒的地方! 谢谢,但我最终解决了问题。 在我的@中,我不知道如何使用您的用户名。