И второй вопрос: как я понял, размер пакета для нулевой EP ограничен снизу, для FS USB 2.0 у меня меньше 16 байтов не работает. Действительно ли есть такое ограничение, или где-то в коде ошибка?
Нет. Только что проверил на 8-битной точке, все работает.
Цитата:
Так вот такой вопрос: как лучше (как принято): принимать указатель на функцию или std::function?
Не думаю, что вам это поможет, но в моем варианте за разбиение данных по размеру endpoint'a (кроме ep0) отвечает юзерский код, вызываемый по колбэку endpoint_IN. Но у меня Си, не С++.
Только что проверил на 8-битной точке, все работает.
Эх, а я уж понадеялся, что все нормально. А на какой ОС, можете сказать? Просто вроде проскакивало здесь, что тот же Linux более лояльный (у меня самая свежая Win10).
COKPOWEHEU писал(а):
за разбиение данных по размеру endpoint'a (кроме ep0) отвечает юзерский код
Выбирал, как сделать, решил попробовать освободить юзера от необходимости разбивать самостоятельно. Но, возможно, тоже приду к тому, что это сам пользователь должен делать, если окажется слишком накладно.
А что именно вы хотите настолько эффективно посылать? В том смысле что в USB весь обмен хост-центрчен, то есть он дает устройству команду "мне нужно столько-то байт", устройство посылает и спит до следующей команды. То есть информация о завершении ему просто не нужна. Есть, конечно, исключение с Interrupt-точками, но там посылки обычно мелкие и в буфер влезают запросто. Или зайдем с другой стороны - MSD, где надо сначала огромный кусок данных послать, а потом еще специальный пакет-подтверждение. Это для простого буфера (или что там у вас) наоборот неподъемная задача. Откуда ему знать что после передачи основного буфера надо еще дополнительный передать? То есть даже так юзеру останется немало работы.
Цитата:
Эх, а я уж понадеялся, что все нормально. А на какой ОС, можете сказать?
Linux, WinXP, win10. Но в документации прямо сказано что ep0 может быть 8, 16, 32 и 64 байта. А для низкоскоростных только 8 байт, без вариантов.
Выбирал, как сделать, решил попробовать освободить юзера от необходимости разбивать самостоятельно.
Имеет смысл сделать очередь отправки в ep0. Для остальных точек на откуп пользователя буферизация, так как даже в пределах одного класса задачи могут быть совсем разные и требуют творческого подхода.
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Очередь это разбиение одного пакета на кусочки по размеру точки. Отправлять байты по своему желанию через нее нельзя, только в ответ на запросы. Ну а очередь на передачу одного пакета и у меня реализована. Даже банальный DeviceDescriptor занимает больше 8 байт, а другие могут и в 64 байта не поместиться.
В случае USB очередь из нескольких пакетов оправдана разве что для Interrupt-точек. Ну не знаю, чтобы прикинуться клавиатурой и послать последовательность символов.
В случае USB очередь из нескольких пакетов оправдана разве что для Interrupt-точек.
Но я и в этом случае соглашусь с вашим прошлым сообщением - пусть пользователь сам отправляет, как надо, и в этом случае как раз callback на успешную передачу будет полезен.
Нашел проблему, очень интересно для меня все оказалось. Тыкание пальца в небо показало, что если установку адреса перенести из лямбды в обработчик CTR_TX, то все начинает работать правильно. Практически уверен, что словил следующую ситуацию: после первых 8 (или 16, отладку процесса нумерации так и не осилил) хост кинул второй сброс (что написано в "USB in a NutShell", надо быть все-таки более внимательным), но поле класса, обозначающее оставшееся количество байтов для передачи не обнулилось. Далее пришел SetAddress, на что я кинул ZLP, но и там остаток не обнулил, поэтому в обработке успешной передачи ZLP девайс отправил хосту оставшиеся 2 байта от дескриптора устройства, хост сошел с ума, дважды попытался завершить нумерацию, ничего не получилось, выдал ошибку. Сейчас в отправке ZLP обнуляю счетчик остатка и все нормально. Спасибо за помощь.
Что-то вы всё усложняете. Там же тупой автомат "Запрос -> Ответ". По reset всё сбросить.
Размер очереди отправки задаётся только в момент формирования ответа или обнуляется по reset. Если ответ это ZLP, то и очередь автоматом обнулится. При штатном прохождении энумерации не должно быть ситуаций когда хост даёт новый запрос не дочитав ответ на старый. Но автомат должен быть к этому готов. При формировании каждого нового ответа очередь инициализируется заново. Досылать ничего от прошлого ответа уже не надо. Хотя, повторюсь, при правильном обмене такой ситуации не должно возникать.
Проверьте, что вы правильно обрабатываете следующие моменты: 1. По ресет надо сбрасывать все регистры usb-контроллера в состояние как до энумерации. Все ваши программные очереди и статусы тоже. 2. При ответе на SetAddress надо сначала отправить ZLP и только после его ухода записать полученный адрес в регистр. Я недавно открыл для себя, что самое оптимальное по коду это при каждом CTR_TX в ep0 писать в регистр адрес. Для контроллеров с OTG с этим можно не заморачиваться, у них можно устанавливать адрес сразу. 3. При запросе дескрипторов хост пишет сколько он хочет получить в ответ. Если дескриптор больше, чем просит хост, то отправить надо столько сколько попросили. Не надо пихать весь дискриптор в этом случае. Хост по заголовку увидит реальный размер дескриптора и переспросит больше, если захочет. В обратной же ситуации, когда просят больше чем есть, надо отправлять реальный размер. 4. Если размер дескриптора кратен размеру конечной точки, то в конце надо ZLP дослать. Похоже, автомат хоста не доверяет длине, написанной в поле дескриптора, а за конец ответа принимает ситуацию когда пакет меньше размера конечной точки. И только после этого начинает проверку и разбор дескриптора.
Если учесть вышеперечисленные особенности, то нештатных обрывов или недосылов не будет.
Насчёт отладки процесса энумерации - посмотрите мой проект. Там в RTT всё что может быть полезно валится. RTT вообще стоит освоить и в каждом проекте в Debug ветке использовать.
3. При запросе дескрипторов хост пишет сколько он хочет получить в ответ.
Обычно сначала запршивает 8 байт
Цитата:
4. Если размер дескриптора кратен размеру конечной точки, то в конце надо ZLP дослать. Похоже, автомат хоста не доверяет длине, написанной в поле дескриптора, а за конец ответа принимает ситуацию когда пакет меньше размера конечной точки.
Дело не в хосте, а в устройстве. Оно может послать данных меньше, чем хочет передать хост. А неоконченный пакет как раз и является признаком конца передачи. Даже если пакет обрывается не успев начаться. И никто не отменял криворуких разработчиков железа (вроде меня, azhel12 или китайских бракоделов - не путать с нормальными разработчиками). Они вполне могут послать и слишком длинный ответ, и внутренне противоречивый, который невозможно корректно распарсить. И хост должен попытаться. Или хотя бы не сойти с ума.
VladislavS, я смотрю важнее всего найти повод поспорить именно для вас! Ну вот вроде бы ни слова возражения не сказал - нет, VladislavS считает своим долгом начать срач!
Будьте добры расшифровать что вы хотели сказать этими цитатами. Во избежание очередного недопонимания. Спойлер
Цитата:
поскольку для ep0 допустим размер 8 байт
Согласно стандарту размер ep0 может быть 8, 16, 32 или 64 байта (для низкоскоростных - только 8 байт). Размер DeviceDescriptor составляет 18 байт, то есть в минимальный размер он не помещается. Размер Configuration или HID Descriptor'ов вообще может быть любым, в том числе больше 64 байт. Значит поддержка разбиения пакета на кусочки по размеру ep0 необходима в любом случае.
Цитата:
см. выше: библиотека это скомпилированный файл. То-то и оно, что в заголовочниках исполняемый код не пишут.
Это общеизвестный факт, не знаю зачем его цитировать.
Цитата:
Обычно сначала запршивает 8 байт
Опять-таки: И? Ну да, обычно если размер заранее неизвестен запрашивается сначала 8 байт или минимальный размер дескриптора. Какие выводы вы из этого хотите сделать?
см. выше: библиотека это скомпилированный файл. То-то и оно, что в заголовочниках исполняемый код не пишут.
Это общеизвестный факт, не знаю зачем его цитировать.
Вот именно об этом я и говорил. Категоричное ОБЩЕИЗВЕСТНЫЙ ФАКТ ничего общего не имеющее с действительностью. Все ошибаются, про 8 байт в ep0 вы же поправились. А вот тут не хочу на третий круг заходить.
Я бы в своей реализации хоста в случае неизвестного размера дескриптора просил бы выслать 256 байт ☺ А уж на компе так вообще можно килобайтный буфер выделить и сразу килобайт просить — чего уж там!
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 16
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения