Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32 USB FS OTG
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2, 3
aaarrr
Цитата(prottoss @ Nov 7 2015, 22:08) *
Так же исполняется по приходу прерывания USB Bus Reset. Так что точка всегда готова к приему пакетов.

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

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

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

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

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

Именно в этот момент EPENA и снимается.
prottoss
Цитата(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
aaarrr
Цитата(prottoss @ Nov 7 2015, 23:16) *
Спасибо.

Пожалуйста sm.gif Правда, веселый контроллер USB у STM?
prottoss
Цитата(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, то, в принципе, сносно должно получится.
aaarrr
Цитата(prottoss @ Nov 7 2015, 23:37) *
Мне сейчас интересно посмотреть, какая будет производительность у это OTG_FS ядра. Вижу, что ни о каком двойном буферировании BULK точек в мануале речи не идет - надеюсь оно там есть на уровне ядра?

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

Вот не уверен. Вручную запрягать и обслуживать M2M на каждый чих может оказаться накладнее, чем быстренько выгрузить данные программно.
prottoss
Поднял на собственном стеке HID с двумя INT точками. Сделал эхо. Все прекрасно работает. Производительность не измерял пока.
Есть непонимание по одному вопросу: Есть регистры, задающие размерность FIFO для IN конечных точек. Это OTG_FS_DIEPTXF0 для контрольной точки и OTG_FS_DIEPTXFx для рабочих точек.
С полем INEPTXFD все понятно. В мануале прямо про них написано:
Цитата
Bits 31:16INEPTXFD:IN endpoint TxFIFO depth
This value is in terms of 32-bit words.
Minimum value is 16
The power-on reset value of this register is specified as the largest IN endpoint FIFO
number depth.

С полем INEPTXSA, у меня, полного понимания нет. Описание в доке:
Цитата
INEPTXSA:IN endpoint FIFOx transmit RAM start address
This field contains the memory start address for IN endpoint transmit FIFOx. The address
must be aligned with a 32-bit memory location.
Т.е. вроде как исчисление в этом поле в байтах, но число должно быть выровнено на 32 бита.
Посмотрел примеры от ST. Там берется, к примеру, размер буфера в 32-бит словах (как и нужно), и это значение используется для вычисления адреса следующего буфера... Т.е. значение не делится на 4 для получения смещения в байтах...
Посмотрел в отладчике состояние этих регистров по умолчанию после инициализации OTG - там, судя по дефолтным значениям полей, происходит то же самое. Правда, для последних регистров, в итоге, занчение адреса вылезает за пределы максимального размера памяти OTG... Хоть в байтах, хоть в 32-бит словах. Опять веселье (С)aaarrr

Извините, может немного сумбурно объяснил вопрос.
aaarrr
Цитата(prottoss @ Nov 20 2015, 15:26) *
Т.е. вроде как исчисление в этом поле в байтах, но число должно быть выровнено на 32 бита.

Нет, все в словах исчисляется. FIFO у них иной адресации и не имеет.
Tarbal
Цитата(prottoss @ Nov 8 2015, 00:37) *
Мне сейчас интересно посмотреть, какая будет производительность у это OTG_FS ядра. Вижу, что ни о каком двойном буферировании BULK точек в мануале речи не идет - надеюсь оно там есть на уровне ядра? Криво, конечно, что OUT буфер один общий и его нужно обязательно вычитывать сразу, но если прикрутить DMA, то, в принципе, сносно должно получится.


Расскажите дилетанту для чего в USB нужен DMA пожалуйста. Ведь если посылать полные пакеты по 64 байта, то уже вроде как железо заполнит само буфер и вызовет одно прерывание на принятых 64 байта. Или речь идет о коротких пакетах? Вероятно я не вижу подводных камней.
prottoss
Цитата(aaarrr @ Nov 20 2015, 19:09) *
Нет, все в словах исчисляется. FIFO у них иной адресации и не имеет.
Зачем тогда написано, что в поле адреса должно быть загружено значение, выровненное на 32 бита? Как можно не выровнять то, что уже выровнено?


Цитата(Tarbal @ Nov 20 2015, 19:28) *
Расскажите дилетанту для чего в USB нужен DMA пожалуйста. Ведь если посылать полные пакеты по 64 байта, то уже вроде как железо заполнит само буфер и вызовет одно прерывание на принятых 64 байта. Или речь идет о коротких пакетах? Вероятно я не вижу подводных камней.
Ну хотя бы для того чтобы переслать данные из памяти USB в порт, минуя копирование данных в память. Вроде как в stm32 otg это можно сделать, хотя, я еще не пробовал. За выходные вечера хочу попробовать. Организация FIFO, на мой взгляд, позволяет это сделать. При запуске трансфера настроить точку и канал, и по прерываниям по приему стартовать канал DMA.
aaarrr
Цитата(Tarbal @ Nov 20 2015, 16:28) *
Ведь если посылать полные пакеты по 64 байта, то уже вроде как железо заполнит само буфер и вызовет одно прерывание на принятых 64 байта.

Именно что буфер FIFO заполнит, а не буфер в памяти процессора.

Цитата(prottoss @ Nov 20 2015, 16:37) *
Зачем тогда написано, что в поле адреса должно быть загружено значение, выровненное на 32 бита? Как можно не выровнять то, что уже выровнено?

Загадка-с. Выразились неудачно, CCCV и тому подобное.
prottoss
Ну и по передаче так же.

Цитата(aaarrr @ Nov 20 2015, 19:46) *
Загадка-с. Выразились неудачно, CCCV и тому подобное.
Что такое CCCV? sm.gif
aaarrr
Цитата(prottoss @ Nov 20 2015, 16:45) *
При запуске трансфера настроить точку и канал, и по прерываниям по приему стартовать канал DMA.

64 байта пакета - это всего 16 слов, возможность выигрыша в такой конфигурации представляется сомнительной.
prottoss
Цитата(aaarrr @ Nov 20 2015, 19:46) *
Выразились неудачно
Т.е. Вы уверены, что поле адреса - это 32-бит значения?
aaarrr
Цитата(prottoss @ Nov 20 2015, 16:47) *
Что такое CCCV? sm.gif

Ctrl-C Ctrl-V, copy-paste sm.gif

Цитата(prottoss @ Nov 20 2015, 16:48) *
Т.е. Вы уверены, что поле адреса - это 32-бит значения?

Честно скажу, не проверял. Но логика организации FIFO не позволяет думать иначе.
Tarbal
Цитата(prottoss @ Nov 20 2015, 17:45) *
Ну хотя бы для того чтобы переслать данные из памяти USB в порт, минуя копирование данных в память. Вроде как в stm32 otg это можно сделать, хотя, я еще не пробовал. За выходные вечера хочу попробовать. Организация FIFO, на мой взгляд, позволяет это сделать. При запуске трансфера настроить точку и канал, и по прерываниям по приему стартовать канал DMA.


Спасибо. Значит я все правильно понял.
prottoss
Цитата(aaarrr @ Nov 20 2015, 19:48) *
64 байта пакета - это всего 16 слов, возможность выигрыша в такой конфигурации представляется сомнительной.
Согласен. Я не пробовал еще DMA, но, может быть есть возможность быстро его стартануть...


Цитата(aaarrr @ Nov 20 2015, 19:50) *
Честно скажу, не проверял. Но логика организации FIFO не позволяет думать иначе.
Хм. Логика понятна - доступ только 32 бит ИО, по этому размер задается в словах. Но смещение то не обязательно должно задаваться словами...
aaarrr
Цитата(aaarrr @ Nov 20 2015, 16:50) *
Честно скажу, не проверял. Но логика организации FIFO не позволяет думать иначе.

Поясню: я исходил из адресации в словах, в программе задействован не один буфер, каких-либо проблем и накладок не обнаружено.
prottoss
Размер трансфера данных задается все таки в байтах

Цитата(aaarrr @ Nov 20 2015, 19:55) *
Поясню: я исходил из адресации в словах, в программе задействован не один буфер, каких-либо проблем и накладок не обнаружено.
Я тоже, в своей программе задал буфера так, что они в любом случае, не пересекаются. Значит буду пробовать делать крэш.
Tarbal
Цитата(aaarrr @ Nov 8 2015, 01:15) *
Вот не уверен. Вручную запрягать и обслуживать M2M на каждый чих может оказаться накладнее, чем быстренько выгрузить данные программно.


Или просто переставить указатель на буфер, а этот буфер в обработку. Хотя M2M надо тоже переставить указатели и стартануть -- не так много действий.
prottoss
Вернусь к вопросу использования DMA.
Цитата(aaarrr @ Nov 20 2015, 19:48) *
64 байта пакета - это всего 16 слов, возможность выигрыша в такой конфигурации представляется сомнительной.

Для OUT передач это, возможно, и верно, т.к. для BULK и INT трансферов 64 байта - это максимум. Я проверил на HID и на CDC с штатным Windows драйвером usbser.sys.
Для IN передач все намного радужнее. У IN точек есть персональный хардварный буфер, который может быть по размеру намного больше чем размер точки. Т.е. к примеру, если точка имеет размер 64 байта, я свободного могу сделать буфер размером, к примеру, в 512 байт и загрузить его полностью используя DMA. В данном случае будет явный прирост производительности.

Жаль, конечно, что для OUT точек сделали какой то кастрированный общий буфер...
prottoss
Продолжаю потихоньку грызть OTG.

Построил USB MSD устройство. Столкнулся с вот такой проблемой:

Рабочая конфигурация FIFO:
1. OUT FIFO - 128 байт. (Возможны и другие варианты).
2. IN FIFO для EP0 - 64 байта.
3. IN FIFO для EP1 (MSD bulk IN) < 512 байт. Любой значение в пределах 64 * (1..7)
так все работает прекрасно.

Если ставлю IN FIFO для EP1 =512 или более - передача в хост затыкается на команде SCSI Read10 чтения 0 сектора. Состояние регистров EP1 IN становится вот такое:
В регистре DIEPCTL1 бит EPENA установлен, что говорит о том, что точка занята (в режиме передачи).
В регистре DIEPSIZ1 поле PKTCNT равно количеству 64 бит пакетов, т.е. 512/64 = 8. Поле XFRSIZ = 0;
В регистре DTXFSTS1 поле INEPTFSAV = 0 - Буфер полный.

Хост, при этом, передачу не видит.

Сделал обманку в обработчике прерываний от Tx FIFO empty - в прерывании гружу не все, что нужно, а только 64/128/192 байт. Все начинает работать как часы.
Если гружу 256 байт или больше опять зависон на передаче 512 байт сектора.

В чем может быть проблема?

Шаманъ
Подниму темку в связи со схожим вопросом...
Цитата(prottoss @ Dec 18 2015, 14:19) *
Построил USB MSD устройство. Столкнулся с вот такой проблемой:

Если ставлю IN FIFO для EP1 =512 или более - передача в хост затыкается на команде SCSI Read10 чтения 0 сектора. Состояние регистров EP1 IN становится вот такое:
В регистре DIEPCTL1 бит EPENA установлен, что говорит о том, что точка занята (в режиме передачи).
В регистре DIEPSIZ1 поле PKTCNT равно количеству 64 бит пакетов, т.е. 512/64 = 8. Поле XFRSIZ = 0;
В регистре DTXFSTS1 поле INEPTFSAV = 0 - Буфер полный.

Хост, при этом, передачу не видит.


CDC устройство (свое), данные ходят через BULK EP1. Работает все, кроме передачи данных от девайса к хосту (при этом через EP0 ответы проходят нормально, код пересылки данных на 99% общий). После записи в TX FIFO EP1 остается в таком виде:
DIEPCTL1 = 0x80498040, т.е. EPENA установлен
DIEPSIZ1 = 0x80000, поле PKTCNT=1, поле XFRSIZ = 0 (изначально отправлялся 1 пакет размером 5 байт, соответственно было 0x80005)
DTXFSTS1 = 14, исходный размер был 16 слов, записал 5байт (=2 слова), т.е. все логично.
Если писать данные дальше, то буфер заполняется и все. crying.gif

Ситуация почти 1:1 с Вашей, интересно что это может быть, и чем все закончилось у Вас?
P.S. Да, камень STM32F746
Genadi Zawidowski
Я эту ситуацию ловил как результат порчи FIFO из-за взаимного перекрытия областей разных ендпоинтов.
Не совсем как в документации инициализирую GRXFSIZ - если точно по формуле, висим. Попробуйте увеличить, не забывая про размер FIFO (для FS - 1280 байт).
У меня опытным путем получено addplaces = 3
to Шаманъ: а попробовать мой исходник затащить? На каждом углу же предлагаю взять...

CODE
static uint32_t usbd_makefifoparam(uint_fast16_t base, uint_fast16_t size)
{
return ((uint32_t) size << 16) | base;
}

// Преобразование размера в байтах размера данных в требования к fifo
// Расчет аргумента функции HAL_PCDEx_SetRxFiFo, HAL_PCDEx_SetTxFiFo
static uint_fast16_t size2buff4(uint_fast16_t size)
{
const uint_fast16_t size4 = (size + 3) / 4; // размер в 32-бит значениях
return ulmax16(0x10, size4);
}

static void usbd_fifo_initialize(PCD_HandleTypeDef * hpcd, uint_fast16_t fullsize)
{
PCD_TypeDef * const instance = hpcd->Instance;

// DocID028270 Rev 2 (RM0410): 41.11.3 FIFO RAM allocation
// DocID028270 Rev 2 (RM0410): 41.16.6 Device programming model
uint_fast16_t maxoutpacketsize4 = size2buff4(USB_OTG_MAX_EP0_SIZE);
//uint_fast16_t base4;
uint_fast8_t numcontrolendpoints = 1;
uint_fast8_t numoutendpoints = 1;

// при addplaces = 3 появился звук на передаче в трансивер (при 2-х компортах)
// но если CDC и UAC включать поодиночке, обмен не нарушается и при 0.
// todo: найти все-таки документ https://www.synopsys.com/ip_prototyping_kit...tgv2_drd_pc.pdf

uint_fast8_t addplaces = 3;

#if WITHUSBUAC
numoutendpoints += 1;
#if WITHRTS96
enum { nuacinpackets = 1, nuacoutpackets = 1 };
#elif WITHRTS192
enum { nuacinpackets = 1, nuacoutpackets = 1 };
#else /* WITHRTS96 || WITHRTS192 */
enum { nuacinpackets = 2, nuacoutpackets = 2 };
#endif /* WITHRTS96 || WITHRTS192 */
const uint_fast16_t uacinmaxpacket = uasbd_getuacinmaxpacket();
maxoutpacketsize4 = ulmax16(maxoutpacketsize4, nuacoutpackets * size2buff4(VIRTUAL_AUDIO_PORT_DATA_SIZE_OUT));
#endif /* WITHUSBUAC */

#if WITHUSBCDC
numoutendpoints += 2;
#if WITHUSBUAC
#if WITHRTS96 || WITHRTS192
enum { ncdcindatapackets = 3, ncdcoutdatapackets = 4 };
#else /* WITHRTS96 || WITHRTS192 */
enum { ncdcindatapackets = 2, ncdcoutdatapackets = 2 };
#endif /* WITHRTS96 || WITHRTS192 */
#else /* WITHUSBUAC */
enum { ncdcindatapackets = 4, ncdcoutdatapackets = 4 };
#endif /* WITHUSBUAC */

maxoutpacketsize4 = ulmax16(maxoutpacketsize4, ncdcoutdatapackets * size2buff4(VIRTUAL_COM_PORT_DATA_SIZE));
#endif /* WITHUSBCDC */

#if WITHUSBCDCEEM
numoutendpoints += 1;
#if WITHUSBUAC
#if WITHRTS96 || WITHRTS192
enum { ncdceemindatapackets = 3, ncdceemoutdatapackets = 4 };
#else /* WITHRTS96 || WITHRTS192 */
enum { ncdceemindatapackets = 2, ncdceemoutdatapackets = 2 };
#endif /* WITHRTS96 || WITHRTS192 */
#else /* WITHUSBUAC */
enum { ncdceemindatapackets = 4, ncdceemoutdatapackets = 4 };
#endif /* WITHUSBUAC */

maxoutpacketsize4 = ulmax16(maxoutpacketsize4, ncdceemoutdatapackets * size2buff4(USBD_CDCEEM_BUFSIZE));
#endif /* WITHUSBCDCEEM */

uint_fast16_t base4;
uint_fast16_t size4;

{
/* Установить размер RX FIFO */
// (4 * number of control endpoints + 6) +
// ((largest USB packet used / 4) + 1 for status information) +
// (2 * number of OUT endpoints) +
// 1 for Global NAK
size4 =
(4 * numcontrolendpoints + 6) +
(maxoutpacketsize4 + 1) +
(2 * numoutendpoints) +
1 +
addplaces;

instance->GRXFSIZ = size4;
base4 = size4;

/* Установить размер TX FIFO EP0 */
size4 = 2 * (size2buff4(USB_OTG_MAX_EP0_SIZE) + 0);
instance->DIEPTXF0_HNPTXFSIZ = usbd_makefifoparam(base4, size4);
base4 += size4;
}

#if WITHUSBUAC
{
/* endpoint передачи звука в компютер */
const uint_fast8_t pipe = USBD_EP_ISOC_IN & 0x7F;

size4 = nuacinpackets * (size2buff4(uacinmaxpacket) + 0);
instance->DIEPTXF [pipe - 1] = usbd_makefifoparam(base4, size4);
base4 += size4;
}

#endif /* WITHUSBUAC */

#if WITHUSBCDC

{
/* полнофункциональное устройство */
const uint_fast8_t pipe = USBD_EP_CDC_IN & 0x7F;

size4 = ncdcindatapackets * (size2buff4(VIRTUAL_COM_PORT_DATA_SIZE) + 0);
instance->DIEPTXF [pipe - 1] = usbd_makefifoparam(base4, size4);
base4 += size4;
}

/* Эти endpoints не используются для обмена */
size4 = 0x10;
instance->DIEPTXF [(USBD_EP_CDC_INT & 0x7F) - 1] = usbd_makefifoparam(base4, size4);
instance->DIEPTXF [(USBD_EP_CDC_INb & 0x7F) - 1] = usbd_makefifoparam(base4, size4);
instance->DIEPTXF [(USBD_EP_CDC_INTb & 0x7F) - 1] = usbd_makefifoparam(base4, size4);

#endif /* WITHUSBCDC */

#if WITHUSBCDCEEM

{
/* полнофункциональное устройство */
const uint_fast8_t pipe = USBD_EP_CDCEEM_IN & 0x7F;

size4 = ncdceemindatapackets * (size2buff4(USBD_CDCEEM_BUFSIZE) + 0);
instance->DIEPTXF [pipe - 1] = usbd_makefifoparam(base4, size4);
base4 += size4;
}

#endif /* WITHUSBCDCEEM */

USB_FlushRxFifo(instance);
USB_FlushTxFifoAll(instance);

if ((base4 * 4) > fullsize)
{
char b [32];
debug_printf_P(PSTR("usbd_fifo_initialize error: base4=%u, fullsize=%u\n"), (base4 * 4), fullsize);
local_snprintf_P(b, sizeof b / sizeof b [0], PSTR("used=%u"), (base4 * 4));
display_setcolors(COLOR_RED, BGCOLOR);
display_at(0, 0, cool.gif;
for (;;)
;
}
else
{
debug_printf_P(PSTR("usbd_fifo_initialize: base4=%u, fullsize=%u\n"), (base4 * 4), fullsize);
#if 0
// Диагностическая выдача использованного объёма FIFO RAM
char b [32];

local_snprintf_P(b, sizeof b / sizeof b [0], PSTR("used=%u"), (base4 * 4));
display_setcolors(COLOR_GREEN, BGCOLOR);
display_at(0, 0, cool.gif;
local_delay_ms(2000);
#endif
}
}
Шаманъ
Цитата(Genadi Zawidowski @ Mar 20 2017, 03:43) *
Я эту ситуацию ловил как результат порчи FIFO из-за взаимного перекрытия областей разных ендпоинтов.

Геннадий приветствую!
Спасибо за ответ. Я вчера обнаружил похожую тему https://community.st.com/thread/15083

Вот оттуда про магическое число 3 sm.gif:
Цитата
I have found this comment in the HAL_PCDEx_SetTxFiFo function code (Cube lib 1.6.0):

"When DMA is used 3n * FIFO locations should be reserved for internal DMA registers"


Но тут речь про TXFIFO и про DMA. У Вас же RXFIFO, а у меня DMA нет...

Цитата
Не совсем как в документации инициализирую GRXFSIZ - если точно по формуле, висим. Попробуйте увеличить, не забывая про размер FIFO (для FS - 1280 байт).
У меня опытным путем получено addplaces = 3

Причем, что интересно EP0 работает нормально, а у нее FIFO как раз за RXFIFO - получается фигня какая-то...

Цитата
to Шаманъ: а попробовать мой исходник затащить? На каждом углу же предлагаю взять...

Заглянул - у меня совсем другая концепция построения модуля (я не пытаюсь сваять еще одного сколь-либо универсального монстра - минимум кода, минимум памяти, максимум быстродействия). Библиотеки от STM я не использую - все свое. Но всеравно спасибо!

Кстати про FIFO и доки. В доках написано несколько туманно, но по факту OTG_DIEPTXF0 и OTG_DIEPTXF1 адресуют один и тот же регистр.

Кстати, а какие размеры fifo и их адреса вызывали проблемы, а какие были рабочими? Может удастся установить связь и найти корень зла sm.gif
Genadi Zawidowski
Рабочие в проекте. Проблемы если по формуле (там где кодичество IN уendpoints итак далее учитываетмся). GRXFSIZ увеличивайте пока не заработает. DMA я не использовал (хотя и с ним работает).
Или - попробуйте для TX FIFO выделять память от конца - а в GRXFSIZ все что останется...

Или - срисуйте с моего проекта для Вашего конкретного случая распределение памяти FIFO под CDC - и проверьте, работает или нет, что виновато - остальной код или эта часть.
Да хоть пополам разделите 1280.

ps: в аттачменте - тестовый бинарник под плату STM32F746G-DISCO, на FS порту создает два компорта и аудио. Один из компортов - кенвудовский CAT.
Шаманъ
Цитата(Genadi Zawidowski @ Mar 20 2017, 11:42) *
Проблемы если по формуле (там где кодичество IN уendpoints итак далее учитываетмся). GRXFSIZ увеличивайте пока не заработает.

У меня изначально под RXFIFO выделялось памяти намного больше, чем в формуле. Одну проблему нашел, исправил, проблема была очень глупой (описка).

Получил первый пакет на компе (пока в сниффере). Потом затык с теми же симптомами. Вызывает подозрение этот фрагмент (стрелочками отметил, что это такое непонятно):
Нажмите для просмотра прикрепленного файла

Цитата
/* Эти endpoints не используются для обмена */
size4 = 0x10;
instance->DIEPTXF [(USBD_EP_CDC_INT & 0x7F) - 1] = usbd_makefifoparam(base4, size4);
instance->DIEPTXF [(USBD_EP_CDC_INb & 0x7F) - 1] = usbd_makefifoparam(base4, size4);
instance->DIEPTXF [(USBD_EP_CDC_INTb & 0x7F) - 1] = usbd_makefifoparam(base4, size4);


И у Вас получается туда что-либо записать? У меня регистры у отключенных эндпоинтов совершенно мертвые (возвращают 0, запись игнорируют).

Цитата(Genadi Zawidowski @ Mar 20 2017, 11:42) *
ps: в аттачменте - тестовый бинарник под плату STM32F746G-DISCO, на FS порту создает два компорта и аудио. Один из компортов - кенвудовский CAT.

Спасибо, но дискавери у меня нет rolleyes.gif
Genadi Zawidowski
1) эти неиспользуемые ендпоинты инициализируются обычном способом, просто не выделяется память под буферы (а так как написано).
2) Ты помнишь, что в OTG_FS DMA отсутствует?
3) производительность, простота... Я начал тоже с написания с чистого листа (только заглядывая в кубокод). Это было после того как за месяц аналогичным способом поднял USB DEVICE на Renesas. Уткнувшись в стену через пару недель, решил сперва поднять как работает (и получил железно работающий интерфейс CDC+AUDIO). И за 33 дня (trial period USBLyzer-а) все закончил. Сейчас я пожалуй под структуру от ST склонен перетащить версию под Renesas, чем сильно менять то что работает. Но полигон в любом случае есть.
4) по логу: смотреть кто за кем... без этого могу предположить что в 13 строке инициировано чтение и в 14 удачно завершилось - десяток байт передан. А что в 15 строке не понял... Или не получилось начать передачу. Или это неудачно завершилась ранее инициированная операция. НЕ знаю как с этим логгером работать (варишарк?)
controller_m30
У меня был похожий случай недавно (на USB CDC), что данные от Хоста к устройству шли нормально, а от устройства к Хосту ни в какую.
Дескрипторы устройства были классические (EP1 IN/OUT - данные BULK, EP2 IN - Interrupt), всё вроде должно работать.

А проблема была в том, что конечную точку EP2 я забыл проинициализировать в контроллере. Я через неё отправлять ничего не собирался и забыл про неё, но Хост, зная из дескрипторов что эта точка есть, периодически (но крайне редко) - делал к ней запрос. Я этот запрос в логах даже найти не мог, т.к. он был 1 раз на 255 кадров SOF.
А поскольку EP2 не была инициализирована в железе, то она никак не отвечала на этот запрос: ни ACK, ни NACK ни как-то ещё. И Хост вообще прекращал делать запросы типа IN не только к EP2 IN но и к EP1 IN. В результате данные от устройства к Хосту не читались. Но передавались от Хоста к устройству исправно.

Когда я вспомнил-таки про EP2 и инициализировал её - данные от EP1 пошли нормально. У меня эта точка ничего не делает, просто отвечает NACK на запрос от Хоста, и всё.
Genadi Zawidowski
Добавлю - особенно хорошо проявляются такие забытые ендпоинты при работе через хаб. Во всяком случае, у меня было такое как и у Вас - совсем необслуживаемая точка не мешала работать компорту при прямом подключении и прекращала всякой обмен при подключении через хаб.
Шаманъ
Цитата(Genadi Zawidowski @ Mar 20 2017, 15:56) *
1) эти неиспользуемые ендпоинты инициализируются обычном способом, просто не выделяется память под буферы (а так как написано).

Что значит обычным способом? Попробуте как-нибудь ради прикола что-то записать регистр конфигурации ФИФО неиспользуемой точки.
Цитата
2) Ты помнишь, что в OTG_FS DMA отсутствует?

Да, мне ДМА не нужен, соответственно не использую.
Цитата
3) производительность, простота... Я начал тоже с написания с чистого листа (только заглядывая в кубокод). Это было после того как за месяц аналогичным способом поднял USB DEVICE на Renesas. Уткнувшись в стену через пару недель, решил сперва поднять как работает (и получил железно работающий интерфейс CDC+AUDIO). И за 33 дня (trial period USBLyzer-а) все закончил.

Ну у меня пока с чистого листа это дело заняло три дня, из которых один потрачен на идиотскую ошибку с распределением ФИФО и эту последнюю нерешенную проблему - врод все не так уж и плохо.
Цитата
по логу: смотреть кто за кем... без этого могу предположить что в 13 строке инициировано чтение и в 14 удачно завершилось - десяток байт передан. А что в 15 строке не понял... Или не получилось начать передачу. Или это неудачно завершилась ранее инициированная операция. НЕ знаю как с этим логгером работать (варишарк?)

Я тоже в этом логгере не силен, есть подозрение, что это вообще глюк логгера. Там вдруг посылается 10 байт через нулевую точку как будто это BULK точка. Перелопатил уже все, что можно, ну не посылаю я ничего такого, и само оно не может уйти - или глюк железки/ее инициализации, или логгер.

Сейчас вообще весело - первый пакет уходит и я его вижу в логгере. Но из очереди (в STMме в смысле) он не убирается и за ним уже ничего в сторону хоста не ходит.

Цитата(controller_m30 @ Mar 20 2017, 17:01) *
А проблема была в том, что конечную точку EP2 я забыл проинициализировать в контроллере. Я через неё отправлять ничего не собирался и забыл про неё, но Хост, зная из дескрипторов что эта точка есть, периодически (но крайне редко) - делал к ней запрос. Я этот запрос в логах даже найти не мог, т.к. он был 1 раз на 255 кадров SOF.

А вот это теплее. Дело в том, что я EP2 не использую, и в дескрипторе она не объявлена у меня. Она ведь исходя из стандарта опциональная, или нет? Наверное от безисходности щас переделаю дескрипторы 1:1 как у STM, и добавлю еще одну точку.
Genadi Zawidowski
Дополнил инициализацию отладочной печатью:
Код
v1=00000000
v2=00000000
v3=00000000
v4=0010013D
v5=0010013D
v6=0010013D
usbd_fifo_initialize: base4=1268, fullsize=1280

Код
    /* Эти endpoints не используются для обмена */
    size4 = 0x10;
    debug_printf_P(PSTR("v1=%08lX\n"), instance->DIEPTXF [(USBD_EP_CDC_INT & 0x7F) - 1]);
    debug_printf_P(PSTR("v2=%08lX\n"), instance->DIEPTXF [(USBD_EP_CDC_INb & 0x7F) - 1]);
    debug_printf_P(PSTR("v3=%08lX\n"), instance->DIEPTXF [(USBD_EP_CDC_INTb & 0x7F) - 1]);
    instance->DIEPTXF [(USBD_EP_CDC_INT & 0x7F) - 1] = usbd_makefifoparam(base4, size4);
    instance->DIEPTXF [(USBD_EP_CDC_INb & 0x7F) - 1] = usbd_makefifoparam(base4, size4);
    instance->DIEPTXF [(USBD_EP_CDC_INTb & 0x7F) - 1] = usbd_makefifoparam(base4, size4);
    debug_printf_P(PSTR("v4=%08lX\n"), instance->DIEPTXF [(USBD_EP_CDC_INT & 0x7F) - 1]);
    debug_printf_P(PSTR("v5=%08lX\n"), instance->DIEPTXF [(USBD_EP_CDC_INb & 0x7F) - 1]);
    debug_printf_P(PSTR("v6=%08lX\n"), instance->DIEPTXF [(USBD_EP_CDC_INTb & 0x7F) - 1]);

Они не используются, но вполне себе инициализированные.
Шаманъ
Цитата(Genadi Zawidowski @ Mar 20 2017, 20:38) *
Дополнил инициализацию отладочной печатью:

Забавно, а у меня что-либо поменять получается только в EP0/EP1...Блин это даже не смешно, но в заголовочном файле была ошибка... 1111493779.gif

Переделал на три точки (как у СТМ), поставил USBlyser - правильный инструмент. Теперь вижу откуда были 10байтные передачи данных на control pipe - это драйвер использовал ее вместо дополнительной Interrupt точки. Также вижу где начинаются проблемы, результата правда пока нет...
Genadi Zawidowski
Цитата
но в заголовочном файле была ошибка

В студию...

зы: с каким кварцем макет? - попробую по приколу тест сделать для твоей платы.
Шаманъ
Цитата(Genadi Zawidowski @ Mar 20 2017, 22:06) *
В студию...


У меня он оказался очень древним, все собирался скачать посвежее, но оно ж работает. В структуре забыли __IO в одном месте. Версия файла 0.9.5 (сейчас скачал свежий, он почти в два раза больше по объему и моложе на 1.5года 1111493779.gif и версия значится 1.2.0). Регистры теперь меняются, как надо, но результат +- такой же:
Нажмите для просмотра прикрепленного файла

Там где зеленым выделено это я отдал хосту 70байт (все прошло нормально). А вот с красного начались проблемы...видать что-то профтыкал я laughing.gif, наверное надо еще раз сделать RTFM по стандарту и скупым докам от STM... Да, терминалом нормально порт открывается и данные от хоста к девайсу ходят.

Цитата
зы: с каким кварцем макет? - попробую по приколу тест сделать для твоей платы.

8MГц это все вокруг платки от WaveShare Core746I построено.
Genadi Zawidowski
Вот версия с внутренним генератором, теоретически должна поднять USB FS на любой макетке.
Цитата
Там где зеленым выделено это я отдал хосту 70байт (все прошло нормально). А вот с красного начались проблемы...

Нда... ендпоинт ушел в себя... Кстати, для понимания - FIFO у них (STM32F746) не для байтов, а для пакетов. вычитывать только целиком.
Шаманъ
Народ, я тут всех поставил на уши, а потом подключил девайс к машине на которой восьмерка (до этого смотрел на старой машине с ХР), и о чудо он отсылает данные обратно sm.gif Теперь проверить надо туда и назад...

Цитата(Genadi Zawidowski @ Mar 20 2017, 23:01) *
Нда... ендпоинт ушел в себя... Кстати, для понимания - FIFO у них (STM32F746) не для байтов, а для пакетов. вычитывать только целиком.

Да я в курсе, там два пакета было - 64 байта и остаток.
Genadi Zawidowski
Попробуй мой тест на XP - у меня работало (терминалкой ;;; - в ответ ?;)
Шаманъ
Цитата(Genadi Zawidowski @ Mar 20 2017, 23:40) *
Попробуй мой тест на XP - у меня работало (терминалкой ;;; - в ответ ?;)

А что оно еще делает на 400кБ?

Убрал одну EP. Итог - в сторону хоста проходит только первая посылка и все. Ладно буду завтра пилить дальше, есть кое какие мысли почему так...
Genadi Zawidowski
На одном из двуз компортов - Kenwood CAT. На объем не обращай внимания, там DSP трансивер внутри... таблицы синусов разные... без выхода наружу. Проверил бы... прошить минутное дело. Хоть сказал бы, опознается или нет.

А что за проблема с interrupt endpoint? на 746 для аудио+компорты впритык хватает. То что XP без interrupt endpoint CDC не работает я где-то писал уже.
Alechek
Цитата(Шаманъ @ Mar 21 2017, 01:38) *
Народ, я тут всех поставил на уши, а потом подключил девайс к машине на которой восьмерка (до этого смотрел на старой машине с ХР), и о чудо он отсылает данные обратно sm.gif Теперь проверить надо туда и назад...

"Cтарая" XP (SP2) и "новая" XP (SP3) - тоже 2 большие разницы. Драйвер CDC в SP3 сильно переработали. Точно что-то поменяли в случае, если размер передачи кратен размеру EP
Шаманъ
Цитата(Genadi Zawidowski @ Mar 21 2017, 00:16) *
Проверил бы... прошить минутное дело. Хоть сказал бы, опознается или нет.

Дело не минутное - надо разобрать девайс, чтобы отключить TFT (поскольку без инициализации LTDC он будет в очень нехорошем состоянии, которое приводит к его медленной деградации). Разбирать довольно долго. Учитывая написанное выше и ниже не уверен, что эта операция что-либо решит.

Цитата
А что за проблема с interrupt endpoint? на 746 для аудио+компорты впритык хватает. То что XP без interrupt endpoint CDC не работает я где-то писал уже.

Мне не хватает - без interrupt EP того, что есть у USB FS хватает впритык (еще бы парочка была кстати, но тут была проблема с распределением других интерфейсов/разводкой платы, в итоге USB HS вытянуть не получилось).

Цитата(Alechek @ Mar 21 2017, 06:52) *
"Cтарая" XP (SP2) и "новая" XP (SP3) - тоже 2 большие разницы. Драйвер CDC в SP3 сильно переработали. Точно что-то поменяли в случае, если размер передачи кратен размеру EP

Спасибо! Теперь припоминаю, что там были проблемы с этим драйвером, из-за чего его особо и не использовал никто. Наверное пора обновиться sm.gif.
Шаманъ
XP таки была "новая" в смысле XP SP3
Шаманъ
Цитата(Genadi Zawidowski @ Mar 21 2017, 00:16) *
Проверил бы... прошить минутное дело. Хоть сказал бы, опознается или нет.

Отчитываюсь, разобрал девайс, отлючил ТФТ, залил - работает. Я тут у себя еще нарыл проблем, коротче буду искать. За файл спасибо - теперь понятно, что работать должно...
Genadi Zawidowski
Спасибо. На какой операционной системе проверялось? На XP SP3 мой файл проверял?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.