Pull to refresh

Comments 10

Заместо нечитаемых функций на 10 000 строк, пришло не читаемое это. А можно же просто писать одноразовый код под текущий проект и быть счастливым.


Ответ для DSarovsky, ну я про нее и имел ввиду. Типо базовое тупейшее ООП без попыток в супер универсальность (ну или суперуниверсальность по самому минимуму вплоть до хардкода).

Я соглашусь разве что с нечитаемостью шаблонной магии, все остальное, как мне кажется, читается даже лучше за счет отсутствия лишних параметров (чего получатся добиться за счет статических элементов). А для конечного потребителя магия скрыта: объяви конечные точки, положи их в интерфейсы, интерфейсы положи в конфигурации, конфигурации в устройство и все заработает.

Ответ для Bobovor: тогда я вас не понял, честно говоря. Пока я на опыте вижу такую зависимость: стремление к суперуниверсальности приводит к усложнению кода, по-другому не получалось. И тогда, как вы и сказали, либо писать понятный одноразовый код под текущий проект (считаю это нормальной практикой, кстати, иметь набор сниппетов и их использовать просто), либо однажды нагородить и потом использовать. Как ни крути, большая часть программистов если не сама пишет НЕодноразовый код, то как минимум его использует (в виде различных библиотек).

Интересно что же такое Interface... Кажется это переусложнено, без потери эффективности думаю можно сделать и с меньшим количеством шаблонных аргументов, хотя бы

Для всех элементов из иерархии я предложил такой набор параметров: всё, что должно быть в дескрипторе + дочерние элементы (то есть для конфигурации интерфейсы, для интерфейсов — конечные точки + что-то классозависимое). Хотя буквально недавно на радиокоте случилась дискуссия с VladislavS, у него видение ровно наоборот: пользователь задает дескриптор всего устройства, а уже суперконфигуратор из него рождает конфигурации, интерфейсы, точки и прочее. Так, наверно, конкретные типы получатся более простыми (по крайней мере банальные параметры типа номера/класса/протокола отпадут). Но уже слишком много сил потрачено, поздно мне переобуваться.

Зацепился параноидальным глазом: в HandleRx - возможность переполнения буфера (в качестве CBW шлём два пакета: 30 байт, затем 64, в результате в структуру размером 31 байт прилетят все 94).

Кроме того, для mass storage принимать из bulk EP произвольные куски пока не наберётся целый CBW - противоречит стандарту. Одиночный bulk transfer заканчивается либо пакетом длины меньше MaxPacketSize данной EP, либо пакетом нулевой длины (размеры CBW и CSW нарочно выбраны не кратными никакому из возможных MaxPacketSize). Если вам, к примеру, шлют два пакета 20+11 байт - это две отдельные (в данном случае неверные) транзакции, сшивать такое в целый CBW - некорректно (корректно - игнорировать обе). То же самое касается и фазы данных - если в CBW пообещали прислать гигабайт, но завершили передачу досрочно (теми же short packet/ZLP) - обрабатываете что дали и заявляете о недостаче в CSW (то самое поле dCSWDataResidue).

Mass Storage Reset через EP0 - важен, им, к примеру, хост может оборвать команду в фазе данных (заставить вас забросить текущий приём/передачу данных и вернуться к ожиданию нового CBW).

Если интересно, usb.org публикует всякие command verifier tools для тестирования на соответствие стандарту, можно много чего отловить.

Спасибо за замечания, с первым полностью согласен, что такая проверка необходима.
По поводу второго замечания сходу не уверен, что правильно понял: то есть нужна проверка того, что если размер меньше макс. размера конечной точки, то он обязательно должен быть последним (дополнить структуру CBW)?

В состоянии ожидания CBW прямо проверяете на соответствие параметра size==sizeof(CBW), если нет - никуда ничего не копируете и сигналите STALL (см. п. 6.6.1 https://www.usb.org/sites/default/files/usbmassbulk_10.pdf), хост снимает его через Mass Storage Reset. В состоянии приёма данных смотрите, если size<MaxPacketSize (у вас он 64) - это конец фазы данных (даже если пришло меньше, чем заявлено в CBW). Если вы в фазе данных, а вам в EP0 прилетел Mass Storage Reset - "забываете" текущую команду и переходите в ожидание CBW.

Спасибо, я понял. Правда, проверять size==sizeof(CBW) опасно, так как точка может быть с макс. размером пакета в 8/16 байтов, это не запрещено, но, как понял, в этом случае должны прилететь N * MaxPacketSize + M (последний).
Со сбросом тоже вроде понял, надо обнулить все аккумуляторы и состояния.
её скриншот приведен на рисунке 9 (0.756 МБ/с). Результат чуть лучше, но все равно примерно вдвое меньше предела в 12,5 Мбит/с.

Да вроде все нормально, что-то близкое к теоретическому пределу вы и выжали. Максимальная частота на линиях D+, D- составляет 12 МГц, то есть сырых 12 Мб/с (откуда взялось 12.5?) или 1.5 МБ/с. Добавляем накладные расходы на служебные пакеты, добавление нулей после каждых шести единиц, задержку между пакетами, сигналы SOF и прочее. Добавляем 10%, зарезервированные под Control endpoints. Как раз 800 — 1000 кБ/с и получается. Ну, может еще сколько-то времени теряете на копирование буферов, я в вашем коде не разбирался.


Экспериментировал на контроллере Stm32f401ccu6, который предлагает 64Кб RAM, чего, в принципе, хватает для носителя с файловой системой FAT 12.

У вас 256кБ флешки, можно было там готовый образ ФС разместить, чтобы при подключении к компу показывалось не что-то бракованное "отформатируй меня", а нормальная флешка.


Для той же цели можно было и виртуальную FAT собрать (получился бы у вас новый шаблон в коллекцию)


Не удержался и проверил свою VirFat на L151 — создал на ней пять "файлов" по 24 МБ:


# dd if=/dev/sdc of=/dev/null status=progress
127517184 байт (128 MB, 122 MiB) скопирован, 207 s, 615 kB/s
250112+0 записей получено
250112+0 записей отправлено
128057344 байт (128 MB, 122 MiB) скопирован, 207,865 s, 616 kB/s

Еще проверил "честный" MSD с таким же отображением конца на начало, что у вас. Правда, готовый образ ФС все же использовал — не форматировать же каждый раз заново:


# dd if=/dev/sdc of=/dev/null status=progress
30917120 байт (31 MB, 29 MiB) скопирован, 39 s, 791 kB/s 
61440+0 записей получено
61440+0 записей отправлено
31457280 байт (31 MB, 30 MiB) скопирован, 39,5894 s, 795 kB/s

В общем-то, порядок скорости такой же, как у вас.

откуда взялось 12.5
Не знаю, я почему-то всегда считал, что 12.5, сейчас заглянул в вики, действительно 12. Не совсем доволен, потому что в прошлом году, когда плотно занимался USB на F103, при поддержке EasyLy удалось из CDC выжать 8.8, но там мы, правда, просто через libusb в конкретную конечную точку чистые данные гнали, без служебных данных, так что, наверно, примерно так и выходит.

У вас 256кБ флешки, можно было там готовый образ ФС разместить, чтобы при подключении к компу показывалось не что-то бракованное «отформатируй меня», а нормальная флешка.
Я так и хотел сначала (собственно, по мотивам Вашей статьи), но в итоге решил сделать на RAM, было интересно именно штатными средствами попробовать поработать (включая форматирование).
Sign up to leave a comment.

Articles