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.

[参考译文] AM2434:第一个上下文切换的数据中止

Guru**** 2868720 points

Other Parts Discussed in Thread: AM2434

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1625579/am2434-data-abort-for-first-context-switch

器件型号: AM2434

您好:

我正在使用 AM2434 从 ind_comms_sdk_am243x_11_00_00_08 运行 FreeRTOS。 在其中一个 R5 内核上、我得到了大约 50%的情况下第一个上下文切换发生了数据中止、这恰好是计时器任务。

我已经读出相应的寄存器:

  • DFAR:0x00000000
  • DFSR:0x00001C06

根据故障寄存器 (https://developer.arm.com/documentation/ddi0460/c/System-Control/Register-descriptions/Fault-Status-and-Address-Registers) 的文档、这似乎是异步外部中止

发生中止时、始终发生在上下文切换结束时 RFEIA 指令执行期间。 这应该意味着、如果我向前推进 PC=7010ace4、I 最终会出现在数据中止处理程序中(在~50%的情况下)。 在此前进一步之后、我要么位于计时器任务函数中、要么位于数据中止的矢量表中。

          vPortRestoreTaskContext():
7010acb0:   F102001F            cps        #0x1f
7010acb4:   E59F01C8            ldr        r0, [pc, #0x1c8]
7010acb8:   E5901000            ldr        r1, [r0]
7010acbc:   E591D000            ldr        r13, [r1]
7010acc0:   E59F01C0            ldr        r0, [pc, #0x1c0]
7010acc4:   E49D1004            pop        {r1}
7010acc8:   E5801000            str        r1, [r0]
7010accc:   E3510000            cmp        r1, #0
7010acd0:   149D0004            popne      {r0}
7010acd4:   1CBD0B20            vpopne     {d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15}
7010acd8:   1EE10A10            vmsrne     fpscr, r0
7010acdc:   F57FF01F            clrex      
7010ace0:   E8BD5FFF            pop        {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r14}
7010ace4:   F8BD0A00            rfeia      r13!

这是一个异步外部中止、因此我假设实际触发器可能来自另一条指令、这条指令恰好是在流水线中同时执行的? 为此、我已经尝试将此任务的栈从外部 DDR 移动到 MSRAM、但没有成功。

什么原因可能导致此问题? 是否有任何额外的故障寄存器或类似的东西可以更详细地解释什么触发了此问题?

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

    您好、

    您是在定制电路板还是在 EVM 上测试这个吗?  

    此外、这是否是您遇到此问题的特定示例代码? 如果您使用的是 EVM 和 SDK 中的示例代码、那么我可以在我这边运行相同的代码以检查是否可以重现问题。

    此致、

    会面。

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

    它是一个定制电路板和一个定制应用程序、因此很遗憾、我无法真正提供重现问题的功能。 但如果您能为我提供一些指导、说明我如何进一步调查这个问题、我将会非常高兴。

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

    您提到了将任务的堆栈从 DDR 移动到 MSRAM 会得到相同的结果。 您是否也在将 DDR 用于 FreeRTOS 内核代码? 您能为您的应用共享链接器文件吗、我只想检查 DDR 是否为此问题负责?

    此外、您在定制电路板上使用哪个 DDR 器件型号?

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

     --stack_size=16384
     --heap_size=32768
    -evector_table
    
    __HEAP_SIZE = 32768;
    __STACK_SIZE = 16384;
    __IRQ_STACK_SIZE = 256;
    __FIQ_STACK_SIZE = 256;
    __SVC_STACK_SIZE = 4096;
    __ABORT_STACK_SIZE = 256;
    __UNDEFINED_STACK_SIZE = 256;
    
    MEMORY
    {
        TCMA_VECTOR                : ORIGIN = 0x00000000, LENGTH = 0x00040
        TCMA                       : ORIGIN = 0x00000040, LENGTH = 0x07FC0
        TCMB                       : ORIGIN = 0x41010000, LENGTH = 0x08000
        CORE0_BSS_CACHED           : ORIGIN = 0x70000000, LENGTH = 0x10000
        CORE1_BSS_CACHED           : ORIGIN = 0x70010000, LENGTH = 0x10000
        CORE0_DATA                 : ORIGIN = 0x70020000, LENGTH = 0x10000
        CORE1_DATA                 : ORIGIN = 0x70030000, LENGTH = 0x10000
        CORE0_CODE                 : ORIGIN = 0x70040000, LENGTH = 0x2F9EC
        CORE0_CODE_HEADER          : ORIGIN = 0x7006F9EC, LENGTH = 0x00614
        CORE0_CODE_RODATA          : ORIGIN = 0x70070000, LENGTH = 0x0FDE4
        CORE0_CODE_RODATA_HEADER   : ORIGIN = 0x7007FDE4, LENGTH = 0x0021C
        CORE1_CODE                 : ORIGIN = 0x70080000, LENGTH = 0x4F5F4
        CORE1_CODE_HEADER          : ORIGIN = 0x700CF5F4, LENGTH = 0x00A0C
        CORE2_BSS_UNCACHED         : ORIGIN = 0x700D0000, LENGTH = 0x10000
        CORE3_BSS_CACHED           : ORIGIN = 0x700E0000, LENGTH = 0x10000
        CORE2_CODE                 : ORIGIN = 0x700F0000, LENGTH = 0x7C000
        CORE2_SHARED               : ORIGIN = 0x7016C000, LENGTH = 0x02000
        CORE3_SHARED               : ORIGIN = 0x7016E000, LENGTH = 0x02000
        CORE3_CODE                 : ORIGIN = 0x70170000, LENGTH = 0x50000
        CORE0_SHARED               : ORIGIN = 0x701C0000, LENGTH = 0x08000
        CORE1_SHARED               : ORIGIN = 0x701C8000, LENGTH = 0x08000
        CORE2_BSS_CACHED           : ORIGIN = 0x80000000, LENGTH = 0x200000
        CORE0_PLC_APP_CODE         : ORIGIN = 0x80200000, LENGTH = 0x08000
        CORE0_PLC_APP_DATA         : ORIGIN = 0x80210000, LENGTH = 0x08000
        CORE1_PLC_APP_CODE         : ORIGIN = 0x80300000, LENGTH = 0x08000
        CORE1_PLC_APP_DATA         : ORIGIN = 0x80310000, LENGTH = 0x08000
        CORE2_DATA                 : ORIGIN = 0x80400000, LENGTH = 0x10000
        CORE3_DATA                 : ORIGIN = 0x80500000, LENGTH = 0x10000
    }
    
    SECTIONS
    {
        .vector : {
            *(.vector_table)
        } > TCMA_VECTOR, palign(8) 
    
        .stack : {
        } > TCMA, palign(8) 
    
        GROUP : {
            .bss : {
            } palign(8)
        } > CORE2_BSS_CACHED
    
        GROUP : {
            .bss.uncached : {
            } palign(8)
            .bss.nocache : {
            } palign(8)
        } > CORE2_BSS_UNCACHED
    
        GROUP : {
            .text : {
            } palign(8)
            .rodata : {
            } palign(8)
            .cinit : {
            } palign(8)
        } > CORE2_CODE
    
        GROUP : {
            .irqstack : {
                . = . + __IRQ_STACK_SIZE;
            } align(8)
            RUN_START(__IRQ_STACK_START)
            RUN_END(__IRQ_STACK_END)
            .fiqstack : {
                . = . + __FIQ_STACK_SIZE;
            } align(8)
            RUN_START(__FIQ_STACK_START)
            RUN_END(__FIQ_STACK_END)
            .svcstack : {
                . = . + __SVC_STACK_SIZE;
            } align(8)
            RUN_START(__SVC_STACK_START)
            RUN_END(__SVC_STACK_END)
            .abortstack : {
                . = . + __ABORT_STACK_SIZE;
            } align(8)
            RUN_START(__ABORT_STACK_START)
            RUN_END(__ABORT_STACK_END)
            .undefinedstack : {
                . = . + __UNDEFINED_STACK_SIZE;
            } align(8)
            RUN_START(__UNDEFINED_STACK_START)
            RUN_END(__UNDEFINED_STACK_END)
        } > CORE2_DATA
    
        GROUP : {
            .data : {
            } palign(8)
        } > CORE2_DATA
    
        GROUP : {
            .shared_core0 : {
                *(.spsc_queue_ErrorItemsToREHCore0_write_index)
    			...
            } palign(8), type = NOINIT
        }> CORE0_SHARED
    
        GROUP : {
            .shared_core1 : {
                *(.spsc_queue_ErrorItemsToREHCore1_write_index)
    			...
            } palign(8), type = NOINIT
        }> CORE1_SHARED
    
        GROUP : {
            .shared_core2 : {
                *(.spsc_queue_ErrorItemsToREHCore0_read_index)
    			...
            } palign(8)
        }> CORE2_SHARED
    
        GROUP : {
            .shared_core3 : {
                *(.shared_atomic_variable_bootCounter)
    			...
            } palign(8), type = NOINIT
        }> CORE3_SHARED
    
    }

    这是适用于此内核的链接器脚本。 我已将它缩短了一点 (COREX_SHARED 中的...)、以便能够直接在此处上传它。

    如您在链接器脚本中所见、我们已将 BSS 和数据移动到该内核的 DDR、因此对于 FreeRTOS 内核代码也是如此。 代码本身当前仍在 MSRAM 中、但不久将在 DDR 中部分移动。

    对于 DDR、我们使用  MT40A1G16KD-062E IT

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

    您还能分享 ADFSR 寄存器的值吗?

    您能否使代码以严格顺序执行而不是缓存的 MSRAM 区域、并查看您是否可以访问导致中止(而不是异步中止)的确切指令。  

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

    我已重新配置受影响堆栈所在的 MPU 区域、以使该区域访问控制寄存器值为 0x300。 这应该严格排序、不带缓存?

    通过这些设置、我可以获得以下信息:
    ADFSR = 0x3F
    DFAR = 0x0
    DFSR = 0x1C06

    如果我正确理解了 ADFSR(Cortex-R5 技术参考手册)的文档、则表示错误来自高速缓存/Axim?

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

    您好:
    感谢您的查询。 有关专家因** TI 印度**假期而离职。
    请预计响应会延迟。 感谢您的耐心和理解。

    此致、
    TI E2E 支持团队
    ——
    *这是一个自动通知。*

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

    您好、

    我已重新配置受影响堆栈所在的 MPU 区域、使该区域访问控制寄存器值为 0x300。 这应该严格排序、不带缓存?

    我的意思是将 MSRAM 内存配置 为 vPortRestoreTaskContext() 执行严格排序、以检查它是否能提供触发中止的确切指令。 只需运行测试、您就可以将整个 MSRAM 按严格顺序排列。 要跟踪导致中止的确切指令、请 检查中止处理程序栈帧中 (R14−8) 附近的指令、请参阅 此处的第 5.2.2.4 节: https://www.ti.com/lit/an/sprad28/sprad28.pdf#page=13 

    第一个上下文切换的数据中止、这恰好是计时器任务。

    您提到了切换到计时器任务的第一个上下文开关、可能需要检查在 映射文件中 uxTimerTaskStack 分配到的地址。 要确认计时器任务实际上是导致了任何问题还是其他问题、您可以尝试禁用它并查看您是否仍然看到相同的问题。 您可以通过 在 FreeRTOSConfig.h 文件中将 configUSE_TIMER 配置为 0 来禁用它。

    如果我正确理解了 ADFSR(Cortex-R5 技术参考手册)的文档、这意味着错误来自 Cache/Axim?

    组合的寄存器值指向在写入访问期间由 AXI 从器件错误 (SLVERR) 触发的异步外部中止。 这可能会导致不正确的 MPU 设置。 您能否共享当前的 MPU 设置、或者在可能的情况下共享 syscfg 文件?  

    此致、

    会面。

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

    一旦我配置了严格排序的代码段、就会进入预取中止模式。 这有点奇怪、还没有弄清楚原因。

    uxTimerTaskStack 位于我需要的位置、在 BSS 中为 0x8009b700。

    我将查看是否可以确保首先安排不同的任务。

    这是故障内核的所有 MPU 区域的转储:

    [0]
      baseAddress 0x00000000
      sizeAndEnable 0x0000003F
      Attributes 0x00001020
    [1]
      baseAddress 0x00000000
      sizeAndEnable 0x0000803D
      Attributes 0x00001204
    [2]
      baseAddress 0x00000000
      sizeAndEnable 0x0000001F
      Attributes 0x00001329
    [3]
      baseAddress 0x00000000
      sizeAndEnable 0x0000000B
      属性 0x00000629
    [4]
      baseAddress 0x70000000
      sizeAndEnable 0x0000F727
      Attributes 0x00001624
    [5]
      BaseAddress 0x70080000
      sizeAndEnable 0x0000FB25
      Attributes 0x00001324
    [6]
      BaseAddress 0x70080000
      sizeAndEnable 0x0000F725
      Attributes 0x00001624
    [7]
      BaseAddress 0x70080000
      sizeAndEnable 0x0000EF25
      属性 0x00000324
    [8]
      BaseAddress 0x70080000
      sizeAndEnable 0x0000BF25
      Attributes 0x00001329
    [9]
      BaseAddress 0x70100000
      sizeAndEnable 0x0000F827
      属性 0x00000324
    [10]
      baseAddress 0x80000000
      sizeAndEnable 0x0000FE2F
      属性 0x00000300
    [11]
      BaseAddress 0x80800000
      sizeAndEnable 0x0000FE2D
      属性 0x00000324
    [12]
      baseAddress 0
      sizeAndEnable 0
      属性 0
    [13]
      baseAddress 0
      sizeAndEnable 0
      属性 0
    [14]
      baseAddress 0
      sizeAndEnable 0
      属性 0
    [15]
      baseAddress 0
      sizeAndEnable 0
      属性 0
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您分享 MPU 配置、我看到从 0x70080000 开始的 512KB 区域具有多个 MPU 设置、是否有理由这样做? 此外、我看到、对于从 0x70000000 开始的区域配置为只读、这些存储器的任何写入访问都可能导致数据中止、您可以尝试将其更改为 RD+WR 访问。  

    为其中大多数配置子区域禁用屏蔽的原因是什么?

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

     0x70080000 处的区域乍一看只具有多个设置、实际上它们是基于其启用的子区域的不同区域。 我们正在相当广泛地使用子区域、因为我们将从另一个配置文件自动生成这些设置、因此这只是正确对齐大小和子区域的算法的输出、从而在给定的存储器映射中需要最少数量的 MPU 区域。 但是、如果我理解正确、这实际上应该没问题?

    对于从 0x70000000 开始的寄存器、其具有以下设置:

    • xn=0b1 ->无指令提取
    • AP=0b110 -> 特权/用户只读
    • TEx=0b100
    • S=0b1
    • C=0b0
    • B=0b0 -> TEX、C、B=0b10000 ->不可缓存内部和外部策略

    该存储器区域旨在由其他内核写入并由该内核读取、从而实现这些设置。 我不明白您的意思是只读/任何写入访问? 您能否澄清一下这一说法?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    此存储器区域旨在通过其他内核写入并由此内核读取、因此需进行这些设置。 我不明白您的意思是只读/任何写入访问? 您能否澄清此陈述?

    我要说的是、这个特定内核只对该存储器区域具有读取访问权限、如果该内核尝试写入该区域中的存储器、则可能会导致中止。  只要该 CPU 不访问该存储器区域、就可以正常访问。  

    我将查看是否可以确保首先安排不同的任务。

    请告诉我您对此的观察结果、中止主要是由于 STORE 指令尝试访问某些无效的存储器区域或对内核禁用了访问、但您的 MPU 设置并未表明存在此问题。

    您是否可以为我提供可在 EVM 上运行的参考代码? 我可以尝试在我最后重现这个问题、看看是否能找出根本原因。

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

    不幸的是,不管怎样,我都不能打破它,它实际上只会出现在我们定制硬件的整个系统中。 非常有趣的部分也是我如何能够通过断点避免问题、因为对我来说原因未知。 为了更改计时器任务的优先级 、我在 xTimerCreateTimerTask 添加了一个断点、将调用中的优先级更改为 xTaskCreateStatic 并让系统再次运行。 但这样就不会再出现问题了。 更令人困惑的是、当我根本不更改优先级、只需进入任务创建、然后让系统再次运行时、我会得到相同的结果。

    因此总结一下:数据中止只出现一次。 重试完全相同的东西成功了。 因此、我得出结论:MPU 设置必须正确、因为否则数据中止将再次出现。 除此之外、我可以提前一些指令步骤避免数据中止、稍后与数据中止无关。

    这总的来说是一个非常不清楚和令人困惑的错误模式。 你有什么想法可能导致这样的事情吗?

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

    对不起,我骗了自己。 这个问题只是有时出现,因此我之前的结论是,手动步骤在任务创建过程中产生了差异是错误的。 但是,在加号方面,我现在能够降级计时器任务,让另一个任务成为第一个上下文切换的任务。 问题也会出现在那里、因此它似乎与上下文切换所在的任务无关。 数据中止仅出现、有时至少出现在任务的第一个上下文切换中。

    但其他结论仍然有效。 我认为这不可能是 MPU 的错误配置、因为这样会一直发生、重试不会成功。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我的意思是从 vPortRestoreTaskContext() 执行严格排序的位置配置 MSRAM 内存、以检查它是否能为我们提供触发中止的确切指令。

    我想我现在已经理解了当我将代码区域配置为严格排序时系统失败的原因:

    MPU 区域中具有器件或严格排序存储器类型属性的任何地址都以隐式方式获得从不执行 (XN) 权限。

    R5 技术参考手册中的链接

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

    尊敬的 Benedikt:

    抱歉耽误时间、我正在内部检查以获得更多想法、一旦我有更新、就会通知您。

    此致、

    会面。