Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Embedded 如何调试STM32设备中的意外重置?_Embedded_Interrupt Handling_Cortex M3_Stm32 - Fatal编程技术网

Embedded 如何调试STM32设备中的意外重置?

Embedded 如何调试STM32设备中的意外重置?,embedded,interrupt-handling,cortex-m3,stm32,Embedded,Interrupt Handling,Cortex M3,Stm32,我正在用一个STM32F107芯片用C做一些开发,在某个时候,当我调用一个特定的函数时,设备开始复位。我没有调试器,我的调试只是串口上的纯文本 我曾经使用过一些其他的微控制器,在这些微控制器中,我能够访问寄存器来查看重置的原因,但是我似乎找不到一个与此设备等效的微控制器。我知道Cortex-M3的硬件异常,但我不知道其中一个是否被触发,因为当我在这些处理程序中时,我似乎无法通过usart发送文本(可能是因为我的TX函数使用中断?) 所以,我决定问问在这个设备上比我更有经验的人:在调试这样的情况时

我正在用一个STM32F107芯片用C做一些开发,在某个时候,当我调用一个特定的函数时,设备开始复位。我没有调试器,我的调试只是串口上的纯文本

我曾经使用过一些其他的微控制器,在这些微控制器中,我能够访问寄存器来查看重置的原因,但是我似乎找不到一个与此设备等效的微控制器。我知道Cortex-M3的硬件异常,但我不知道其中一个是否被触发,因为当我在这些处理程序中时,我似乎无法通过usart发送文本(可能是因为我的TX函数使用中断?)

所以,我决定问问在这个设备上比我更有经验的人:在调试这样的情况时通常做些什么

编辑


其中一个开发者激活了WWDG看门狗,在我从故障处理程序获取信息之前,它正在重置硬件。这是一个硬错误,因为使用指向错误位置的指针调用函数。然而,我将保留这个问题,希望有人能提供更多的细节(或相关材料),以便从保存在寄存器中的C代码返回,比如说,一个硬故障(@dwelch idea)。

鉴于您没有调试器,我建议您在微控制器上找到一些外围设备来帮助您。也许你有一个LED可以切换,或者一个简单的GPIO引脚没有被使用,你可以连接到示波器。如果您切换GPIO引脚的速度足够慢(不超过1 Hz,可能更慢,具体取决于仪表),则可以使用电压表而不是示波器。将代码放入每个异常处理程序中,一次切换一个LED或GPIO引脚,直到找到它为止。如果有多个GPIO引脚可用,则可以加快该过程。您还可以为导致重置的特定函数编写包装。包装器函数将发送一个中断列表,这些中断是在中断函数执行之前启用的。这样,您就不必浪费时间测试那些未启用的

在这种情况下,GPIO引脚的一个优点是它们不需要中断。最好远离任何需要中断的东西(如本例中的USART)。如果重置是由更高优先级的异常引起的,则调试代码将永远不会执行


重置由未初始化的指针引起也是很常见的。函数指针设置为零会导致执行看起来很像重置。如果是这种情况,USART初始化代码可能是在USART完全传输字节之前执行的,这将使USART在这种情况下无法用作调试工具。

Cortex M3具有出色的故障处理功能,可以让您的生活更轻松。在遇到故障时,它会自动堆叠几个寄存器,如PC和LR,故障状态寄存器会告诉您总线故障地址等信息

您应该实现一个好的故障处理程序(例如,此处的硬故障处理程序:)以打印出堆叠寄存器和调试故障状态寄存器


您应该使用UART进行打印,只需编写自己的简单自定义版本的printf,以便从不依赖于中断的故障处理程序中使用。只需将字节直接写入uart Tx数据寄存器,并轮询字节完成。

当你说重置时,我认为你点击的是重置向量,而不是中断或处理程序。你是说它确实重置了芯片,重新启动了你的软件,还是说它挂在某个地方?或者向量表中的所有点都指向重置向量

如何进行取决于你真正看到了什么,你需要更清楚或更具体,或者你需要帮助弄清楚这一点

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

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( ;; );
}