在 STM32F411 Discovery 上实现 HD44780 LCD 时调试 HardFault

Posted

技术标签:

【中文标题】在 STM32F411 Discovery 上实现 HD44780 LCD 时调试 HardFault【英文标题】:Debugging HardFault while implementing HD44780 LCD on STM32F411 Discovery 【发布时间】:2019-03-09 14:36:13 【问题描述】:

我在使用这个库在 STM32F411 Discovery 上编程 LCD HD44780 时遇到问题:https://stm32f4-discovery.net/2015/07/hal-library-15-hd44780-for-stm32fxxx/ 问题是在实现库并运行代码后,我通常会卡在 HardFault_Handler 函数中。我阅读了互联网上有关调试硬故障的几篇文章,并从该站点实现了HardFault_HandlerC 函数:https://community.nxp.com/thread/389002 该程序现在卡在此函数中,这让我了解了寄存器中的内容,但现在我真的不知道我接下来应该做什么,因为这些值完全没有告诉我。

这些是提到的寄存器的值:

stacked_r0  volatile unsigned long  0   
stacked_r1  volatile unsigned long  0   
stacked_r2  volatile unsigned long  0   
stacked_r3  volatile unsigned long  1   
stacked_r12 volatile unsigned long  45000000    
stacked_lr  volatile unsigned long  11018266    
stacked_pc  volatile unsigned long  553682714   
stacked_psr volatile unsigned long  8192    
_CFSR   volatile unsigned long  256 
_HFSR   volatile unsigned long  1073741824  
_DFSR   volatile unsigned long  11  
_AFSR   volatile unsigned long  0   
_BFAR   volatile unsigned long  3758157112  
_MMAR   volatile unsigned long  3758157108  

谁能告诉我下一步我应该怎么做才能进一步检查问题?

我的随机运行程序也卡在了这段代码中(而不是 HardFault):

/* Wait till LSE is ready */
      while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
      
        if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
        
          return HAL_TIMEOUT;
        
      

这似乎与单元化LSE有关,但我认为我应该首先专注于调试硬故障。

【问题讨论】:

如果你有一个带跟踪的调试器,检查一下。通过在处理程序中设置断点并检查跟踪,它将立即显示哪个代码是罪魁祸首。或者,一些调试器可能会显示调用堆栈。 前段时间我给出了一个答案,描述了如何在代码中找到导致错误的位置 - 请参见此处:***.com/questions/51085240/...。此外,即使使用调试器,也不能始终保证它在 HardFault 处理程序中显示方便的调用堆栈。 【参考方案1】:

调试硬故障非常困难。您很可能已进入硬故障处理程序,因为发生了没有可用处理程序的异常,但也可能是因为处理程序本身产生了异常。

正如Lundin 在评论中所说,如果您有一个不错的调试器,您可以在硬故障处理程序中放置一个断点,并让调试器向您显示完整的调用堆栈。但如果没有,你将不得不以艰难的方式去做。

当 CPU 进入处理程序模式以处理异常时,硬件会将各种寄存器推送到活动堆栈,您实现的处理程序会从堆栈中取出这些寄存器供您检查。首先要看的是堆栈程序计数器(PC)的内容。尝试以十六进制获取其值;然后,您应该能够使用调试器将其与产生故障的指令的地址相关联。

如果堆叠的 PC 地址与合理的代码地址不对应,则有可能另一行代码试图跳转到这个无意义的地址,这就是触发故障的原因。在这种情况下,您可以通过查看堆栈链接寄存器 (LR) 地址来获取一些信息 - 这应该包含 CPU 上次遇到调用指令时程序计数器的值。这可能与生成恶意分支的行不完全对应,但它应该让您足够接近以放置另一个断点并单步执行,直到发生异常。

如果这些建议不能让您找到罪魁祸首,我很乐意编辑此答案并提供进一步的建议 - 只需发表评论,我会尽快回复您。

【讨论】:

以上是关于在 STM32F411 Discovery 上实现 HD44780 LCD 时调试 HardFault的主要内容,如果未能解决你的问题,请参考以下文章

STM32F411RE:程序冻结,超声波传感器不工作

STM32F411我需要通过USB高速发送大量数据

stm32f411ceu6怎么用Micropythor烧录固件

STM32F411CE芯片锁住解决办法

STM32F411RE和L610物联网入门学习笔记

STM32F411最小系统!实测成功!