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

 
 
10 страниц V  « < 2 3 4 5 6 > »   
Reply to this topicStart new topic
> STM32 USB FS OTG
prottoss
сообщение Nov 7 2015, 18:41
Сообщение #46


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Продолжаю неспеша тупить с 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, но вижу что данные не те, что нужно.

В чем подвох?


--------------------
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 7 2015, 18:48
Сообщение #47


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(prottoss @ Nov 7 2015, 21:41) *
В чем подвох?

OTG_FS_DOEPCTL0.EPENA установлен?
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2015, 18:54
Сообщение #48


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(aaarrr @ Nov 8 2015, 00:48) *
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 программируются сразу после вычитывания буфера.


--------------------
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 7 2015, 19:02
Сообщение #49


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(prottoss @ Nov 7 2015, 21:54) *
Т.е. NAK и EPENA программируются сразу после вычитывания буфера.

Так выходит, что до получения первого пакета EPENA не установлен?
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2015, 19:08
Сообщение #50


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(aaarrr @ Nov 8 2015, 01:02) *
Так выходит, что до получения первого пакета 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 точке я еще принимать не пробовал. Пока хочу разобраться почему в буфере не то что передал хост.


--------------------
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 7 2015, 19:29
Сообщение #51


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(prottoss @ Nov 7 2015, 22:08) *
Так же исполняется по приходу прерывания USB Bus Reset. Так что точка всегда готова к приему пакетов.

EPENA сбрасывается при каждом SETUP'е, устанавливать надо непосредственно перед приемом пакета.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2015, 19:44
Сообщение #52


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(aaarrr @ Nov 8 2015, 01:29) *
EPENA сбрасывается при каждом SETUP'е, устанавливать надо непосредственно перед приемом пакета.
Не понял, что значит "устанавливать надо непосредственно перед приемом пакета".



--------------------
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 7 2015, 19:47
Сообщение #53


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(prottoss @ Nov 7 2015, 22:44) *
Не понял, что значит "устанавливать надо непосредственно перед приемом пакета".

Получили SETUP - узнали из него, что будет "продолжение" в виде OUT-транзакции - тут же на месте взвели EPENA.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2015, 19:51
Сообщение #54


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(aaarrr @ Nov 8 2015, 01:47) *
Получили SETUP - узнали из него, что будет "продолжение" в виде OUT-транзакции - тут же на месте взвели EPENA.

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


--------------------
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 7 2015, 19:55
Сообщение #55


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(prottoss @ Nov 7 2015, 22:51) *
Но я вроде так и делаю. В функции IUSBD_EP0_Read получаю SETUP: Вычитываю данные из RX FIFO и тут же взвожу EPENA и CNAK

Перенесите обработку SETUP сюда:
Код
case 0x04:    /* SETUP transaction completed (triggers an interrupt) */

Именно в этот момент EPENA и снимается.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2015, 20:16
Сообщение #56


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(aaarrr @ Nov 8 2015, 01:55) *
Перенесите обработку SETUP сюда:
Код
case 0x04:    /* SETUP transaction completed (triggers an interrupt) */

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

Правда взвод точки я воткнул не в том месте кода, как Вы сказали, а в обработчике от 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


--------------------
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 7 2015, 20:28
Сообщение #57


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(prottoss @ Nov 7 2015, 23:16) *
Спасибо.

Пожалуйста sm.gif Правда, веселый контроллер USB у STM?
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2015, 20:37
Сообщение #58


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(prottoss @ Nov 8 2015, 02:16) *
Правда взвод точки я воткнул
Неа, не туда воткнул sm.gif В общем сделал как советовали. Теперь код прерывания по 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 код разрешения точки вообще убрал




Цитата(aaarrr @ Nov 8 2015, 02:28) *
Пожалуйста sm.gif Правда, веселый контроллер USB у STM?
Ага веселый, но изучать все равно нужно - тренд.

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


--------------------
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 7 2015, 20:59
Сообщение #59


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(prottoss @ Nov 7 2015, 23:37) *
Мне сейчас интересно посмотреть, какая будет производительность у это OTG_FS ядра. Вижу, что ни о каком двойном буферировании BULK точек в мануале речи не идет - надеюсь оно там есть на уровне ядра?

Уровень буферизации зависит от количества памяти, выделенной в FIFO на прием для точки: если выделить на два пакета максимального размера, то будет как раз двойная.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2015, 21:06
Сообщение #60


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(aaarrr @ Nov 8 2015, 02:59) *
Уровень буферизации зависит от количества памяти, выделенной в FIFO на прием для точки
Это то понятно. Памяти в буфере можно выделить даже на 4 размера конечной точки BULK, при чем в обе стороны.


--------------------
Go to the top of the page
 
+Quote Post

10 страниц V  « < 2 3 4 5 6 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 04:33
Рейтинг@Mail.ru


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