Я работаю над встроенным проектом с микроконтроллером STM32F405, и у меня несколько запутанное поведение.Я портирую существующий (рабочий) проект из STM32F1 в STM32F4, но я добавил стандартную периферийную библиотеку USB ST ST для VCP.
Если я скомпилирую программу с оптимизацией -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;
}
Я использую ванильный GNU make
и gcc-arm-none-eabi 5-4-2016q3
в качестве моего toolcahin, ванильного компоновщика STи сценарий запуска с 2015 года для STM32F405, а код VCP - с марта 2012 года. Я новичок в сценариях запуска и компоновщика, но я не вижу ничего подозрительного ни в одном из них.Я также не вижу ничего вопиющего в коде ST VCP, но я определенно не понимаю каждую строку.
У меня три вопроса:
- Похоже ли это на переполнение стека?
- Как распределяется стек для IRQ?В реализации ST прерывание VCP имеет очень глубокое дерево вызовов.Нужно ли мне просто выделять больше для IRQ VCP?
- Какие оптимизации в
-O2
могут вызвать такое поведение?Мне интересно, смогу ли я выборочно отключить некоторые оптимизации, которые могли бы помочь мне отследить мою ошибку.