Jump to content

    
Sign in to follow this  
V_M_Luck

STM32 USB FS OTG

Recommended Posts

Продолжаю неспеша тупить с STM32. С Setup пакетами разобрался. Нужно вычитывать RX буфер сразу по приходу прерывания RXFLVL: RxFIFO non-empty.

Прикрутил свою либу верхнего уровня с реализованным протоколом USB CDC. Все работает за исключением обработки запроса от хоста SET LINE CODING.

 

В этом запросе две фазы.

Первая SETUP - хост присылает 8 байт собственно запрос.

Вторая DATA, где устройтсво должно принять собственно данные для установки порта - битрейт, четность и т.п. - 7 байт.

Принятие данных организовываю так же в прерывании RXFLVL. Читаю OTG_FS->GRXSTSP.

Количество байт - 7, статус - 0x02: /* OUT data packet received */. Все вроде четко. Вычитываю данные из FIFO, но вижу что данные не те, что нужно.

 

В чем подвох?

Share this post


Link to post
Share on other sites
OTG_FS_DOEPCTL0.EPENA установлен?

 

Прерывание по RXFLVL у меня построено сейчас вот так:

static void ISRH_RxFifoNonEmpty(void)
{
    UINT32 status = OTG_FS->GRXSTSP;    /* Get the Status from the top of the FIFO */
    UINT8 ep_num = ((status & OTG_FS_GRXSTSP_EPNUM_MSK) >> OTG_FS_GRXSTSP_EPNUM_POS);
    INT data_len = ((status & OTG_FS_GRXSTSP_BCNT_MSK) >> OTG_FS_GRXSTSP_BCNT_POS);
    g_EP_Desc[0].data_len = data_len;
    UINT8 packet_status = ((status & OTG_FS_GRXSTSP_PKTSTS_MSK) >> OTG_FS_GRXSTSP_PKTSTS_POS);
    
    switch(packet_status)
    {
        case 0x01:    /* Global OUT NAK (triggers an interrupt) */
            break;
                    
        case 0x02:    /* OUT data packet received */
            if(0 == ep_num)
            {
                USBD_CTRL_STATE usbd_state = USBD_DataOut();    /* Process the setup request parse */
                if(USBD_CTRL_STAGE_DATA_IN == usbd_state)    /* DATA_IN stage */
                    OTG_FS->DIEPEMPMSK |= (UINT32)1;    /* Enable TX FIFO empy intr. from EP0 */
            }
            break;
                
        case 0x03:    /*  OUT transfer completed (triggers an interrupt) */
            break;
        
        case 0x04:    /* SETUP transaction completed (triggers an interrupt) */
            break;
                
        case 0x06:    /* SETUP data packet received */
            if(0 == ep_num)
            {
                USBD_CTRL_STATE usbd_state = USBD_Setup();    /* Process the setup request parse */
                if(USBD_CTRL_STAGE_DATA_IN == usbd_state)    /* DATA_IN stage */
                    OTG_FS->DIEPEMPMSK |= (UINT32)1;    /* Enable TX FIFO empy intr. from EP0 */
            }
            break;
                
        default:
            break;
    }
}

 

Функции верхнего уровня: USBD_Setup() и USBD_DataOut() для чтения из RX буфера используют одну и ту же функцию чтения:

USBD_RESULT IUSBD_EP0_Read(P_UINT8 data, INT data_len, P_INT xfer)
{    
    if(data_len > g_EP_Desc[0].data_len)
        data_len = g_EP_Desc[0].data_len;
    g_EP_Desc[0].data_len = 0;
    
    EP_OUT_FIFO_SW_Get((void *)IUSBD_FIFO_BASE, (void *)data, data_len);    /* Read data from FIFO */
    
    OTG_FS->DOEPTSIZ0 =    /* Setup transfer size for ready to receive */
        OTG_FS_DOEPTSIZ0_XFRSIZ(USBD_CFG_DEVICE_EP0_SIZE * IUSBD_CFG_EP0_DOEPTSIZ_STUPCNT) |
        OTG_FS_DOEPTSIZ0_PKTCNT |
        OTG_FS_DOEPTSIZ0_STUPCNT(IUSBD_CFG_EP0_DOEPTSIZ_STUPCNT);
    OTG_FS->DOEPCTL0 |= (OTG_FS_DOEPCTL0_CNAK | OTG_FS_DOEPCTL0_EPENA);
    
    *xfer = data_len;
    return USBD_RES_OK;    /* OK */
}

 

Т.е. NAK и EPENA программируются сразу после вычитывания буфера.

Share this post


Link to post
Share on other sites
Так выходит, что до получения первого пакета EPENA не установлен?

 

Вот эта часть кода:

OTG_FS->DOEPTSIZ0 =    /* Setup transfer size for ready to receive */
        OTG_FS_DOEPTSIZ0_XFRSIZ(USBD_CFG_DEVICE_EP0_SIZE * IUSBD_CFG_EP0_DOEPTSIZ_STUPCNT) |
        OTG_FS_DOEPTSIZ0_PKTCNT |
        OTG_FS_DOEPTSIZ0_STUPCNT(IUSBD_CFG_EP0_DOEPTSIZ_STUPCNT);
    OTG_FS->DOEPCTL0 |= (OTG_FS_DOEPCTL0_CNAK | OTG_FS_DOEPCTL0_EPENA);

Так же исполняется по приходу прерывания USB Bus Reset. Так что точка всегда готова к приему пакетов.

И, когда приходит прерывание о новом пакете, и это DATA OUT stage - количество данных в GRXSTSP верное - 7 байт.

Только данные почему то не те, которые послал хост...

В остальном все работает нормально.

 

Данные по OUT BULK точке я еще принимать не пробовал. Пока хочу разобраться почему в буфере не то что передал хост.

Share this post


Link to post
Share on other sites
Так же исполняется по приходу прерывания USB Bus Reset. Так что точка всегда готова к приему пакетов.

EPENA сбрасывается при каждом SETUP'е, устанавливать надо непосредственно перед приемом пакета.

Share this post


Link to post
Share on other sites
EPENA сбрасывается при каждом SETUP'е, устанавливать надо непосредственно перед приемом пакета.
Не понял, что значит "устанавливать надо непосредственно перед приемом пакета".

 

 

Share this post


Link to post
Share on other sites
Не понял, что значит "устанавливать надо непосредственно перед приемом пакета".

Получили SETUP - узнали из него, что будет "продолжение" в виде OUT-транзакции - тут же на месте взвели EPENA.

Share this post


Link to post
Share on other sites
Получили SETUP - узнали из него, что будет "продолжение" в виде OUT-транзакции - тут же на месте взвели EPENA.

Но я вроде так и делаю. В функции IUSBD_EP0_Read получаю SETUP: Вычитываю данные из RX FIFO и тут же взвожу EPENA и CNAK

Share this post


Link to post
Share on other sites
Но я вроде так и делаю. В функции IUSBD_EP0_Read получаю SETUP: Вычитываю данные из RX FIFO и тут же взвожу EPENA и CNAK

Перенесите обработку SETUP сюда:

case 0x04:    /* SETUP transaction completed (triggers an interrupt) */

Именно в этот момент EPENA и снимается.

Share this post


Link to post
Share on other sites
Перенесите обработку SETUP сюда:

case 0x04:    /* SETUP transaction completed (triggers an interrupt) */

Именно в этот момент EPENA и снимается.

Спасибо. Как всегда помогли быстро разобраться. :a14: :beer:

 

Правда взвод точки я воткнул не в том месте кода, как Вы сказали, а в обработчике от OUT точки по флагу STUP (SETUP phase done) в регистре DOEPINT0. Перечитал даташит про EPENA в DOEPCTL0:

Bit 31EPENA:Endpoint enable

The application sets this bit to start transmitting data on endpoint 0.

The core clears this bit before setting any ofthe following interrupts on this endpoint:

– SETUP phase done

– Endpoint disabled

– Transfer completed

Share this post


Link to post
Share on other sites
Правда взвод точки я воткнул
Неа, не туда воткнул :) В общем сделал как советовали. Теперь код прерывания по RXFLVL выглядит вот так:

static void ISRH_RxFifoNonEmpty(void)
{
    UINT32 status = OTG_FS->GRXSTSP;    /* Get the Status from the top of the FIFO */
    UINT8 ep_num = ((status & OTG_FS_GRXSTSP_EPNUM_MSK) >> OTG_FS_GRXSTSP_EPNUM_POS);
    INT data_len = ((status & OTG_FS_GRXSTSP_BCNT_MSK) >> OTG_FS_GRXSTSP_BCNT_POS);
    g_EP_Desc[0].data_len = data_len;
    UINT8 packet_status = ((status & OTG_FS_GRXSTSP_PKTSTS_MSK) >> OTG_FS_GRXSTSP_PKTSTS_POS);
    
    switch(packet_status)
    {
        case 0x01:    /* Global OUT NAK (triggers an interrupt) */
            break;
                    
        case 0x02:    /* OUT data packet received */
            if(0 == ep_num)
            {
                USBD_CTRL_STATE usbd_state = USBD_DataOut();    /* Process the setup request parse */
                if(USBD_CTRL_STAGE_DATA_IN == usbd_state)    /* DATA_IN stage */
                    OTG_FS->DIEPEMPMSK |= (UINT32)1;    /* Enable TX FIFO empy intr. from EP0 */
            }
            break;
                
        case 0x03:    /*  OUT transfer completed (triggers an interrupt) */
            break;
        
        case 0x04:    /* SETUP transaction completed (triggers an interrupt) */
            if(0 == ep_num)
            {
                OTG_FS->DOEPTSIZ0 =    /* Setup transfer size for ready to receive */
                    OTG_FS_DOEPTSIZ0_XFRSIZ(USBD_CFG_DEVICE_EP0_SIZE * IUSBD_CFG_EP0_DOEPTSIZ_STUPCNT) |
                    OTG_FS_DOEPTSIZ0_PKTCNT |
                    OTG_FS_DOEPTSIZ0_STUPCNT(IUSBD_CFG_EP0_DOEPTSIZ_STUPCNT);
                OTG_FS->DOEPCTL0 |= (OTG_FS_DOEPCTL0_CNAK | OTG_FS_DOEPCTL0_EPENA);
            }
            break;
                
        case 0x06:    /* SETUP data packet received */
            if(0 == ep_num)
            {
                USBD_CTRL_STATE usbd_state = USBD_Setup();    /* Process the setup request parse */
                if(USBD_CTRL_STAGE_DATA_IN == usbd_state)    /* DATA_IN stage */
                    OTG_FS->DIEPEMPMSK |= (UINT32)1;    /* Enable TX FIFO empy intr. from EP0 */
            }
            break;
                
        default:
            break;
    }
}

 

Из функции IUSBD_EP0_Read код разрешения точки вообще убрал

 

 

 

 

Пожалуйста :) Правда, веселый контроллер USB у STM?
Ага веселый, но изучать все равно нужно - тренд.

 

Мне сейчас интересно посмотреть, какая будет производительность у это OTG_FS ядра. Вижу, что ни о каком двойном буферировании BULK точек в мануале речи не идет - надеюсь оно там есть на уровне ядра? Криво, конечно, что OUT буфер один общий и его нужно обязательно вычитывать сразу, но если прикрутить DMA, то, в принципе, сносно должно получится.

Share this post


Link to post
Share on other sites
Мне сейчас интересно посмотреть, какая будет производительность у это OTG_FS ядра. Вижу, что ни о каком двойном буферировании BULK точек в мануале речи не идет - надеюсь оно там есть на уровне ядра?

Уровень буферизации зависит от количества памяти, выделенной в FIFO на прием для точки: если выделить на два пакета максимального размера, то будет как раз двойная.

Share this post


Link to post
Share on other sites
Уровень буферизации зависит от количества памяти, выделенной в FIFO на прием для точки
Это то понятно. Памяти в буфере можно выделить даже на 4 размера конечной точки BULK, при чем в обе стороны.

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this