Перейти к содержанию
    

Всмысле? Функция hwtx() выше, вызываю её вручную, по команде в UART консоль.

 

    while(1){
        if((USART3->SR & USART_SR_RXNE)){ // data received
            char c=USART3->DR;
            //...
            if(c=='3'){hwtx();}
        }

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кажется, чего-то я в этой жизни не понимаю :(

Из девайса в комп через второй эндпоинт отправляется только один пакет, после чего этот эндпоинт наглухо виснет. Пробовал:

1. Сбрасывать FIFO через регистр GRSTCTL. Как выборочно, так и все.

2. Отключать-включать эндпоинт, ставить CNAK

3. Сбрасывать весь регистр DIEPCTL2 в ноль, и заново конфигурировать

4. Плясать с бубном

 

Идеи закончились. После успешной отправки "Hello world" на комп, второй раз отправить не удаётся. Только перетыкание кабеля срабатывает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

(Назначение 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);
}

Изменено пользователем SviMik

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Собственно, я ошибок не вижу. Я делаю все примерно тоже самое, единственное, дополнительно устанавливаю NAK в конце отправки пакета. Но, по идее, он должен ставиться автоматом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я сдаюсь :(

Можете выложить какой-нибудь минимальный рабочий пример с USB?

Или может я выложу свой проект целиком?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подниму тему.

Подскажите плз, все глаза стёр уже где узнать адрес 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) после установки адреса проходит нормально.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но комп посланного дескриптора не видит, а свободное место в 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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ещё разик подниму тему.

 

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

 

Прикрутил библиотеку libopencm3, сделал из неё HID. Обмен - по нулевому endpoint'у блоками в 32 байта.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ещё разик подниму тему.

 

На эти грабли: 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. И я надеюсь что в реальных условиях такого потока не будет. :)

 

Правда на текущий момент есть два "нюанса":

1) Не работает на одном из ноутбуков у сотрудника - устройство обнаруживается, но данные в программу от устройства не поступают.

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

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

 

libopencm3 мельком смотрел - смутила необходимость в цикличном выполнении функции usbd_poll. В библиотеке от st все callback'и из OTG_FS_IRQHandler дергаются.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Рекомендацию библиотеки 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 использовал возможность использовать несколько транзакций в одном фрейме?

 

 

 

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

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

 

libopencm3 мельком смотрел - смутила необходимость в цикличном выполнении функции usbd_poll. В библиотеке от st все callback'и из OTG_FS_IRQHandler дергаются.

Не понимаю, почему так сделали, но там уже почти всё готово для оборачивания этого poll() в прерывание. Собственно, эта часть заработала почти сразу. Дальше - аналогично, штатными callback'оми (правда, тут они динамические - через указатели).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По спецификации 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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подумал-подумал, и окончательно запутался.

 

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

 

А в control можно ведь засунуть длинный пакет, чтоб оно "само" резало-склеивало?.. Вроде б не запрещают.

Сейчас посмотрю, что происходит на границе второй-третий пакет...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

окончанием данных служит пакет длинной меньше максимального

если надо передать данные кратной длине пакета, то за последним полным пакетом посылают пакет 0 длинны как признак окончания.

 

целостность пакета как я понимаю берет на себя железо. А вот деление на пакеты я встречал разные реализации. У кого-то надо прям руками заполнять по пакетно, у кого-то один здоровый буфер и железо контроллера само режет. Я не знаю реализации STM, у них USB какой-то чудной...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...