SviMik
Участник-
Постов
11 -
Зарегистрирован
-
Посещение
Репутация
0 Обычный-
Я сдаюсь :( Можете выложить какой-нибудь минимальный рабочий пример с USB? Или может я выложу свой проект целиком?
-
(Назначение hwtx - слать Hello World. Исключительно для дебага, поэтому упрощена до безобразия) Скорее всего, я упустил что-то важное, но не могу понять что :( Для общения через нулевой эндпоинт используется тот же алгоритм, и он работает. Разница только в типах эндпоинтов (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); }
-
Кажется, чего-то я в этой жизни не понимаю :( Из девайса в комп через второй эндпоинт отправляется только один пакет, после чего этот эндпоинт наглухо виснет. Пробовал: 1. Сбрасывать FIFO через регистр GRSTCTL. Как выборочно, так и все. 2. Отключать-включать эндпоинт, ставить CNAK 3. Сбрасывать весь регистр DIEPCTL2 в ноль, и заново конфигурировать 4. Плясать с бубном Идеи закончились. После успешной отправки "Hello world" на комп, второй раз отправить не удаётся. Только перетыкание кабеля срабатывает.
-
Всмысле? Функция hwtx() выше, вызываю её вручную, по команде в UART консоль. while(1){ if((USART3->SR & USART_SR_RXNE)){ // data received char c=USART3->DR; //... if(c=='3'){hwtx();} }
-
Всмысле флаг прерывания? Да, как и все остальные прерывания, сбрасываю. }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); } }
-
Хорошо. Тоесть моя конфигурация выше впринципе правильная, и должна работать? Но почему же с отправкой у меня проблемы... При этом, в нулевой эндпоинт отправлять дескрипторы проблем нет, а отправить данные в второй эндпоинт - проходит только первый пакет и всё. Возможно, с bulk эндпоинтами как-то иначе поступать надо? А документация уже утомила своими ляпами... В таблице одно, в тексте другое... Доходит до того, что в таблице бит подписан Reserved, а ниже в тексте даётся его нормальное описание. Или в таблице "r", а в описании сказано, что в него писать надо. IN и OUT тоже путают, приходится логически до всего доходить. Даже ссылки неправильные. кликаю в оглавлении на DIEPTSIZx, попадаю на DOEPTSIZx... такой вот тест на внимательность :( Извиняюсь, накипело...
-
Вомзжно, я что-то не так понял с 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;
-
Пытаюсь реализовать 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, а отправка не идёт...
-
Вот же однако... Заработало! Плюс вам в карму, если б она тут была :) А я CNAK только один раз при инициализации ставил, и думал оно так и будет... Интересно, а когда "по правилам" его надо ставить? "после обработки setup" это когда 1. закончил приём setup запроса 2. только записал ответ на setup в FIFO 3. когда отправка моего ответа уже завершена (сейчас я поставил от балды)
-
В моём случае, дескриптор взят из заведомо рабочего проекта, но под другой МК (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 2. EPENA в DIEPCTL0 должен устанавливаться до того, как начну писать данные в FIFO. Однако, я пробовал и другой порядок действий, безрезультатно.
-
Ровно та же проблема, как и в последнем сообщении. XFRCM прерывание получаю, от компа на дескриптор ноль реакции. Дескриптор заведомо рабочий, взят из проекта, который делал на МК другого производителя. Пробовал делать как строго по даташиту, так и переставлять всё, что только возможно - не работает. Если автор решил проблему - хотелось бы узнать как :)