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.

[参考译文] TM4C123GH6PZ:诊断无效状态用法故障-堆栈溢出?

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/582892/tm4c123gh6pz-diagnosing-invalid-state-usage-fault---stack-overflow

器件型号:TM4C123GH6PZ
主题中讨论的其他器件: TM4C123

您好!

我遇到一个问题、在 我的 TM4C123GH6PZ 上运行我的程序大约一个小时后、微控制器进入故障 ISR。 我想详细介绍我到目前为止所采取的步骤、并寻求一些建议或建议。

我尝试使用  这里的文档来调试故障。 我已通过 NVIC_FAULT_STAT 寄存器确定我正在进入无效状态使用故障。 NVIC_FAULT_ADDR 正在读取地址0xE000EDF8。 从 TM4C123GH6PZ 数据表中可以看出、这似乎在为 Cortex-M4F 外设(SysTick、NVIC、MPU、FPU 和 SCB)保留的存储器内。 查看 Cortex-M4F 数据表、0xE000EDF8似乎是"调试内核寄存器数据寄存器"。 我在这里看到了一个死区、因为我不确定这是否是正确的故障地址。

听起来、导致无效状态使用故障的最常见原因是堆栈溢出或堆栈损坏。 我阅读 了此文档 并添加了一个硬件观察点来监视__stack。 到目前为止、我还未达到这个观察点、但我仍然遇到 FaultISR。 我之前读过、有时可以通过将整个堆栈设置为特定的已知值并查看是否/何时在内存中修改所有值来调试堆栈溢出。 我看到这可以在链接器文件中完成、但我不确定如何操作。

我还注意到、在我的链接器文件(.cmd)内有语句  

__STACK_TOP =__STACK + 1900;

这是旧项目的结转。 我的堆栈大小实际上设置为2600。 上述陈述有何影响? 从论坛上的前一个线程开始、__STACK_TOP 和__STACK_END 作为栈的最低值开始。 当堆栈被填充时、__STACK_TOP 下降到值__STACK。 通过设置__STACK_TOP =__STACK + 1900,我是否顺便将堆栈设置为仅1900? 我的映射文件显示的堆栈大小为0xA28 (2600)、但似乎我要在程序开始时抵消堆栈顶部。

任何帮助、提示或想法都将受到广泛赞赏! 这是我第一次真正挖掘堆栈的使用情况、因此如果我缺少明显的东西、请注意!

此致、

CamK

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

    对于 INVSTATE 故障、最有可能的原因是堆栈溢出或堆栈损坏。 _stack_top 是加载到矢量0x0处堆栈指针的内容、如所示 (void (*)(void)((uint32_t)&_stack_top)。 请从1900更改为2600以匹配您在 CCS 中定义的堆栈大小。 当您更改为_stack_top =_stack + 2600时会发生什么情况?

    INVSTAT 故障的其他可能原因包括将一个分支目标地址载入 PC 或者矢量表包含一个 LSB=0的矢量地址。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Charles、

    感谢您的回复。

    我进行了建议的更改和设置
    __STACK_TOP =__STACK + 2600;
    以匹配 CCS 中定义的堆栈大小。

    运行一段时间(半小时)后、我仍然会生成无效状态使用故障。 我为__stack 设置了硬件观察点,但它从未达到这一点。 我还尝试将堆栈大小增加到3200、但没有结果。

    是否有任何其他建议方法来确定它是否是 stackoverflow 与堆栈损坏? 听起来我可能能够使用 LR 寄存器来确定最后运行的函数。

    此致、
    CamK
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您是否尝试在代码优化设置较低的情况下进行编译,如果您进行 SysPrintf()调用,还会在链接器选项中添加一些堆 RAM。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    当您位于 HardFault 异常例程中时、LR 的值是多少? 它是正常地址吗?

    也许这就是你可以尝试的东西。 当您进入 HardFault 异常例程时、找出 SP 值。 在存储器窗口中、转到 SP 指向的地址。 检查保存到堆栈中的 LR 值。 在异常期间、R0、R1、R2、R3、R12 SP、LR、PC 和 PSR 以降序保存到栈中、R0位于地址底部。 转至压入堆栈的 LR 指向的地址。 您是否在该地址看到任何可能导致 INVSTAT 使用故障的指令、例如尝试对偶数地址执行 BLX?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、

    我没有执行任何动态分配(堆设置为0)、并且我关闭了优化。

    我运行了程序并等待它崩溃。 我转到存储在 SP 中的地址-它似乎是栈范围内的有效地址-并找到存储在栈上的 LR。 我转到了 LR (0x3A35)的地址、并在该地址查看了分解。 我的最后一条指令似乎是 str 指令。

    我看到 blx 指令为0x3A32。 异常堆栈帧(SP + 0x08)中存储的 R2的值为0x00000000。 这是否是罪魁祸首?

    此致、

    CamK

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    CamK、
    我很久以前遇到过类似的问题:在非常罕见和随机的情况下执行死刑会冻结。 在这种情况下、您实际上考虑配置看门狗、以便将产品推向市场。
    在将所有可能的堆栈和芯片的 Pod 封装成组后、问题最终出现在数组索引上-这是接收到的数据的几乎不可能组合、这会导致错误代码尝试远于数组声明的大小。
    这是我再也不会让它发生的事情,但它有点隐蔽,与我看到的问题没有明显的关系。 要点是:在寻找像您一样的问题时、请保持非常开放的心态。
    就堆栈而言、在我闪烁 LED 之前、我的 TM4C129项目都设置为4096、TM4Cs 设置为2048、这当然不是太科学、但它们是数字、可以避免发生其他神秘(调试时很痛苦)的问题。
    此致
    布鲁诺
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Hi Cam、
    正如我之前所指出的、一个到偶数地址(R2的 bit0=0)的 blx 将尝试切换到 CortexM4中不允许的 ARM 状态。 请调查相应的 C 代码、以查看是否有任何关于为什么 R2=0的线索。 在将 R2压入堆栈之前是什么?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    因此、在进行一些修改后、每次运行时、我都会始终收到指令访问违规故障(NVIC_FAULT_STAT 寄存器= 0x00000001)。 NVIC_MM_AADR = 0xE000EDF8 (相同的调试数据寄存器)。 系统崩溃的速度快得多、但它更加一致、并且始终导致相同的堆栈指针(0x20005238)。 如果我跟随该地址、我可以在每次运行时在堆栈上看到相同的 LR 地址(0x10DD3)。 堆栈上的 PC 寄存器是0xFFFFFF30 -这不能有效、可以吗? 看起来 R0是0x00000000。  

    在我的 UART 4中断中、我可以在 LR 地址处看到反汇编过程中的以下代码。 我正在使用 TivaWare 提供的环形缓冲器 RingBufUsed 函数(我认为2.1.3.156)来检查环形缓冲器中是否有数据。  

    违规指令或任何内容是否突出? ulMode 只是一个标准的无符号32位整数。 circtxBuffer 是大小为256的环形缓冲器(使用 TivaWare 中提供的结构)。 我还会附加整个 UART4中断、以防我忽略某些内容。 这个问题确实让我感到很痛苦。 有趣的是、我的调试屏幕有一个包含消息0xFFFFFFF0的小窗口(没有为0xFFFFFFF0定义符号)。 我是否可以检查其他寄存器以帮助我指明正确的方向?

    空 UART4IntHandler (空)
    {
    uint32 intStatus;
    uint32 ulMode = 0;
    schevent 事件;
    uint8 recChar[16];
    uint8索引= 0;
    
    intStatus = MAP_UARTIntStatus (UART4_base、true);
    MAP_UARTIntClear (UART4_BASE、intStatus);
    
    if (intStatus &(UART_IM_RTIM | UART_IM_RXIM))
    {
    while (MAP_UARTCharsAvail (UART4_base))
    {
    recChar[index+]= MAP_UARTCharGetNonBlocking (UART4_base);
    }
    
    if (索引)
    {
    RingBufWrite (&cRxBuffer、recChar、index);
    event.sig = UART_sig;
    SH_POST_ISR (UART4_TASK_PRIO、事件);
    MAP_IntMasterEnable();
    }
    RxInt++;
    }
    
    ulMode = RingBufUsed (&circtxBuffer);
    IF (ulMode)
    {
    for (index=0;index < ulMode;index++)
    {
    if (map_UARTSpaceAvail (UART4_base))
    {
    MAP_UARTCharPut (UART4_base、RingBufReadOne (&circtxBuffer));
    }
    其他
    {
    索引= ulMode;
    }
    
    }
    
    } 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 CamK:
    访问冲突意味着 CPU 正在从一个 XN 地址执行(从不执行)。 系统控制空间始终为 XN。

    您是否显示故障/故障仅在输入 UART4IntHandler()时发生?

    如果您单步执行汇编代码、它会在哪条指令生成故障?

    指数是否在任何时候超过16?

    在调用 RingBufUsed()之前和调用之后,哪些寄存器保存到栈中?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Charles、

    我找到了问题。 事实证明阵列缓冲器过流。 通信速率太高、在中断处理程序清除 FIFO 之前、将有更多字节到达(FIFO 触发级别设置为6/8)、并且阵列将溢出。

    感谢大家的观看。 解决这一问题需要很多耐心。

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

    CamK

    不得不说... "告诉您!"

    "...问题最终出现在阵列索引上-它几乎不可能组合接收到的数据、这会导致错误代码尝试写入距离阵列声明大小远的位置..."

    再看一下您的代码-即使通信速度很快、也不应让中断跳跃允许发生这种情况。 应该发生的"最糟糕"是未处理或丢失的数据、但没有阵列损坏;当然、空间不足的不是硬件 FIFO。

    尽管如此、很高兴您找到了它、感谢您分享了结果。

    布鲁诺