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

 
 
> STM4 USB CDC. Интересное поведение
drozel
сообщение Oct 19 2015, 10:35
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 108
Регистрация: 2-02-11
Пользователь №: 62 650



Использую libopencm3. За основу взят вот этот пример CDC.
Размер фрейма для нашего ендпойнта настроен 64.
Написал простеньку логику: МК принимает фрейм, смотрит первый элемент и высылает назад статик массив размером, указанным в принятом байте.
Таким образом, я в терминале посылаю число и в ответ получаю заказанное кол-во байт.
Код:
Код
static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep)
{
    (void)ep;

    int len = usbd_ep_read_packet(usbd_dev, 0x01, USBio.buffer, 64);
    сdcacm_data_tx((uint8_t *)textBuf, USBio.buffer[0]);
}


Посылаю число 0х20 - получаю 32 байта данных.
Посылаю число 0х3F - gjkexf. 63 байта в ответ.
Посылаю 0x40 - тишина. Еще раз - тишина. Теперь внимание! Посылаю 0х01 - получаю 129 байт.
Т.е. пришли все запрошенные за прошлые 3 раза данные.
Выходит, что если МК посылает кол-во байт, совпадающее с размером фрейма - данные где-то зависают.

Начал копать: посылает ли МК? Поставил коллбек по окончанию передачи, виду, что передача проходит.
Принимает ли ПК? К сообщению прикреплен скриншот USB сниффера.
Данные действительно где-то зависают. Буфер драйвера? Буфер USB контроллера?

Кто сталкивался?

Прикрепленное изображение


UPD: нащел аналогичный вопрос на форуме СТ. Он там остался без ответа)
UPD2: Вот тут пояснили, что передача длиной равной размеру кадра должна дополняться передачей нулевой длины. Однако, такая логика не согласуется с логикой разрабов libopencm3, которые используют следующую логику для проверки занятости ендпойнта в функции отправки:
Код
while(usbd_ep_write_packet(usbd_dev, 0x82, buf, len) == 0);

Функция возвращает 0, если идет передача, таким образом происходит ожидание освобождения ендпойнта. Посылка длиной 0 байт приведет к зависанию и вообще не похоже, что такая вещь предусмотрена разрабами

Сообщение отредактировал drozel - Oct 19 2015, 10:46
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Kabdim
сообщение Oct 19 2015, 11:00
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Тем не менее zero length packet нужен.

Сообщение отредактировал Kabdim - Oct 19 2015, 11:00
Go to the top of the page
 
+Quote Post
drozel
сообщение Oct 19 2015, 11:05
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 108
Регистрация: 2-02-11
Пользователь №: 62 650



Цитата(Kabdim @ Oct 19 2015, 17:00) *
Тем не менее zero length packet нужен.

Я правильно понимаю, что без zero-length данные зависают на стороне приемника? Чем вообще ограничивается кол-во данных, которые можно протолкнуть без zero-packet?
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Oct 19 2015, 13:50
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Цитата(drozel @ Oct 19 2015, 14:05) *
Я правильно понимаю, что без zero-length данные зависают на стороне приемника? Чем вообще ограничивается кол-во данных, которые можно протолкнуть без zero-packet?

Да.
Если вопрос про макс размер трансфера, то афаик зависит от операционки, а именно драйвера USB. Для винды так. Если вопрос про то что бы не вставлять ZLP, то тоже довольно очевидно: если передаете байтов картных пакету нужно добавить 1 фейковый байт к передаче. Но решение не лучшее. Лучше использовать/написать более вменяемую библиотеку.
Go to the top of the page
 
+Quote Post
SSerge
сообщение Oct 19 2015, 14:05
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Цитата(Kabdim @ Oct 19 2015, 20:50) *
Если вопрос про то что бы не вставлять ZLP, то тоже довольно очевидно: если передаете байтов картных пакету нужно добавить 1 фейковый байт к передаче. Но решение не лучшее. Лучше использовать/написать более вменяемую библиотеку.

Можно и наоборот: никогда не передавать больше 63 байт за раз.
Это сделать значительно проще, не нужно досконально изучать и переписывать всю библиотеку.


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Oct 19 2015, 14:49
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Цитата(SSerge @ Oct 19 2015, 17:05) *
Это сделать значительно проще, не нужно досконально изучать и переписывать всю библиотеку.

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

drozel, у меня используется следующая схема:
usbd_poll() вызывается из прерывания, там есть два основных коллбэка:
- out ep складывает принятые данные в буфер. Оттуда основная задача по мере сил и возможностей выгребает данные.
- in ep пытается "достать" данные из буфера. Заполнение буфера и запуск передачи (однократный вызов write_ep()) - из основной задачи.

В эту схему пакет нулевой длины легко приделывается, никаких while (write_ep(...)) {} не нужно. Хотя, конечно, кто ж им мешал возвращать отрицательные значения?..


PS полез рыться на репозитарий libopencm3, обнаружил те же самые грабли, но по обмену control endpoint. Исправили ровно неделю назад.
Вот уроды, я ж в этот код уже несколько месяцев не лазил (все дескрипторы у меня короче)...
До остальных эндпоинтов у них руки пока не дошли.


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


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


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