我正在使用STM32F405微控制器进行嵌入式项目,并且有一些非常令人困惑的行为。我正在将现有(工作)项目从STM32F1移植到STM32F4,但我已为VCP添加了ST的标准外设库USB堆栈。
如果我使用-O0
优化编译程序,那么它会无限期地按预期运行。但是,如果我使用-O2
进行编译,那么项目将运行10-15分钟,但随后我会看到ST的VCP驱动程序代码中出现堆栈溢出的情况。
实际的错误表现为指针(GREGS
)变为无效,即使指针早先在同一个函数中使用过。该指针指向USB外设的硬件中断配置寄存器,因此实际数据没有消失,但是当访问指针时,我得到一个错误,我可以看到我的调试器指针无效。 (我已经从下面的usb_dcd_int.c
复制了实际的函数,指出了麻烦的行。)
static uint32_t DCD_HandleRxStatusQueueLevel_ISR(USB_OTG_CORE_HANDLE *pdev)
{
USB_OTG_GINTMSK_TypeDef int_mask;
USB_OTG_DRXSTS_TypeDef status;
USB_OTG_EP *ep;
/* Disable the Rx Status Queue Level interrupt */
int_mask.d32 = 0;
int_mask.b.rxstsqlvl = 1;
/*****************************************************************/
/*********** POINTER IS READ HERE - NO PROBLEMS ******************/
/*****************************************************************/
USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, int_mask.d32, 0);
/* Get the Status from the top of the FIFO */
status.d32 = USB_OTG_READ_REG32( &pdev->regs.GREGS->GRXSTSP );
ep = &pdev->dev.out_ep[status.b.epnum];
switch (status.b.pktsts)
{
case STS_GOUT_NAK:
break;
case STS_DATA_UPDT:
if (status.b.bcnt)
{
USB_OTG_ReadPacket(pdev,ep->xfer_buff, status.b.bcnt);
ep->xfer_buff += status.b.bcnt;
ep->xfer_count += status.b.bcnt;
}
break;
case STS_XFER_COMP:
break;
case STS_SETUP_COMP:
break;
case STS_SETUP_UPDT:
/* Copy the setup packet received in FIFO into the setup buffer in RAM */
USB_OTG_ReadPacket(pdev , pdev->dev.setup_packet, 8);
ep->xfer_count += status.b.bcnt;
break;
default:
break;
}
/* Enable the Rx Status Queue Level interrupt */
/*****************************************************************/
/************************* GREGS == :-( ************************/
/*****************************************************************/
USB_OTG_MODIFY_REG32( &pdev->regs.GREGS->GINTMSK, 0, int_mask.d32);
return 1;
}
我使用vanilla GNU make
和gcc-arm-none-eabi 5-4-2016q3
作为我的工具,ST的vanilla链接器和启动脚本从2015年开始用于STM32F405,VCP代码来自2012年3月。我是新手启动和链接器脚本,但我不能在任何一个中看到任何可疑的东西。我也没有看到ST的VCP代码中有任何明显的东西,但我当然不理解每一行。
我有三个问题:
-O2
中哪些优化可能会导致此行为?我想知道我是否可以选择性地禁用一些可能有助于我追踪我的错误的优化。答案 0 :(得分:0)
-fstack-usage
检查函数的堆栈使用情况。但这与问题无关。使用更好的优化进行编译会创建具有较小堆栈使用的代现在我不知道The actual bug manifests as a pointer (GREGS) getting dereferenced even though the pointer had been used earlier in the same function.
你是什么意思。程序员的意图是两次取消引用GINTMSK。 GINTMSK指针被声明为volatile,它将在每次使用时被解除声明并且不会被优化掉。这也是意图,因为GINTMSK是硬件映射的寄存器变量
根据您的描述,看起来pdev->regs.GREG
的值在某个位置被修改了。
USB_OTG_ReadPacket()看起来相当简单,但是缓冲点可能位于错误的位置并覆盖了pdev结构?
也许在此中断期间,具有不同优先级的其他中断将触发并修改pdev
结构。尝试添加__disable_irq()
和__enable_irq()
警卫
如果要移植此项目,可以考虑移动到STM32 HAL库并使用STM32CubeMX程序生成一些代码。每个版本的STM32库都会变得更好,而一些最老的库在各种优化方面都存在问题。