我正在使用STM32F107芯片在C中进行一些开发,在某个时候,当我调用特定功能时,设备开始重置。我没有调试器,我的调试只是串行端口上的纯文本。

我已经使用了其他一些微控制器,可以在其中访问寄存器以查看重置的原因,但是我似乎找不到该设备的等效物。我知道Cortex-M3的硬件例外,但是我不知道其中一个是在触发的,因为当我在这些处理程序中时我似乎无法通过USART发送文本功能使用中断?)。

因此,我决定询问比我在此设备中拥有更多经验的人:通常在此类调试情况下做些什么?

编辑

其中一位开发人员激活了WWDG看门狗,它正在重置硬件,然后才能从故障处理程序中获取信息。这是一个严重的错误,因为指向错误的位置的指针调用功能。但是,我将继续这个问题,希望有人能提供更多的细节(或材料),以指向保存的寄存器中的C代码,可以说是一个严重的错误(@dwelch的想法)。

有帮助吗?

解决方案

Cortex M3具有出色的故障处理功能,可以使您的生活更轻松。碰到故障时,它会自动堆叠几个寄存器,例如PC和LR,并且故障状态寄存器会告诉您诸如BUS FARDS的地址,等等。

您应该实现一个很好的故障处理程序(例如,在这里的硬故障处理程序: http://blog.frankvh.com/2011/12/07/cortex-m3-m4-hard-faultler/)打印出堆叠的寄存器和调试故障状态寄存器。

您应该使用UART进行打印,只需编写自己的简单自定义版本的PrintF,以便从您的故障处理程序中使用,而不取决于中断。只需将字节直接写入UART TX数据寄存器和轮询以完成字节完成即可。

其他提示

除了提到有关调试的中断处理程序的提及之外,一些ST MicroS还具有重置源寄存器,您可以在电源上阅读(即重置后)。对于Cortex M家族(M0/M3/M4),寄存器为RCC_CSR。 http://www.st.com/web/en/resource/technical/document/reference_manual/dm00031020.pdf

不幸的是,您将无法知道这些具体内容(例如硬错)是否会告诉您看门狗(窗口或独立)是否已绊倒。

鉴于您没有调试器,我建议您在微控制器上找到一些外围设备来帮助您。也许您有一个LED可以切换或简单的GPIO引脚,您可以使用它可以连接到示波器。如果您慢慢地切换GPIO引脚(根据仪表的不同,不超过1 Hz,可能会慢得多),则可以使用伏特仪而不是示波器。将代码放在每个异常处理程序中,直到您对其进行跟踪,以切换LED或GPIO PIN。如果您有多个GPIO引脚,则可以加快该过程。您还可以为引起重置的特定功能编写包装器。包装器函数将在执行破坏功能之前发送启用的中断列表。这样,您就不必浪费时间测试未启用的时间。

在这种情况下,GPIO引脚的优势之一是它们不需要中断。最好远离任何需要中断的东西(在这种情况下像您的usart一样)。如果重置是由更高的优先级引起的,那么您的调试代码将永远不会执行。

复位是由非初始化的指针引起的。设置为零的功能指针会导致执行看起来很像重置。如果是这种情况,则可能正在执行USART初始化代码,然后在本例中将USART完全传输之前,这将使USART无用为在这种情况下的调试工具。

当您说重置时,我认为您会击中重置向量,而不是中断或处理程序之一。您是说它确实确实重置了芯片并重新开始您的软件,还是说它挂在某个地方?还是您的矢量表都在重置矢量?

如何进行取决于您真正看到的内容,您需要更加清晰或更具体,或者您需要帮助解决这个问题。

通常,我将未使用的向量映射到一个简单的悬挂式代码线,该代码将其分支到本身。稍后,我可能会将其中一些重新映射到真实的代码。

Cortex-M非常好,您可以指出C代码。如果您认为自己有例外,请指出一个例行程序,该程序可以抓住一些可以帮助您弄清楚您所处模式的东西,链接寄存器可能具有该信息或CSR,请打印出来并进入无限循环。用此通用调试函数的地址填充矢量表的未使用部分。

从那里,您需要弄清楚为什么要遇到这个例外,例如,它可能是一个不规学的访问。可能是,在完全设置处理程序之前,您在尝试将设备捕获时会产生一个中断,谁知道。

在您完成此操作时,请通过更多答案或信息编辑您的问题。

不幸的是,对STM32并不实用,“正确”的事情是。那将是放置一个具有源代码知识的大型例外处理程序,并可以放松堆栈,并为您提供导致故障的完整呼叫堆栈和线号。这将需要将应用程序中的所有调试信息添加到STM32的闪存中,这是不切实际的。

有一些方法可以欺骗您的IDE有时给您通话堆栈。我会提供细节,但我忘了写下来,所以我忘记了。我认为它必须手动将堆栈指针从一个影子寄存器更改为另一个影子寄存器。

我通常要做的是在硬故障异常向量上放置一个断点,然后在断路点命中时查看所有寄存器。考虑一下谋杀案的法医证据,用塑料炸药做。寄存器的价值将为您提供想法。以0x20000000开头的寄存器值是RAM地址。以0x08000000开头的寄存器值是闪存地址。打开拆卸器并输入这些地址。它可能会直接进入变量或在这些内存位置的功能。如果那无济于事,请查看堆栈指针。在堆栈指针上查看内存位置,并执行相同的技巧。我总是发现足够的弹片来定位发生例外的功能。

您可以使用以下代码进行调试。

void HardFault_Handler(void)
{
    __asm volatile
       (
           " tst lr, #4                                                \n"
           " ite eq                                                    \n"
           " mrseq r0, msp                                             \n"
           " mrsne r0, psp                                             \n"
           " ldr r1, [r0, #24]                                         \n"
           " ldr r2, handler2_address_const                            \n"
           " bx r2                                                     \n"
           " handler2_address_const: .word prvGetRegistersFromStack    \n"
       );

  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {
  }
}

也要添加。

void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )
{
    /* These are volatile to try and prevent the compiler/linker optimising them
    away as the variables never actually get used.  If the debugger won't show the
    values of the variables, make them global my moving their declaration outside
    of this function. */
    volatile uint32_t r0;
    volatile uint32_t r1;
    volatile uint32_t r2;
    volatile uint32_t r3;
    volatile uint32_t r12;
    volatile uint32_t lr; /* Link register. */
    volatile uint32_t pc; /* Program counter. */
    volatile uint32_t psr;/* Program status register. */

    r0 = pulFaultStackAddress[ 0 ];
    r1 = pulFaultStackAddress[ 1 ];
    r2 = pulFaultStackAddress[ 2 ];
    r3 = pulFaultStackAddress[ 3 ];

    r12 = pulFaultStackAddress[ 4 ];
    lr = pulFaultStackAddress[ 5 ];
    pc = pulFaultStackAddress[ 6 ];
    psr = pulFaultStackAddress[ 7 ];

    /* When the following line is hit, the variables contain the register values. */
    for( ;; );
}

我正在使用它来获取寄存器的任何值。如果愿意,您还可以添加更多寄存器。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top