реклама на сайте
подробности

 
 
> STM32F407+USB3300 потеря пакетов isochronous, бесконечное прерывание incomplite OUT
Left Radio
сообщение Sep 28 2014, 22:06
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 48
Регистрация: 4-11-08
Пользователь №: 41 361



Всем доброго времени! Прошу подскажите куда копать уже несколько дней и бессонных ночей sm.gif никак не поедут лыжи sad.gif В общем пытаюсь запустить аудио поток по HS USB используя PHY USB3300 и STM32F407VE на своей плате, устройство определяется правильно, драйвера устанавливаются для UAC1 в Win7, и нормально видится в linux в UAC1 и UAC2, но как только устройство правильно приконектилось и пошли SOF-ы начинает вызваться прерывание Incomplete isochronous OUT (INCOMPISOOUT в регистре OTG_HS_GINTSTS), причем получаю их постоянно, одно за другим, данные по EP1 естественно при этом не идут, а по EP0 обмен с компом идет нормально (иначе бы ОС не увидело бы девайса, да и перепроверил).

Я использую OTG драйвер от ST и там в обработчике DCD_IsoOUTIncomplete_ISR только сбрасывается прерывание и все, что явно в противоречии с процедурой описанной в доке (Incomplete isochronous OUT data transfers, стр. 1205), пробовал сделать обработку прерывания как там написано, но толку с этого ноль sad.gif Никак не могу понять почему происходит потеря пакетов, код рабочий, с встроенным FS PHY все работает отлично на другой плате(естественно с реконфигурацией проекта под FS).
Железо скорее всего ни причем, так как идет нормальный обмен по EP0, корректно обрабатываются запросы на дескрипторы и на установку AltSettings 0/1. В качестве проверки запускал VCP HS на устройстве с тем же драйвером OTG от ST, правда там bulk а не isochronous, но главное что работает и работает стабильно.
Дескрипторы если нужно выложу, но мне кажется скорее всего проблема не там, и еще подскажите пожалуйста по встроенному DMA под USB HS, как его настроить и куда оно будет ложить данные? Про выравнивание при его использовании знаю, в лоб включение DMA ничего не решает, все также девайс определяется правильно но и по прежнему теряются пакеты sad.gif

Буду рад за любую подсказку, спасибо!

Сообщение отредактировал Left Radio - Sep 29 2014, 01:21
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Left Radio
сообщение Oct 1 2014, 21:42
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 48
Регистрация: 4-11-08
Пользователь №: 41 361



Interrupt тут не причем я жду прерывания по готовности данных в приемном FIFO, вот часть рекомендуемой последовательности в RM0090(стр. 1205):
3. In Slave mode, wait for the RXFLVL interrupt (in OTG_HS_GINTSTS) and empty the
data packets from the receive FIFO
– This step can be repeated many times, depending on the transfer size.
4. The assertion of the XFRC interrupt (in OTG_HS_DOEPINTx) marks the completion of
the isochronous OUT data transfer. This interrupt does not necessarily mean that the
data in memory are good.

Таймер запустить и синхронизировать с SOF не проблема, но зачем, надо будет к тому же ждать пока весь кадр ляжет в FIFO, да и ведь уже есть прерывания SOF/EOPF, можно забирать данные по тому же принципу по SOF, или в крайнем случае по EOPF, хотя последнее противоречит доке. Да и это не работает, такое впечатление что что то не так с самим Iso OUT EP в HS или проблема с организацией самой изохронной передачи в HS core, но это только впечатление. Возможно также я не правильно читаю FIFO, но тут тоже не до конца понятно, в FS где тот же проект(естественно сконфигурированный под FS) работает правильно wacko.gif, и когда приходит прерывание XFRC данные уже лежат в буфере который я указал при инициализации EP(эти функции собственно часть библиотеки STM):

CODE

uint8_t usbd_audio_Init (void *pdev, uint8_t cfgidx)
{
/* Open EP OUT */
DCD_EP_Open((USB_OTG_CORE_HANDLE*)&USB_OTG_dev, AUDIO_OUT_EP, AUDIO_OUT_PACKET, USB_OTG_EP_ISOC);

/* Initialize the Audio output Hardware layer */
if (AUDIO_OUT_fops.Init(AUDIO_FREQUENCY, DEFAULT_VOLUME, 0) != USBD_OK)
{
return USBD_FAIL;
}

/* Prepare Out endpoint to receive audio data */
DCD_EP_PrepareRx((USB_OTG_CORE_HANDLE*)&USB_OTG_dev, AUDIO_OUT_EP, (uint8_t*)IsocOutWrPtr, AUDIO_OUT_PACKET);

return USBD_OK;
}


uint32_t DCD_EP_Open(USB_OTG_CORE_HANDLE *pdev ,
uint8_t ep_addr,
uint16_t ep_mps,
uint8_t ep_type)
{
USB_OTG_EP *ep;

if ((ep_addr & 0x80) == 0x80)
{
ep = &pdev->dev.in_ep[ep_addr & 0x7F];
}
else
{
ep = &pdev->dev.out_ep[ep_addr & 0x7F];
}
ep->num = ep_addr & 0x7F;

ep->is_in = (0x80 & ep_addr) != 0;
ep->maxpacket = ep_mps;
ep->type = ep_type;
if (ep->is_in)
{
/* Assign a Tx FIFO */
ep->tx_fifo_num = ep->num;
}
/* Set initial data PID. */
if (ep_type == USB_OTG_EP_BULK )
{
ep->data_pid_start = 0;
}
USB_OTG_EPActivate(pdev , ep );
return 0;
}

uint32_t DCD_EP_PrepareRx( USB_OTG_CORE_HANDLE *pdev,
uint8_t ep_addr,
uint8_t *pbuf,
uint16_t buf_len)
{
USB_OTG_EP *ep;

ep = &pdev->dev.out_ep[ep_addr & 0x7F];

/*setup and start the Xfer */
ep->xfer_buff = pbuf;
ep->xfer_len = buf_len;
ep->xfer_count = 0;
ep->is_in = 0;
ep->num = ep_addr & 0x7F;

if (pdev->cfg.dma_enable == 1)
{
ep->dma_addr = (uint32_t)pbuf;
}

if ( ep->num == 0 )
{
USB_OTG_EP0StartXfer(pdev , ep);
}
else
{
USB_OTG_EPStartXfer(pdev, ep );
}
return 0;
}


USB_OTG_STS USB_OTG_EPActivate(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep)
{
USB_OTG_STS status = USB_OTG_OK;
USB_OTG_DEPCTL_TypeDef depctl;
USB_OTG_DAINT_TypeDef daintmsk;
__IO uint32_t *addr;


depctl.d32 = 0;
daintmsk.d32 = 0;
/* Read DEPCTLn register */
if (ep->is_in == 1)
{
addr = &pdev->regs.INEP_REGS[ep->num]->DIEPCTL;
daintmsk.ep.in = 1 << ep->num;
}
else
{
addr = &pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL;
daintmsk.ep.out = 1 << ep->num;
}
/* If the EP is already active don't change the EP Control
* register. */
depctl.d32 = USB_OTG_READ_REG32(addr);
if (!depctl.b.usbactep)
{
depctl.b.mps = ep->maxpacket;
depctl.b.eptype = ep->type;
depctl.b.txfnum = ep->tx_fifo_num;
depctl.b.setd0pid = 1;
depctl.b.usbactep = 1;
USB_OTG_WRITE_REG32(addr, depctl.d32);
}
/* Enable the Interrupt for this EP */
#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED
if((ep->num == 1)&&(pdev->cfg.coreID == USB_OTG_HS_CORE_ID))
{
USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DEACHMSK, 0, daintmsk.d32);
}
else
#endif
USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DAINTMSK, 0, daintmsk.d32);
return status;
}

USB_OTG_STS USB_OTG_EPStartXfer(USB_OTG_CORE_HANDLE *pdev , USB_OTG_EP *ep)
{
USB_OTG_STS status = USB_OTG_OK;
USB_OTG_DEPCTL_TypeDef depctl;
USB_OTG_DEPXFRSIZ_TypeDef deptsiz;
USB_OTG_DSTS_TypeDef dsts;
uint32_t fifoemptymsk = 0;

depctl.d32 = 0;
deptsiz.d32 = 0;
/* IN endpoint */
if (ep->is_in == 1)
{
depctl.d32 = USB_OTG_READ_REG32(&(pdev->regs.INEP_REGS[ep->num]->DIEPCTL));
deptsiz.d32 = USB_OTG_READ_REG32(&(pdev->regs.INEP_REGS[ep->num]->DIEPTSIZ));
/* Zero Length Packet? */
if (ep->xfer_len == 0)
{
deptsiz.b.xfersize = 0;
deptsiz.b.pktcnt = 1;
}
else
{
/* Program the transfer size and packet count
* as follows: xfersize = N * maxpacket +
* short_packet pktcnt = N + (short_packet
* exist ? 1 : 0)
*/
deptsiz.b.xfersize = ep->xfer_len;
deptsiz.b.pktcnt = (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket;

if (ep->type == EP_TYPE_ISOC)
{
deptsiz.b.mc = 1;
}
}
USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[ep->num]->DIEPTSIZ, deptsiz.d32);

if (pdev->cfg.dma_enable == 1)
{
USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[ep->num]->DIEPDMA, ep->dma_addr);
}
else
{
if (ep->type != EP_TYPE_ISOC)
{
/* Enable the Tx FIFO Empty Interrupt for this EP */
if (ep->xfer_len > 0)
{
fifoemptymsk = 1 << ep->num;
USB_OTG_MODIFY_REG32(&pdev->regs.DREGS->DIEPEMPMSK, 0, fifoemptymsk);
}
}
}


if (ep->type == EP_TYPE_ISOC)
{
dsts.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DSTS);

if (((dsts.b.soffn)&0x1) == 0)
{
depctl.b.setd1pid = 1;
}
else
{
depctl.b.setd0pid = 1;
}
}

/* EP enable, IN data in FIFO */
depctl.b.cnak = 1;
depctl.b.epena = 1;
USB_OTG_WRITE_REG32(&pdev->regs.INEP_REGS[ep->num]->DIEPCTL, depctl.d32);

if (ep->type == EP_TYPE_ISOC)
{
USB_OTG_WritePacket(pdev, ep->xfer_buff, ep->num, ep->xfer_len);
}
}
else
{
/* OUT endpoint */
depctl.d32 = USB_OTG_READ_REG32(&(pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL));
deptsiz.d32 = USB_OTG_READ_REG32(&(pdev->regs.OUTEP_REGS[ep->num]->DOEPTSIZ));
/* Program the transfer size and packet count as follows:
* pktcnt = N
* xfersize = N * maxpacket
*/
if (ep->xfer_len == 0)
{
deptsiz.b.xfersize = ep->maxpacket;
deptsiz.b.pktcnt = 1;
}
else
{
deptsiz.b.pktcnt = (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket;
deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket;
}
USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPTSIZ, deptsiz.d32);

if (pdev->cfg.dma_enable == 1)
{
USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPDMA, ep->dma_addr);
}

if (ep->type == EP_TYPE_ISOC)
{
if (ep->even_odd_frame)
{
depctl.b.setd1pid = 1;
}
else
{
depctl.b.setd0pid = 1;
}
}
/* EP enable */
depctl.b.cnak = 1;
depctl.b.epena = 1;
USB_OTG_WRITE_REG32(&pdev->regs.OUTEP_REGS[ep->num]->DOEPCTL, depctl.d32);
}
return status;
}



А значит вычитка FIFO произошла до прерывания XFRC, скорее всего по прерываниям RXFLVL как и рекомендовано в доке. И все это прекрасно работает в FS режиме, а после переконфигурации на HS ядро, внешний PHY, и правки дескрипторов, начинаются вот такие чудеса с прерываниями IINCOMPISOOUT и как следствие блокированием прерываний RXFLVL и XFRC sad.gif , возможно есть какие либо особенности при работе isochronous в HS по сравнению с FS не знаю, пока ничего такого не нашел.
Но это все может оказаться бесполезным, так как не ясен источник IINCOMPISOOUT, если это искажение данных пакетов и/или неверный CRC, то как бы не читать будет явно не нормально sad.gif, как выяснить источник этого прерывания так и остается неясным. Как вариант можно заподозрить и аппаратную часть если бы не нормальная работа в VCP HS режиме, о чем писал раньше, наигрался я с этим примером достаточно, начинаются проблемы только когда сбиваю кварц МК или кварц USB3300 sm.gif.

Сообщение отредактировал Left Radio - Oct 1 2014, 22:20
Go to the top of the page
 
+Quote Post

Сообщений в этой теме


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 29th July 2025 - 09:59
Рейтинг@Mail.ru


Страница сгенерированна за 0.01536 секунд с 7
ELECTRONIX ©2004-2016