Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32 USB FS OTG
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2, 3
V_M_Luck
Разбираюсь с USB FS OTG на STM32F107. Есть плата с STM32F107 и USB. Мне нужен только device. Что то самостоятельно по даташиту не очень получилось. Попытался запустить пример HID от ST из STM32_USB-FS-Device_Lib_V3.3.0. Не работает. Попадает пару раз в прерывание по RESET, потом в ENUMDN и все. Больше никакой активности.
Смотрел USB TRACE - host даже не пытается запрашивать дескрипторы.
Вопрос - у кого-нибудь этот пример заработал?

Извините. Нашел у себя косяк - пример заработал.
V_M_Luck
Вновь поднимаю тему.
Пример-то заработал. Но тянуть к себе в проект дикий фреймворк из-за одного эндпоинта для HID совсем не хочется. Стал разбираться в регистрах по даташиту и примеру.
Инициализацию вроде-бы сделал. Получаю USBRST, ENUMDNE, потом получаю запрос GET_DEVICE_DESCRIPTOR.
И тут-то все начинается. Настраиваю DIEPTSIZ0, DIEPCTL0 .
Помещаю в фифо данные.
Получаю прерывание на IN endpoint XFRCM. Вроде все ОК. Но HOST этого дескриптора не видит. В результате, вместо SET_ADDRESS опять получаю GET_DEVICE_DESCRIPTOR и все по кругу. Так раз 5 и HOST прекращает енумерацию.

Уже два дня голову ломаю. Может кто-нибудь сталкивался? Подскажите, в какую сторону посмотреть.
SviMik
Ровно та же проблема, как и в последнем сообщении. XFRCM прерывание получаю, от компа на дескриптор ноль реакции.
Дескриптор заведомо рабочий, взят из проекта, который делал на МК другого производителя.
Пробовал делать как строго по даташиту, так и переставлять всё, что только возможно - не работает.

Если автор решил проблему - хотелось бы узнать как sm.gif
Forger
Цитата(V_M_Luck @ Jul 13 2011, 19:51) *
...Подскажите, в какую сторону посмотреть...

Попробуте все ваши дискрипторы вставить в заведомо рабочий проект, пусть даже с "толстым" фреймворком.
Далее можно просто записать все, что отправляется/принимается хостом (соот. прогой) и сравнивать уже с логами уже своего проекта.
Наверняка, будет в чем-то разница, оттуда и копать sm.gif
SviMik
В моём случае, дескриптор взят из заведомо рабочего проекта, но под другой МК (ARM от атмела, ATSAM3S). Там я писал полностью сам, без библиотек, так что в протоколе USB немного понимаю (как мне кажется).

Решил пересесть на STM, и вот такой затык.

Цитата
Далее можно просто записать все, что отправляется/принимается хостом (соот. прогой)

К сожалению, не всё. Я пробовал SniffUSB, но он начинает запись только после корректного опознания устройства, тоесть абсолютно бесполезен в моём случае.

Мой текущий дескриптор девайса выглядит так (как я уже сказал, он заведомо рабочий):
Код
static char device_descriptor[18]={
    /* Standard USB device descriptor for the CDC serial driver */
    sizeof(device_descriptor), // size
    1, // USBGenericDescriptor_DEVICE
    0x00,0x02, // USBDeviceDescriptor_USB2_00
    2, // CDCDeviceDescriptor_CLASS
    0, // CDCDeviceDescriptor_SUBCLASS
    0, // CDCDeviceDescriptor_PROTOCOL
    64, // BOARD_USB_ENDPOINTS_MAXPACKETSIZE
    0xEB,0x03, // CDCDSerialDriverDescriptors_VENDORID
    0x24,0x61, // CDCDSerialDriverDescriptors_PRODUCTID
    0x10,0x01, // CDCDSerialDriverDescriptors_RELEASE
    1, // Index of manufacturer description //0
    2, // Index of product description //0
    3, // Index of serial number description //0
    1, // One possible configuration
};

(остальные не привожу, т.к. до них вообще дело не доходит)

Что происходит на заведомо рабочей плате с SAM3S:
1. usb сброс
2. приходит setup пакет с запросом дескриптора девайса
3. МК отправляет дескриптор (18 байт)
4. usb сброс
5. приходит фрейм, назначающий адрес usb устройству
6. и т.д.

Что происходит с STM32F4: не работает.
1. usb сброс
2. приходит setup пакет с запросом дескриптора девайса
3. МК отправляет дескриптор (18 байт)
4. а дальше тишина, и через 3 секунды переходим к п.1

Приблизительный код для стм32 (упрощено до безобразия в целях отладки):
Код
volatile uint32_t * fifo=(uint32_t *)(OTG_FS_DFIFO0_BASE);
OTG_FS->DIEPTSIZ0=(1<<19)|18; // PKTCNT; XFRSIZ
OTG_FS->DIEPCTL0=(1<<31)|(1<<26); // EPENA; CNAK
*fifo=0x02000112;
*fifo=0x40000002;
*fifo=0x612403EB;
*fifo=0x02010110;
*fifo=0x00000103;


Работу с FIFO предполагаю, на основе того, что чтение работает таким образом:
Код
volatile uint32_t * fifo=(uint32_t *)OTG_FS_DFIFO0_BASE;
int i=0;
for(i=0;i<BCNT;i+=4){
    int data=*fifo;
    rbuf[i+0]=(data>>0)&0xFF;
    rbuf[i+1]=(data>>8)&0xFF;
    rbuf[i+2]=(data>>16)&0xFF;
    rbuf[i+3]=(data>>24)&0xFF;
    pprintf("< %02X%02X%02X%02X", rbuf[i+0], rbuf[i+1], rbuf[i+2], rbuf[i+3]);
}


Исходя из даташита, я делаю правильно.

1. DIEPTSIZ0 должен устанавливаться до того, как поставлю EPENA в DIEPCTL0
Цитата
The application must modify this register before enabling endpoint 0. Once endpoint 0 is
enabled using the endpoint enable bit in the device control endpoint 0 control registers
(EPENA in OTG_FS_DIEPCTL0), the core modifies this register. The application can only
read this register


2. EPENA в DIEPCTL0 должен устанавливаться до того, как начну писать данные в FIFO.
Цитата
1. Program the OTG_FS_DIEPCTLx register with the endpoint characteristics and set the
CNAK and EPENA bits.
2. Write the data to be transmitted in the next frame to the transmit FIFO.


Цитата
1. The application must set the transfer size and packet count fields in the endpointspecific
registers and enable the endpoint to transmit the data.
2. The application must also write the required data to the transmit FIFO for the endpoint.


Однако, я пробовал и другой порядок действий, безрезультатно.
aaarrr
CNAK в DOEPCTL0 после обработки setup установить не забыли?
SviMik
Вот же однако... Заработало! Плюс вам в карму, если б она тут была sm.gif
А я CNAK только один раз при инициализации ставил, и думал оно так и будет...

Интересно, а когда "по правилам" его надо ставить? "после обработки setup" это когда
1. закончил приём setup запроса
2. только записал ответ на setup в FIFO
3. когда отправка моего ответа уже завершена

(сейчас я поставил от балды)
aaarrr
Цитата(SviMik @ Sep 10 2012, 02:19) *
Интересно, а когда "по правилам" его надо ставить? "после обработки setup" это когда
1. закончил приём setup запроса
2. только записал ответ на setup в FIFO
3. когда отправка моего ответа уже завершена

В общем-то в любой момент правильно, можно после п.1
SviMik
Пытаюсь реализовать CDC девайс. Что получилось:
1. Приём от компа к девайсу - без проблем, любое количество данных.
2. Отправка от девайса к компу - отправляется только первый пакет. Дальше ничего не шлётся.

Что я мог упустить?

Код
void hwtx(){
    volatile uint32_t * fifo=(uint32_t *)OTG_FS_DFIFO2_BASE;
    int i;
    int len=12;
    char data[]={"Hello world\n"};
    pprintf("1. FIFO: %i words free", OTG_FS->DTXFSTS2&0xFFFF);
    OTG_FS->DIEPTSIZ2=(1<<19)|(len<<0); // PKTCNT; XFRSIZ
    OTG_FS->DIEPCTL2|=(1UL<<31)|(1<<26); // EPENA; CNAK
    for(i=0;i<len;i+=4){
        *fifo=((data[i+0]&0xFF)<<0)|((data[i+1]&0xFF)<<8)|((data[i+2]&0xFF)<<16)|((data[i+3]&0xFF)<<24);
    }
    pprintf("2. FIFO: %i words free", OTG_FS->DTXFSTS2&0xFFFF);
}


попытка 1, строка приходит
1. FIFO: 64 words free
2. FIFO: 61 words free
IRQ: SOF
IRQ: EP2 IN XFRC (Transfer completed)

попытка 2:
1. FIFO: 64 words free
2. FIFO: 61 words free

попытка 3:
1. FIFO: 61 words free
2. FIFO: 58 words free

тоесть далее просто забивается FIFO, а отправка не идёт...
SviMik
Вомзжно, я что-то не так понял с FIFO буфферами. Если верить даташиту, размер буффера указывается в word, т.е. по 4 байта.
Текущая инициализация FIFO выглядит так:
Код
OTG_FS->GRXFSIZ=64; // RX FIFO = x words
OTG_FS->DIEPTXF0=(128<<16) | 64; // TX FIFO 0 = x words; start=x
OTG_FS->DIEPTXF1=(64<<16) | 192; // TX FIFO 1 = x words; start=x
OTG_FS->DIEPTXF2=(64<<16) | 256; // TX FIFO 2 = x words; start=x


Это конфигурация, при которой девайс нормально инициализируется. При попытке уменьшить приёмный буффер, инициализация уже не проходит. Хотя 64 cлова (256 байт) явно избыточно для SETUP пакетов.

Инициализация эндпоинтов:

Код
/* CDC endpoints: 0:control, 1:bulk out, 2:bulk in, 3:int in */
/* OUT */
OTG_FS->DOEPCTL0=(1<<26)|(1<<15)|(0<<0); // CNAK; active endpoint; Maximum packet size=64;
OTG_FS->DOEPCTL1=(1<<26)|(2<<18)|(1<<15)|(64<<0); // CNAK; Endpoint type; active endpoint; Maximum packet size;
/* IN */
OTG_FS->DIEPCTL0=(0<<22)|(1<<15)|(0<<0); // TxFIFO number; active endpoint; Maximum packet size=64;
OTG_FS->DIEPCTL2=(2<<22)|(2<<18)|(1<<15)|(64<<0); // TxFIFO number; Endpoint type; active endpoint; Maximum packet size;
MBR
Цитата(SviMik @ Sep 18 2012, 04:11) *
Это конфигурация, при которой девайс нормально инициализируется.

receive fifo шареный. Он не только для setup-пакетов используется. Плюсом, не забываете DIEPTXFx offset сдвигать при уменьшении GRXFSIZ?

Еще чтение мануалов рулит:

10 locations must be reserved in the receive FIFO to receive SETUP packets on control
endpoint. The core does not use these locations, which are reserved for SETUP packets, to
write any other data. One location is to be allocated for Global OUT NAK. Status information
is written to the FIFO along with each received packet. Therefore, a minimum space of
(Largest Packet Size / 4) + 1 must be allocated to receive packets. If multiple isochronous
endpoints are enabled, then at least two (Largest Packet Size / 4) + 1 spaces must be
allocated to receive back-to-back packets. Typically, two (Largest Packet Size / 4) + 1
spaces are recommended so that when the previous packet is being transferred to the CPU,
the USB can receive the subsequent packet.

От себя добавлю, что рекомендация two (Largest Packet Size / 4) + 1 исходит из того, что, пока мы один буфер из FIFO забираем, железо уже принимает второй.
SviMik
Хорошо. Тоесть моя конфигурация выше впринципе правильная, и должна работать? Но почему же с отправкой у меня проблемы... При этом, в нулевой эндпоинт отправлять дескрипторы проблем нет, а отправить данные в второй эндпоинт - проходит только первый пакет и всё. Возможно, с bulk эндпоинтами как-то иначе поступать надо?

А документация уже утомила своими ляпами... В таблице одно, в тексте другое... Доходит до того, что в таблице бит подписан Reserved, а ниже в тексте даётся его нормальное описание. Или в таблице "r", а в описании сказано, что в него писать надо. IN и OUT тоже путают, приходится логически до всего доходить. Даже ссылки неправильные. кликаю в оглавлении на DIEPTSIZx, попадаю на DOEPTSIZx... такой вот тест на внимательность sad.gif
Извиняюсь, накипело...
MBR
Цитата(SviMik @ Sep 18 2012, 17:48) *
При этом, в нулевой эндпоинт отправлять дескрипторы проблем нет, а отправить данные в второй эндпоинт - проходит только первый пакет и всё. Возможно, с bulk эндпоинтами как-то иначе поступать надо?

А XFRC не забываете сбрасывать после приема пакета?
SviMik
Всмысле флаг прерывания? Да, как и все остальные прерывания, сбрасываю.

Код
    }else if(OTG_FS->DAINT&(1<<2)){ // IEPINT on EP 2
        //print("- DAINT_IRQ: EP2 IN");
        if(OTG_FS->DIEPINT2&(1<<0)){ // Data IN transaction completed
            OTG_FS->DIEPINT2=(1<<0);
            pprintf("EP_IRQ(IN): EP2 XFRC");
        }else if(OTG_FS->DIEPINT2&(1<<1)){ // Endpoint disabled interrupt
            OTG_FS->DIEPINT2=(1<<1);
            pprintf("EP_IRQ(IN): EP2 EPDISD");
        }else if(OTG_FS->DIEPINT2&(1<<3)){ // Timeout condition mask
            OTG_FS->DIEPINT2=(1<<3);
            pprintf("EP_IRQ(IN): EP2 TOC");
        }else if(OTG_FS->DIEPINT2&(1<<4)){ // IN token received when TxFIFO is empty
            OTG_FS->DIEPINT2=(1<<4);
            pprintf("EP_IRQ(IN): EP2 ITTXFE");
        }else if(OTG_FS->DIEPINT2&(1<<6)){ // IN endpoint NAK effective
            OTG_FS->DIEPINT2=(1<<6);
            pprintf("EP_IRQ(IN): EP2 INEPNE");
        }else if(OTG_FS->DIEPINT2&(1<<7)){ // Transmit FIFO empty
            OTG_FS->DIEPINT2=(1<<7);
            pprintf("EP_IRQ(IN): EP2 TXFE");
        }else{
            pprintf("EP_IRQ(IN): EP2 %i", OTG_FS->DIEPINT2);
        }
    }
MBR
А где запись данных после отправки очередного балка?
SviMik
Всмысле? Функция hwtx() выше, вызываю её вручную, по команде в UART консоль.

Код
    while(1){
        if((USART3->SR & USART_SR_RXNE)){ // data received
            char c=USART3->DR;
            //...
            if(c=='3'){hwtx();}
        }
SviMik
Кажется, чего-то я в этой жизни не понимаю sad.gif
Из девайса в комп через второй эндпоинт отправляется только один пакет, после чего этот эндпоинт наглухо виснет. Пробовал:
1. Сбрасывать FIFO через регистр GRSTCTL. Как выборочно, так и все.
2. Отключать-включать эндпоинт, ставить CNAK
3. Сбрасывать весь регистр DIEPCTL2 в ноль, и заново конфигурировать
4. Плясать с бубном

Идеи закончились. После успешной отправки "Hello world" на комп, второй раз отправить не удаётся. Только перетыкание кабеля срабатывает.
MBR
Раз все остальное вроде верно, что там в hwtx?
SviMik
(Назначение hwtx - слать Hello World. Исключительно для дебага, поэтому упрощена до безобразия)
Скорее всего, я упустил что-то важное, но не могу понять что sad.gif
Для общения через нулевой эндпоинт используется тот же алгоритм, и он работает. Разница только в типах эндпоинтов (control и bulk). И вот с bulk что-то не выходит.

Код
void hwtx(){
    volatile uint32_t * fifo=(uint32_t *)OTG_FS_DFIFO2_BASE;
    int i;
    int len=12;
    char data[]={"Hello world\n"};
    pprintf("1. FIFO: %i words free", OTG_FS->DTXFSTS2&0xFFFF);
    OTG_FS->DIEPTSIZ2=(1<<19)|(len<<0); // PKTCNT; XFRSIZ
    OTG_FS->DIEPCTL2|=(1UL<<31)|(1<<26); // EPENA; CNAK
    for(i=0;i<len;i+=4){
        *fifo=((data[i+0]&0xFF)<<0)|((data[i+1]&0xFF)<<8)|((data[i+2]&0xFF)<<16)|((data[i+3]&0xFF)<<24);
    }
    pprintf("2. FIFO: %i words free", OTG_FS->DTXFSTS2&0xFFFF);
}
MBR
Собственно, я ошибок не вижу. Я делаю все примерно тоже самое, единственное, дополнительно устанавливаю NAK в конце отправки пакета. Но, по идее, он должен ставиться автоматом.
SviMik
Я сдаюсь sad.gif
Можете выложить какой-нибудь минимальный рабочий пример с USB?
Или может я выложу свой проект целиком?
NaughtyFreak
Подниму тему.
Подскажите плз, все глаза стёр уже где узнать адрес Rx FIFO для STM32F4. Пишу собственный стек (на базе их либы правда), с Tx адресами мне всё понятно, а Rx у них один на всех насколько я понял, а вот как из него читать не доходит.
Сергей Борщ
Подниму древнюю тему.

STM32F107, родной стек из Cube напугал множеством лишних телодвижений. Почти 20 К кода за виртуальный COM мне кажется многовато. Пишу свой, запнулся на элементарном - не отсылаются данные (дескриптор). Получаю setup запрос на device descriptor размером 8 байт. Проверяю наличие места в FIFO (DTXFSTS0), там 0x40 слов. Прописываю в DIEPTSIZ0 количество пакетов (PKTCNT) = 1 и размер посылки (XFRSIZ) = 8. Прописываю в FIFO два слова. После записи каждого слова наблюдаю уменьшение на 1 содержимого DTXFSTS0. После записи обоих слов XFRSIZ становится равным нулю, а DTXFSTS0, соответственно, 0x3E. Запускаю обмен (одновременно выставляю CNAK и EPENA в DIEPCTL0). Попадаю в прерывание XFRC, то есть ядро думает, что пакет отправило. При этом PKTCNT становится равен нулю. Но комп посланного дескриптора не видит, а свободное место в FIFO увеличивается всего на одно слово (DTXFSTS0 становится равным 0x3F). Как будто ядро вместо восьми байтов отсылает не более четырех. Родной пример из Cube работает, и если никто не подскажет - буду вставлять отладочный вывод в пример Cube. Но, мало ли, кто-то знает что ему не нравится?
Такое ощущение, что ядро при передаче неправильно воспринимает записанный в XFRSIZ размер, но он уменьшается до нуля именно в момент записи в FIFO последнего слова, четко в соотвествии с руководством пользователя. В общем уже третий вечер перечитываю руководство, хожу по шагам по своей программе и по примеру из Cube, вроде все делаю так же, а каменный цветок не выходит хоть тресни. Отсылка пакета нулевого размера (ZLP) после установки адреса проходит нормально.
Сергей Борщ
Цитата(Сергей Борщ @ Mar 16 2015, 11:49) *
Но комп посланного дескриптора не видит, а свободное место в FIFO увеличивается всего на одно слово (DTXFSTS0 становится равным 0x3F). Как будто ядро вместо восьми байтов отсылает не более четырех.
Разобрался. Нужно сначала запускать передачу установкой CNAK и EPENA, а уже потом запихивать данные в FIFO. Надо внимательнее читать документацию:
Цитата
Using one of the above mentioned methods, when the application determines that
there is enough space to write a transmit packet, the application must first write into the
endpoint control register, before writing the data into the data FIFO.
esaulenka
Ещё разик подниму тему.

На эти грабли: https://my.st.com/public/STe2ecommunities/m...rrentviews=1592 никто не наступал?

Прикрутил библиотеку libopencm3, сделал из неё HID. Обмен - по нулевому endpoint'у блоками в 32 байта.
setup-пакеты ходят нормально, а от data out пропадают первые 4 байта. Странный костыль в библиотеке - добавить тысячу NOP'ов перед считыванием - не помогает. Да и выглядит он некрасиво...
johnshadow
Цитата(esaulenka @ Apr 7 2015, 12:57) *
Ещё разик подниму тему.

На эти грабли: https://my.st.com/public/STe2ecommunities/m...rrentviews=1592 никто не наступал?

Прикрутил библиотеку libopencm3, сделал из неё HID. Обмен - по нулевому endpoint'у блоками в 32 байта.
setup-пакеты ходят нормально, а от data out пропадают первые 4 байта. Странный костыль в библиотеке - добавить тысячу NOP'ов перед считыванием - не помогает. Да и выглядит он некрасиво...


Попробуйте стандартную от st - у меня вполне нормально завелась как CustomHID. Использовал STM32_USB-Host-Device_Lib_V2.1.0 на проце stm32f105, плюс FreeRtos. Делал CAN-USB сниффер - сливать дампы FMS j1939 с грузовиков. На стресс тестах правда пропускной способности USB не хватает - ограничение HID, но не хочется отказываться от использования дефолтных драйверов в windows. И я надеюсь что в реальных условиях такого потока не будет. sm.gif

Правда на текущий момент есть два "нюанса":
1) Не работает на одном из ноутбуков у сотрудника - устройство обнаруживается, но данные в программу от устройства не поступают.
Вполне возможно что проблемы не в либе - ноутбук этот ремонтный. Так же возможно проблема в компоненте HID для lazarus, который я использую в программе на большом брате. Все руки не доходят разобраться.
2) Несколько раз были замечены случаи переподключения устройства - внешне проявляется как будто устройство отключили и сразу подключили. Опять же склоняюсь к мысли, что это не из-за либы. Скорее всего это ошибки в моей реализации остального функционала - похоже что попадаю в HardFault и перегружаюсь по WDT. Проявляется этот глюк крайне редко - пока пытаюсь поймать.

libopencm3 мельком смотрел - смутила необходимость в цикличном выполнении функции usbd_poll. В библиотеке от st все callback'и из OTG_FS_IRQHandler дергаются.
esaulenka
Рекомендацию библиотеки ST спасибо. Знать, что оно таки работоспособно, это хорошо :-)

Допилил этот CustomHID из крайней версии CubeMX (он там сломаный, просто куда-то потеряли кусок кода).
Да, действительно, работает. Да, действительно, данные не теряет.

При сравнении CubeMX и libopencm3 была обнаружена интересная особенность. Как известно, эндпоинт после завершения обмена становится неактивным, и его надо постоянно включать.
Авторы libopencm3 делают это при первой же возможности (для OUT-транзакции - сразу после вычитывания из FIFO), а в "родной" библиотеке - после многочисленных действий (обработать пакет, подумать, какой будет следующим, какого он размера...). В итоге, в в libopencm3 в один фрейм попадает и SETUP с указанием "а сейчас будет SET REPORT" и собственно данные этого report'а. Точнее, не все данные, а сдвинутые на 4 байта (и дополненные мусором в конце).

Подробности - с фоточками осциллографа (пардон за качество. флешки, которую он поймёт, под рукой нету..) и состоянием регистра прерываний, здесь (кликнуть по картинке, там две страницы).

Если по приему setup пакета ничего не делать и не разрешать обратно эндпоинт в течении 1 мс, всё начинает работать корректно. Но меееедленно.


Собственно, вопрос:
1) я правильно понимаю, что спецификация USB 2.0 Full Speed не запрещает посылать setup и out в один эндпоинт за один фрейм?
2) у кого-нибудь на этом FS OTG использовал возможность использовать несколько транзакций в одном фрейме?



Цитата(johnshadow @ Apr 8 2015, 16:57) *
2) Несколько раз были замечены случаи переподключения устройства - внешне проявляется как будто устройство отключили и сразу подключили. Опять же склоняюсь к мысли, что это не из-за либы. Скорее всего это ошибки в моей реализации остального функционала - похоже что попадаю в HardFault и перегружаюсь по WDT. Проявляется этот глюк крайне редко - пока пытаюсь поймать.

Возможно, это какие-то "электрические" проблемы. Если рядом есть грузовик, надо рассчитывать, что в любой момент с неожиданной стороны придёт помеха.

Цитата(johnshadow @ Apr 8 2015, 16:57) *
libopencm3 мельком смотрел - смутила необходимость в цикличном выполнении функции usbd_poll. В библиотеке от st все callback'и из OTG_FS_IRQHandler дергаются.

Не понимаю, почему так сделали, но там уже почти всё готово для оборачивания этого poll() в прерывание. Собственно, эта часть заработала почти сразу. Дальше - аналогично, штатными callback'оми (правда, тут они динамические - через указатели).
Golikov A.
По спецификации USB 2.0 если мы говорим о SETUP то это control tranfer, а он описан так

Control transfers minimally have two transaction stages: Setup and Status. A control transfer may
optionally contain a Data stage between the Setup and Status stages.

то есть как бы да, данные опционально пихаются прямо в середину до статуса.

Но естественно пакеты разные, потому что как минимум должны иметь разные токены DATA0 всегда у сетапа и первые данные придут уже как DATA1
esaulenka
Подумал-подумал, и окончательно запутался.

Два bulk-пакета подряд ведь повсеместно встречаются? Соответственно, если бы была проблема "теряется начало любого второго пакета", народ бы много где ругался.

А в control можно ведь засунуть длинный пакет, чтоб оно "само" резало-склеивало?.. Вроде б не запрещают.
Сейчас посмотрю, что происходит на границе второй-третий пакет...
Golikov A.
окончанием данных служит пакет длинной меньше максимального
если надо передать данные кратной длине пакета, то за последним полным пакетом посылают пакет 0 длинны как признак окончания.

целостность пакета как я понимаю берет на себя железо. А вот деление на пакеты я встречал разные реализации. У кого-то надо прям руками заполнять по пакетно, у кого-то один здоровый буфер и железо контроллера само режет. Я не знаю реализации STM, у них USB какой-то чудной...
Immortal_Buka
Может подскажет кто:
В соответствии с вот этой штукой: http://blogs.msdn.com/b/usbcoreblog/archiv...e-a-device.aspx
дохожу до п.6, отправляю дескриптор, и хост меня ресетит. Вероятно туплю с фазой статуса контрольной передачи.
STM32F429
Вопрос - мы получаем от хоста токен OUT и нулевой пакет данных. Чтобы ответить мы должны сделать так:

DIEPTSIZ0 |= 0x00080000;
DIEPCTL0 |= (USB_OTG_DIEPCTL_CNAK|USB_OTG_DIEPCTL_EPENA);

Или нет?
Или где в RM прочитать?
prottoss
Доброго времени суток.
Тоже решил освоить STM32 OTG_FS в качестве Device. Тоже не нравится библиотека от ST и решил написать свой драйвер. Тоже проблема с отправкой пакетов. Прочитал всю тему. Все исправил. Но хост так и не получает отравляемые данные в ходе энумерации.

Стратегия у меня такая:
1. В прерывании OTG_FS_GINTSTS_RXFLVL читаю регистр OTG_FS_GRXSTSP.
2. Жду прерывание от OUT Точки. Если прерывание от точки 0, и есть флаг OTG_FS_DOEPINTx_STUP вычитываю данные из RX FIFO и обрабатываю SETUP пакет от хоста.
3. Разрешаю прерывание OTG_FS_DIEPINTx_TXFE - IN FIFO путст.
4. В прерывании от IN точки по OTG_FS_DIEPINTx_TXFE отправляю данные хосту.

Данные вроде отправляются, судя по количеству прерываний (п. 4) но хост ресетит девай после отправки двух пакетов и далее все по новой.
Еще наблюдаю не систематическое возникновение прерываний по OTG_FS_GINTSTS_RXFLVL.

Вопрос - нужно ли, в обработчике OTG_FS_GINTSTS_RXFLVL вычитывать данные (что я не делаю)сразу или можно дожидаться прихода прерывания от OUT точки с флагом OTG_FS_DOEPINTx_STUP?

Спасибо.
aaarrr
Цитата(prottoss @ Oct 25 2015, 15:30) *
Данные вроде отправляются, судя по количеству прерываний (п. 4) но хост ресетит девай после отправки двух пакетов и далее все по новой.

Хост сначала запрашивает 8 байт дескриптора устройства, поэтому фраза "количество прерываний" несколько настораживает. Можете рассказать подробнее, что и в какой последовательности происходит?

Цитата(prottoss @ Oct 25 2015, 15:30) *
Вопрос - нужно ли, в обработчике OTG_FS_GINTSTS_RXFLVL вычитывать данные (что я не делаю)сразу или можно дожидаться прихода прерывания от OUT точки с флагом OTG_FS_DOEPINTx_STUP?

Я ориентировался по полю PKTSTS регистра OTG_FS_GRXSTSP - чтение по "SETUP data packet received", обработка по "SETUP transaction completed".
prottoss
Цитата(aaarrr @ Oct 25 2015, 19:07) *
Хост сначала запрашивает 8 байт дескриптора устройства, поэтому фраза "количество прерываний" несколько настораживает. Можете рассказать подробнее, что и в какой последовательности происходит?

Не совсем так по поводу запроса дескриптора устройства. Хост не может запрашивать 8 байт. Он запрашивает намного больше. Но после отправки первых 8 байт (для Windows) должен сделать USB Reset. За тем, по новой, запрос дескриптора устройства, если все в порядке, установка адреса и за тем уже все прочее.

У меня вот такой порядок прерываний (флаги OTG_FS):
1. OTG_FS_GINTSTS_USBRST /* USB device bus reset */
2. OTG_FS_GINTSTS_ENUMDNE /* Enumeration done */
3. OTG_FS_GINTSTS_RXFLVL /* Receive FIFO non-empty */
4. OTG_FS_GINTSTS_RXFLVL /* Receive FIFO non-empty */
5. OTG_FS_GINTSTS_USBRST /* USB device bus reset */
6. OTG_FS_GINTSTS_RXFLVL /* Receive FIFO non-empty */
7. OTG_FS_GINTSTS_RXFLVL /* Receive FIFO non-empty */
8. OTG_FS_GINTSTS_OEPINT /* EP OUT event */
8.1. OTG_FS_DOEPINTx_STUP/* Setup Phase Done (control EPs) */ - Здесь обрабатывам запрос и разрешаем прерывание TX FIFO empty */
9. OTG_FS_GINTSTS_RXFLVL /* Receive FIFO non-empty */
10. OTG_FS_GINTSTS_IEPINT /* EP IN event */
10.1 OTG_FS_DIEPINTx_TXFE /* IN endpoint FIFO empty */ - Здесь отправляем данные хосту - дескриптор устройтсва, первые 8 байт */
11. OTG_FS_GINTSTS_RXFLVL /* Receive FIFO non-empty */ - Не понял че такое???
10. OTG_FS_GINTSTS_IEPINT /* EP IN event */ -ага! данные улетели. Наверное...
12. OTG_FS_GINTSTS_OEPINT /* EP OUT event */ - вы че творите???
12.1. 8.1. OTG_FS_DOEPINTx_STUP/* Setup Phase Done (control EPs) */ - Это че за запрос??? В поле bRequest = 0 */

Потом куча прерываний OTG_FS_GINTSTS_RXFLVL.
Потом сброс шины.
Потом все по новой





Отредактировал

В каждом прерывании нужный флаг закрывается - пишется единица в соответствующий бит/регистр
aaarrr
Цитата(prottoss @ Oct 25 2015, 16:29) *
Хост не может запрашивать 8 байт.

Как это не может? Может, запрашивает, и сбасывает шину при попытке передать больше, например.

Цитата(prottoss @ Oct 25 2015, 16:29) *
У меня вот такой порядок прерываний (флаги OTG_FS):

Подозрительно уже начиная с п.5, какой промежуток времени проходит между пп.4-5?
prottoss
Цитата(aaarrr @ Oct 25 2015, 19:46) *
Как это не может? Может, запрашивает, и сбасывает шину при попытке передать больше, например.

Не может запрашивать меньше байт чем размер Device Descriptor. Обычно запрашивает 256 байт. Но после приема первой посылки отрубает. Т.е. отправил первые 8 байт (если ЕР0 размер равен 8 байт). Получаешь событие, что отправлены 8 байт. Далее приходит BusReset.

Цитата(aaarrr @ Oct 25 2015, 19:46) *
Подозрительно уже начиная с п.5, какой промежуток времени проходит между пп.4-5?
Да. Подозрительно.
1. OTG_FS_GINTSTS_USBRST /* USB device bus reset */ time = 559
2. OTG_FS_GINTSTS_ENUMDNE /* Enumeration done */ time = 569
3. OTG_FS_GINTSTS_RXFLVL /* Receive FIFO non-empty */ time = 596
4. OTG_FS_GINTSTS_RXFLVL /* Receive FIFO non-empty */ time = 596
5. OTG_FS_GINTSTS_USBRST /* USB device bus reset */ time = 6564

Время в миллисекундах от старта МК.

Вопрос мой такой - я должен вычитывать OUT FIFO сразу при приходе OTG_FS_GINTSTS_RXFLVL?
Моя программа при приходе этого прерывания просто считывает вершину OTG_FS_GRXSTSP. Ждет прерывание SETUP и там уже обрабатывает пакет. Но после обработки и отправки ответа начинается какая то каша... ПРи том что OTG_FS_GINTSTS_RXFLVL сыплется постоянно хотя я квитирую это прерывание.
aaarrr
Цитата(prottoss @ Oct 25 2015, 17:17) *
Не может запрашивать меньше байт чем размер Device Descriptor.

Может.

Цитата(prottoss @ Oct 25 2015, 17:17) *
4. OTG_FS_GINTSTS_RXFLVL /* Receive FIFO non-empty */ time = 596
5. OTG_FS_GINTSTS_USBRST /* USB device bus reset */ time = 6564

Тут хост явно чего-то безуспешно ждет. Странно только, что так долго.

Цитата(prottoss @ Oct 25 2015, 17:17) *
Вопрос мой такой - я должен вычитывать OUT FIFO сразу при приходе OTG_FS_GINTSTS_RXFLVL?
Моя программа при приходе этого прерывания просто считывает вершину OTG_FS_GRXSTSP. Ждет прерывание SETUP и там уже обрабатывает пакет.

Выше уже ответил.
prottoss
А OTG_FS_GINTSTS_RXFLVL, как я понял из даташита, не квитируется? Или квитируется... В документации так много путаницы.
aaarrr
Цитата(prottoss @ Oct 25 2015, 18:30) *
А OTG_FS_GINTSTS_RXFLVL, как я понял из даташита, не квитируется? Или квитируется... В документации так много путаницы.

Нет, нужно просто прочитать OTG_FS_GRXSTSP.
prottoss
Цитата(aaarrr @ Oct 25 2015, 21:37) *
Нет, нужно просто прочитать OTG_FS_GRXSTSP.


хм... ну я так и делаю - толку нет. Происходит то что сказал выше.

1.Читаю GRXSTSP.
2. Жду STUP от OUT EP.
3.Разрешаю IN FIFIO empty.
4. по приходу п.3 отправляю данные.
aaarrr
Цитата(prottoss @ Oct 25 2015, 18:44) *
1.Читаю GRXSTSP.
2. Жду STUP от OUT EP.

1. Что в PKTSTS?
2. Не ждите STUP, ориентируйтесь на PKTSTS.
prottoss
Цитата(aaarrr @ Oct 25 2015, 22:11) *
1. Что в PKTSTS?
2. Не ждите STUP, ориентируйтесь на PKTSTS.


Зачем тогда вообще нужен бит STUP в регистре OTG_FS_DOEPINT0???
aaarrr
Цитата(prottoss @ Oct 25 2015, 19:19) *
Зачем тогда вообще нужен бит STUP в регистре OTG_FS_DOEPINT0???

Не знаю, но факт в том, что точно можно обойтись без него.
prottoss
Цитата(aaarrr @ Oct 25 2015, 22:26) *
Не знаю, но факт в том, что точно можно обойтись без него.


Интересно:

Bits 20:17PKTSTS:Packet status
Indicates the status of the received packet
0001: Global OUT NAK (triggers an interrupt)
0010: OUT data packet received
0011: OUT transfer completed (triggers an interrupt)
0100: SETUP transaction completed (triggers an interrupt)
0110: SETUP data packet received
Others: Reserved

А что тогда означает фраза "triggers an interrupt"?
aaarrr
Цитата(prottoss @ Oct 25 2015, 19:50) *
А что тогда означает фраза "triggers an interrupt"?

Загадка.

Цитата
0100: SETUP transaction completed (triggers an interrupt)
0110: SETUP data packet received

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

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

OTG_FS_DOEPCTL0.EPENA установлен?
prottoss
Цитата(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 программируются сразу после вычитывания буфера.
aaarrr
Цитата(prottoss @ Nov 7 2015, 21:54) *
Т.е. NAK и EPENA программируются сразу после вычитывания буфера.

Так выходит, что до получения первого пакета EPENA не установлен?
prottoss
Цитата(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 точке я еще принимать не пробовал. Пока хочу разобраться почему в буфере не то что передал хост.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.