USB-порт может перестать работать после подключения или отключения USB-устройства
Если несколько раз подряд с небольшими перерывами подключить и извлечь устройство USB, то порт USB может перестать отвечать. Когда порт находится в таком состоянии, он не распознает USB-устройство, и оно перестает работать.
В этой статье описаны способы решения этой проблемы.
Необходимые условия
Для выполнения некоторых действий по устранению неполадок, описанных в этой статье, необходимо войти в систему Windows с учетной записью администратора. Если компьютер является персональным, скорее всего, вход в систему с учетной записью администратора уже выполнен. Если компьютер является рабочим и подключен к сети, возможно, потребуется обратиться за помощью к администратору. Чтобы убедиться, что вход в Windows выполнен с учетной записью администратора, перейдите на следующий веб-сайт корпорации Майкрософт:
Решение
Чтобы устранить эту проблему, воспользуйтесь приведенными ниже способами в указанном порядке. После применения каждого способа проверяйте, решена ли проблема. Если нет, переходите к следующему способу.
В этой статье также приводится временное решение проблемы, которым можно воспользоваться, если не помогут другие способы.
Способ 1. Обновление конфигурации оборудования с помощью диспетчера устройств
Обновите конфигурацию оборудования с помощью диспетчера устройств. После этого компьютер сможет распознать USB-устройство, подключенное к USB-порту, и его можно будет использовать.
Чтобы обновить конфигурацию оборудования, выполните указанные ниже действия.
-
Нажмите кнопку Пуск и выберите пункт Выполнить.
Если удалось устранить проблему, дальнейшее содержание этой статьи можно пропустить. Если не удалось устранить проблему, перейдите к следующему способу.
Способ 2. Перезапуск компьютера
Если не удалось решить проблему с помощью обновления конфигурации, перезапустите компьютер. После этого проверьте, работает ли USB-устройство.
Если удалось устранить проблему, дальнейшее содержание этой статьи можно пропустить. Если не удалось устранить проблему, перейдите к следующему способу.
Способ 3. Отключение и повторное включение USB-контроллера
Отключите и снова включите все USB-контроллеры с помощью диспетчера устройств. Это позволит восстановить нормальную работу USB-порта. USB-контроллеры представляют USB-порты в диспетчере устройств. Если расширенное устранение неполадок вызывает затруднения, перейдите к разделу Временное решение.
Чтобы отключить и повторно включить USB-контроллеры, выполните указанные ниже действия.
-
Нажмите кнопку Пуск и выберите пункт Выполнить.
Если USB-порт распознает устройство и его можно использовать, дальнейшее содержание этой статьи можно пропустить.
Если удалось устранить проблему, дальнейшее содержание этой статьи можно пропустить. Если этим методом не удалось устранить проблему,см. раздел «Обходной путь».
Временное решение
Если не удалось устранить проблему с помощью приведенных способов, отключите функцию временного отключения. Обратите внимание на то, что это действие влияет на все драйверы USB-контроллеров (а следовательно, на все USB-порты и подключенные USB-устройства). Поэтому отключить USB-устройства, подключенные к компьютеру, невозможно, и они продолжат потреблять энергию. Кроме того, флажок Разрешить отключение этого устройства для экономии энергии не отображается на вкладке Управление питанием для корневого USB-концентратора.
Чтобы получить помощь при отключении функции временного отключения, перейдите к разделу Помощь в решении проблемы. Если расширенное устранения неполадок не вызывает затруднений, можно отключить эту функцию самостоятельно. Для этого перейдите к разделу Самостоятельное решение проблемы.
Получить помощь в решении проблемы
Чтобы устранить проблему автоматически, щелкните ссылку Устранить проблему. В диалоговом окне Загрузка файла нажмите кнопку Выполнить и следуйте инструкциям мастера устранения проблем.
Примечание. Интерфейс этого мастера может быть доступен только на английском языке, однако автоматическое исправление работает и в других языковых версиях Windows.
Примечание. Решение по устранению проблем можно загрузить на любой компьютер, сохранить его на устройство флэш-памяти или компакт-диск и затем запустить на нужном компьютере.
Самостоятельное решение проблемы
Этот раздел предназначен для опытных пользователей.
В качестве временного решения можно отключить функцию временного отключения USB путем изменения реестра. USB-устройство может не отвечать на запросы из-за состояния гонки в функции временного отключения. Функция выборочной приостановки позволяет эффективно управлять питанием благодаря отключению USB-устройств. Однако иногда она может неправильно выводить USB-устройства из спящего режима. В результате при попытке использования USB-устройства оно не отвечает на запросы.
Также функцию временного отключения можно отключить на сервере, для которого управление питанием неважно или вообще не требуется.
Важно! В этот раздел, способ или задачу включены действия по изменению параметров реестра. Однако их неправильное изменение может привести к возникновению серьезных проблем, поэтому при выполнении таких действий будьте предельно внимательны. Для дополнительной защиты создайте резервную копию реестра. Это позволит восстановить его при возникновении неполадок. Дополнительные сведения о создании резервной копии и восстановлении реестра см. в следующей статье базы знаний Майкрософт:
Создание резервной копии и восстановление реестра Windows XPЧтобы отключить функцию временного отключения, выполните указанные ниже действия.
-
Нажмите кнопку Пуск и выберите пункт Выполнить.
- В меню Правка выберите пункт Создать, затем — Параметр DWORD.
- Введите DisableSelectiveSuspend и нажмите клавишу ВВОД.
- В меню Правка выберите пункт Изменить.
Затем перейдите к разделу Проблема устранена?
Проблема устранена?
Убедитесь, что проблема устранена. Если удалось устранить проблему, дальнейшее содержание этой статьи можно пропустить. Если не удалось устранить проблему, .
Причина
Эта проблема может возникнуть из-за ошибки синхронизации, которая препятствует обнаружению USB-устройства.
Корпорация Майкрософт и производители микросхем, использующихся в устройствах USB, изучили эту проблему. Однако результаты этих исследований нельзя считать окончательными, поскольку воспроизвести условия возникновения проблемы удается не всегда.
Состояние
Корпорация Майкрософт работает над устранением этой проблемы. Дополнительная информация будет размещаться по мере ее появления.
Поиск и устранение неисправностей USB-порта, когда он не работает
В этой статье содержится информация о поиске и устранении проблем, связанных с USB, на компьютере Dell. Пошаговые инструкции по устранению проблем с USB, если порт USB не работает.
Сводка: В этой статье содержится информация о поиске и устранении проблем, связанных с USB, на компьютере Dell. Пошаговые инструкции по устранению проблем с USB, если порт USB не работает.
- Содержание статьи
- Свойства статьи
- Оцените эту статью
Возможно, эта статья была переведена автоматически. Если вы хотите поделиться своим мнением о ее качестве, используйте форму обратной связи в нижней части страницы.
Содержание статьи
Симптомы
Возникли проблемы с USB-устройством, которое не обнаруживается или не распознается на компьютере Dell?
На компьютере Dell может возникнуть проблема, связанная с USB, если вы заметили один или несколько из следующих признаков.
- USB-устройство, которое не обнаруживается или не распознается.
- USB-устройство работает с перебоями.
- Сообщение об ошибке, связанной с драйвером USB.
- Сообщение об ошибке: «USB-устройство работает с меньшей скоростью».
Причина
Проблемы, связанные с USB, могут быть вызваны несовместимостью устройства, устаревшими, неправильными или поврежденными драйверами, поврежденными портами или кабелями USB, неисправным USB-портом и т. д.
Разрешение
ПРИМЕЧАНИЕ. Перед началом процесса поиска и устранения неисправностей отключите USB-устройства от компьютера.
Разверните приведенные ниже разделы для получения подробной информации и выполните действия по поиску и устранению неисправностей в указанной последовательности.
- Приведенные в данной статье инструкции и информация по устранению неисправностей относятся ко всем типам USB-портов (USB Type-A, USB Type-B, Mini USB, Micro USB, USB Type-A 3.0 и USB-C).
- Перед подключением устройств к компьютеру (принтера, сканера и т. п.) необходимо установить драйверы устройств и программное обеспечение для конкретного устройства. Следуйте инструкциям по установке, предоставленным производителем устройства.
ПРЕДУПРЕЖДЕНИЕ. Для некоторых действий по устранению неисправностей может потребоваться перезапуск компьютера. Перед тем как приступить к поиску и устранению неисправностей, добавьте открытые веб-страницы в закладки, сохраните открытые документы, электронные таблицы и несохраненную работу.
ВНИМАНИЕ! Следует выключить или выполнить безопасное извлечение USBустройств, прежде чем отключать их от компьютера. Большинство USB-устройств поддерживают функцию безопасного извлечения оборудования Windows.
Оптимизация системы с помощью SupportAssist
Dell Technologies рекомендует убедиться, что драйверы устройств и BIOS обновлены с помощью приложения SupportAssist для оптимальной производительности USB и устранения распространенных проблем, связанных с USB.
Для запуска приложения SupportAssist выполните следующее.
- Нажмите и удерживайте клавишу Windows (), затем нажмите клавишу q .
- В поле поиска введите SupportAssist
- В списке результатов выберите «SupportAssist (App)».
ПРИМЕЧАНИЕ. Если SupportAssist не отображается в результатах поиска, перейдите на страницу SupportAssist для ПК и планшетов для получения информации о том, как скачать и установить SupportAssist.
ПРИМЕЧАНИЕ. Можно нажать стрелку вниз, а затем запустить отдельный тест. Dell Technologies рекомендует выполнить полную проверку компьютера.
Использование компонента «Оптимизация системы» в SupportAssist
Продолжительность: 00:32
Если доступно, можно выбрать язык субтитров с помощью значка «Настройки» или «CC» в этом видеоплеере.
ПРИМЕЧАНИЕ. Dell Technologies рекомендует перезапустить компьютер после установки обновлений драйверов.
Обновление программы настройки системы (BIOS)
Продолжительность: 02:06
Если доступно, можно выбрать язык субтитров с помощью значка «Настройки» или «CC» в этом видеоплеере.
Если проблема не устранена, перейдите к следующему шагу.
Убедитесь в отсутствии физических повреждений USB-порта или кабеля
Проблемы производительности USB могут возникать, если на USB-кабелях или USB-портах компьютера имеются повреждения. Вы можете столкнуться с одним из следующих признаков: USB-устройство перестает работать, работает с перебоями или USB-кабель «болтается» в разъеме при подключении к компьютеру.
Кабели и порты USB контактируют со средами, которые способствуют скоплению пыли или даже могут привести к физическим повреждениям. Если вы заметили пыль или другие загрязнения в портах или разъемах, очистите их баллоном со сжатым воздухом.
ПРЕДУПРЕЖДЕНИЕ. Не используйте жидкие чистящие средства, воду или влажную ткань. Отсоедините USB-устройство и кабель перед очисткой портов и разъемов с помощью баллона со сжатым воздухом.
Если вы заметили физические повреждения, обратитесь в службу технической поддержки Dell для получения более подробной информации о вариантах ремонта, доступных в вашем регионе. Если повреждения не обнаружены, перейдите к следующему шагу.
Сброс параметров BIOS до заводских настроек
Иногда устаревшие или неправильные настройки BIOS или UEFI вызывают проблемы с USB. Рекомендуется сбросить параметры BIOS или UEFI до заводских настроек.
Для доступа к BIOS или UEFI (программе настройки системы) на компьютере Dell выполните следующие действия.
- Перезапустите компьютер.
- На экране с логотипом Dell нажмите клавишу F2 несколько раз для доступа к BIOS или UEFI.
- На экране BIOS или UEFI нажмите Load Defaults или нажмите клавишу F9 на клавиатуре, чтобы сбросить параметры BIOS до заводских настроек.
ПРИМЕЧАНИЕ. Инструкции по сбросу параметров BIOS или UEFI до значений по умолчанию на вашем компьютере Dell могут отличаться. Дополнительные сведения см. в документации к вашему компьютеру Dell.
Если проблема не устранена, перейдите к следующему шагу.
Запустите диагностический тест оборудования
Выполнение диагностического тестирования оборудования может помочь выявить проблемы, связанные с оборудованием, и предоставить действия, которые помогут устранить неисправность. Чтобы определить, имеется ли на компьютере Dell проблема с оборудованием, рекомендуется сначала запустить на нем диагностическое тестирование оборудования. Компания Dell предлагает как интегрированные, так и онлайн-средства диагностики.
Выполнение диагностического тестирования оборудования с помощью Dell SupportAssist
Если ваш компьютер может загрузиться в Windows и имеет активное подключение к Интернету, запустите тест USB на компьютере с помощью Dell SupportAssist.
Запуск диагностики Dell SupportAssist PSA (Pre-boot System Assessment) или ePSA (Enhanced Pre-boot System Assessment)
- Перезапустите компьютер.
- Когда появится логотип Dell, нажмите клавишу F12 , чтобы выполнить вход в меню однократной загрузки.
- С помощью клавиш со стрелками выберите пункт Diagnostics и нажмите клавишу Enter .
- Чтобы завершить диагностику, следуйте инструкциям на экране и выполняйте соответствующие действия.
- Если диагностика выполнена, перейдите к следующему шагу.
- Если диагностика не выполнена, обязательно запишите код ошибки и код валидации и обратитесь в службу технической поддержки Dell.
Диагностика неисправностей оборудования на ноутбуках или настольных компьютерах Dell с помощью диагностического теста Dell ePSA
Продолжительность: 01:34
Если доступно, можно выбрать язык субтитров с помощью значка «Настройки» или «CC» в этом видеоплеере.Проверка работы USB-устройства на другом компьютере
Чтобы убедиться, что USB-устройство неисправно, отключите USB-устройство от компьютера и подключите его к другому компьютеру. Если устройство не обнаруживается и не работает на другом заведомо исправном компьютере, USB-устройство неисправно. Обратитесь к производителю устройства, чтобы проверить состояние гарантии и узнать информацию о вариантах ремонта для вашего USB-устройства.
Если USB-устройство исправно работает на другом компьютере, перейдите к следующему шагу.
Проверьте диспетчер устройств Windows на наличие ошибок
Диспетчер устройств Windows помогает определить и устранить любые неисправности, связанные с драйверами USB-устройства.
Отображение USB-устройств в диспетчере устройств Windows:
- Нажмите клавишу Windows + R на клавиатуре.
- Введите devmgmt.msc в диалоговом окне « Выполнить » и нажмите клавишу Enter.
- Раскройте раздел Контроллеры USB.
Если проблема не устранена, перейдите к следующему шагу.
Запуск средства устранения неисправностей оборудования Windows
В Microsoft Windows имеются различные средства поиска и устранения неисправностей, предназначенные для быстрой диагностики и автоматического устранения многих проблем персональных компьютеров. Хотя средство устранения неисправностей Windows не может устранить проблемы с оборудованием, его можно использовать как средство для первоначального поиска неисправностей при возникновении проблем с компьютером. Средства устранения неполадок Windows встроены в панель управления в Windows 11, Windows 10, Windows8 или 8.1.
Как запустить средство устранения неисправностей оборудования Windows в Windows 11?
- Нажмите клавиши Windows + X и выберите «Терминал (администратор)».
- Введите msdt.exe -id DeviceDiagnostic в окно PowerShell и нажмите клавишу Enter.
- Откроется диалоговое окно Средство устранения неполадок оборудования и устройств. Нажмите Далее и следуйте инструкциям на экране для завершения процесса устранения неисправностей.
Как запустить средство устранения неисправностей оборудования Windows в Microsoft Windows 10?
- Нажмите Пуск правой кнопкой мыши и выберите Панель управления.
- В разделе Система и безопасность нажмите Поиск и исправление проблем.
- Нажмите Оборудование и звук, затем нажмите Оборудование и устройства.
- Нажмите Далее и следуйте инструкциям на экране для завершения процесса устранения неисправностей.
Как запустить средство устранения неисправностей оборудования Windows в Microsoft Windows 8 или 8.1?
- Нажмите Пуск правой кнопкой мыши и выберите Панель управления.
- В разделе Система и безопасность нажмите Поиск и исправление проблем.
- Нажмите Оборудование и звук, затем нажмите Оборудование и устройства.
- Нажмите Далее и следуйте инструкциям на экране для завершения процесса устранения неисправностей.
Если проблема не устранена, перейдите к следующему шагу.
Скачайте и установите обновления Microsoft Windows
Обновления Windows могут поддерживать работу операционной системы множеством способов. Обновления Windows могут решать определенные проблемы, обеспечивать защиту от вредоносных атак и даже добавлять новые функции к операционной системе.
Как установить Центр обновления Windows в Microsoft Windows 10 и Windows 8 или 8.1?
- Щелкните правой кнопкой мыши кнопку Пуск и выберите пункт Настройки.
- На панели «Настройки» нажмите Обновления и безопасность.
- В левой панели выберите пункт Центр обновления Windows.
- На правой панели нажмите кнопку Проверить обновления.
- Перезагрузите компьютер после скачивания и установки обновлений.
Если проблема не устранена, перейдите к следующему шагу.
Обновите контроллер USB и корневой USB-концентратор
Если проблема не устранена, удаление хост-контроллера USB и корневых USB-концентраторов приведет к принудительной переустановке корневого USB-концентратора во время перезапуска компьютера.
ПРИМЕЧАНИЕ. После удаления корневого USB-концентратора или USB-контроллера USB-клавиатура и мышь перестанут отвечать. Выполните принудительное завершение работы вручную: нажмите и удерживайте кнопку питания в течение 20 секунд.
- Отсоедините USB-устройства, подключенные к компьютеру, за исключением USB-клавиатуры и мыши, прежде чем перейти к следующему шагу.
- Нажмите клавишу Windows + R на клавиатуре.
- Введите devmgmt.msc в диалоговом окне « Выполнить » и нажмите клавишу Enter.
- В окне диспетчера устройств Windows раскройте раздел Контроллеры универсальной последовательной шины.
- Нажмите правой кнопкой мыши на хост-контроллер USB и выберите Удалить.
- Нажмите OK, чтобы подтвердить удаление хост-контроллера USB.
- Повторите шаги 5 и 6, чтобы удалить оставшиеся хост-контроллеры USB.
ПРИМЕЧАНИЕ. Если USB-клавиатура и мышь не отвечают, вручную выполните принудительный перезапуск компьютера и повторите шаги 5 и 6. Для принудительного завершения работы компьютера нажмите и удерживайте кнопку питания в течение 20 секунд.
Чтобы обновить корневой USB-концентратор, выполните следующие действия.
- Отсоедините USB-устройства, подключенные к компьютеру, за исключением USB-клавиатуры и мыши, прежде чем перейти к следующему шагу.
- Нажмите клавишу Windows + R на клавиатуре.
- Введите devmgmt.msc в диалоговом окне « Выполнить » и нажмите клавишу Enter.
- В окне диспетчера устройств Windows раскройте раздел Контроллеры универсальной последовательной шины.
- Нажмите правой кнопкой мыши на корневой USB-концентратор и выберите Удалить.
- Нажмите OK, чтобы подтвердить удаление корневого USB-концентратора.
- Повторите шаги 5 и 6, чтобы удалить оставшиеся корневые USB-концентраторы.
ПРИМЕЧАНИЕ. Если USB-клавиатура и мышь не отвечают, вручную выполните принудительный перезапуск компьютера и повторите шаги 5 и 6. Для принудительного завершения работы компьютера нажмите и удерживайте кнопку питания в течение 20 секунд.
ПРИМЕЧАНИЕ. Может потребоваться установка драйверов USB-устройств и приложений. Чтобы установить USB-устройство, следуйте инструкциям производителя.
Если проблема не устранена, перейдите к следующему шагу.
Обновите корневой USB-концентратор в безопасном режиме Windows
Безопасный режим Windows позволяет определить, связана ли проблема с операционной системой, драйверами устройства или ПО сторонних производителей. Для получения сведений о загрузке компьютера Dell в безопасном режиме см. статью базы знаний Dell ниже в зависимости от операционной системы, установленной на компьютере.
- Microsoft Windows 10
- Microsoft Windows 8 или 8.1
Безопасный режим с загрузкой сетевых драйверов
Продолжительность: 0:50
Если доступно, можно выбрать язык субтитров с помощью значка «Настройки» или «CC» в этом видеоплеере.Если проблема не устранена, перейдите к следующему шагу.
Выполните восстановление системы Windows
Восстановление системы — это встроенный инструмент Windows, предназначенный для защиты и восстановления операционной системы. Если возникла неполадка в компьютере, перед восстановлением заводских настроек по умолчанию или переустановкой операционной системы необходимо воспользоваться функцией восстановления системы.
Выберите операционную систему, установленную на компьютере, для получения дополнительной информации о том, как выполнить восстановление системы.
- Microsoft Windows 10
- Microsoft Windows 8 или 8.1
Если проблема не устранена, перейдите к следующему шагу.
Восстановите заводские настройки компьютера
Если диагностические тесты на USB–портах пройдены, почти наверняка проблема связана с программным обеспечением, установленным на компьютере. Если описанные выше действия по устранению неисправностей не помогли устранить проблему, в качестве последнего средства попробуйте восстановить на компьютере заводские настройки по умолчанию.
В компьютерах Dell небольшой объем пространства на жестком диске зарезервирован для переустановки операционной системы. Это простейший способ восстановления заводских настроек на компьютере. В ходе восстановления с компьютера удаляются все пользовательские данные, поэтому перед началом этого процесса необходимо сделать резервные копии всех файлов.
ПРЕДУПРЕЖДЕНИЕ. Восстановление заводских настроек по умолчанию или переустановка операционной системы с помощью любого носителя для восстановления системы приведет к удалению всех данных на вашем компьютере. Убедитесь в том, что вы сохранили все важные данные, такие как документы, электронные таблицы, изображения и видео, перед восстановлением или переустановкой операционной системы.
Выберите операционную систему, установленную на компьютере, для получения дополнительной информации о том, как выполнить восстановление заводских настроек по умолчанию.
- Microsoft Windows 10
- Microsoft Windows 8 или 8.1
ПРИМЕЧАНИЕ. После восстановления или переустановки операционной системы рекомендуется скачать и установить последние версии драйверов устройства со страницы Драйверы и загружаемые материалы сайта Dell.
Как выполнить сброс настроек в Windows 10
Продолжительность: 01:36
Если доступно, можно выбрать язык субтитров с помощью значка «Настройки» или «CC» в этом видеоплеере.Руководство пользователя
По умолчанию в Windows 10 отключается сетевой протокол SMBv1 (Server Message Block), который отвечает за удаленный доступ к файлам, принтерам и сетевым ресурсам сети. Вместе с ним отключается служба «Обозреватель компьютеров» ( Computer Browser ). Поэтому в Сети Windows ( Сетевом проводнике ) больше не могут отображаться компьютеры Windows с помощью протокола NetBIOS.
Доступ к подключенному накопителю можно получить по IP-адресу роутера (по умолчанию 192.168.1.1 ). В адресной строке Проводника вводим \\192.168.1.1
Начиная с версии KeeneticOS 3.3 была добавлена поддержка протокола многоадресного обнаружения WS-Discovery (Web Services Dynamic Discovery) и службы разрешения имен в одноранговой сети путем многоадресной рассылки LLMNR (Multicast Name Resolution Link-Local), которые будут отвечать за удаленный доступ к файлам, принтерам, сетевым ресурсам сети и обнаружение доменного имени роутера в Сети Windows ( Сетевом проводнике ), как при работе службы » Обозреватель компьютеров » (Computer Browser) и протокола (интерфейса) разрешения уникального имени NetBIOS (Network Basic Input/Output System).
Если роутер не отображается в Сети Windows ( Сетевом проводнике ), необходимо будет проверить:
- Установлен ли в интернет-центре компонент системы » Общий доступ к файлам и принтерам (TSMB/CIFS) «. Подключитесь к веб-конфигуратору и перейдите на страницу » Общие настройки «. В разделе » Обновления и компоненты » нажмите » Изменить набор компонентов «, найдите компонент » Общий доступ к файлам и принтерам (TSMB/CIFS) » и убедитесь, что он установлен.
После включения служб проверьте доступность компьютеров в Сети Windows (Сетевом проводнике). Метод обнаружения WSD :
- UDP/137 — Сеть MS Windows (WINS)
- UDP/138 — Сеть MS Windows (Служба датаграмм NetBIOS)
- TCP/139 — Сеть MS Windows (SMB)
- TCP/445 — MS Active Directory Services
По умолчанию они разрешены для Домашней сети .
Важно
Устройства домашней сети Windows и роутер должны находится в одной » Рабочей группе » (по умолчанию » WORKGROUP «).
Примечание
В операционной системе KeeneticOS имеется поддержка протоколов доступа в TSMB/CIFS : SMBv1/2/3, LLMNR, WSD.
Учимся работать с USB-устройством и испытываем систему, сделанную на базе контроллера FX3
В двух предыдущих статьях мы сделали USB 3.0 систему на базе контроллера FX3. Пришла пора научиться работать с нею из своих программ для PC. Ну, и попутно понять, насколько получившаяся система пригодна для практического применения. Действительно ли ширины канала хватает на весь поток? И не теряются ли единичные байты из потока? Кто хоть немного поработал тестировщиком, не поверит в то, что если система в принципе работает, значит, работает и в деталях. А я на этой должности проработал лет пять, не меньше, поэтому привык проверять всё на практике. В общем, приступаем.
Предыдущие статьи цикла:
- Начинаем опыты с интерфейсом USB 3.0 через контроллер семейства FX3 фирмы Cypress
- Дорабатываем прошивку USB 3.0, используя анализатор SignalTap, встроенный в среду разработки Quartus
1 Теория о методах доступа к USB
1.1 Windows
Когда новое, доселе неизвестное системе USB-устройство впервые вставлено в ЭВМ, работающую под управлением Windows, оно отображается в диспетчере устройств с жёлтым знаком вопроса. Это связано с тем, что Windows обязательно нужен драйвер для работы с ним. Давайте я немного порассуждаю про эти драйверы, но не с научной точки зрения, а как инженер, раскрыв чисто практические аспекты, но несколько упростив теорию. Потому что мне не нужно, чтобы все уснули. Мне нужно, чтобы суть была понятна, так что ряд скучных деталей придётся опустить.
1.1.1 Драйверы, работающие на функциональном уровне
Что такое USB-устройство? Это набор конечных точек. Но прикладному программисту, если честно, эти точки не интересны. Давным-давно, ещё в прошлом тысячелетии, когда последовательные порты делались на микросхеме UART16550, под неё был сделан функциональный драйвер для Windows, и все прикладные программисты привыкли работать с абстракциями именно этого драйвера. И с этой привычкой трудно спорить. Представим на минутку, что с переходником USB-COM придётся работать в USB-шном стиле, на уровне конечных точек. Есть идеология CDC: две конечных точки туда-обратно, одна точка статуса в режиме прерываний и определённый набор команд, подаваемых через конечную точку EP0. Это всё описано в стандартах, относящихся к USB.
Всё? Нет, некоторым этого мало! Prolific сделала свой набор команд для точки EP0, не совместимый с CDC. А FTDI – свой. Он не совместим ни с CDC, ни с Prolific. Так что, если бы прикладной программист работал бы с переходниками USB-COM на уровне конечных точек, ему пришлось бы нелегко. К счастью, Prolific и FTDI предоставляют функциональные драйверы для своих чипов, а для CDC функциональный драйвер разработала сама Microsoft и прилагает его в составе Windows. Поэтому прикладной программист понятия не имеет, как работать с конкретным переходником (помню, мы целый NDA лет 15 назад с FTDI подписывали, чтобы получить от них руководство по их командам, причём я сразу же им послал информацию об ошибке в документе, так как пока работали бюрократы, я через дизассемблер всё сам уже успел изучить, так что сразу нашёл несовпадение их описания с моим). На прикладном уровне драйверы всех упомянутых производителей дают интерфейс такой же, как и при работе со старым добрым UART16550.
То же касается и USB-накопителей. Мало кто знает, что физически там две конечных точки. Почти никому не интересно, как там надо гонять пакеты, чтобы посылать команды и данные. Как разруливать ошибки, знает ещё меньше людей. Все работают через драйвер usbstor.sys, предоставляемый Microsoft, который обеспечивает работу точно так же, как и с дисками, подключёнными через локальную шину материнской платы.
Удобно? Однозначно! Но вот мы сделали своё устройство, не совместимое по логике работы ни с каким из стандартных. И что нам теперь, всенепременно писать для него персональный драйвер?Не обязательно. Если нас устраивает работа на прикладном уровне через конечные точки, то уже имеется целый ряд готовых драйверов, которые позволяют общаться с устройством через них. Некоторые из них мы сейчас и рассмотрим.
1.1.2 CyUSB
С этим драйвером я познакомился раньше других. Было это 12 лет назад. Вот с него и начну рассказ. Правда, скажу лишь вскользь. Фирма Cypress, выпуская замечательные контроллеры FX2LP, просто обязана была сделать драйвер, работающий на уровне конечных точек, чтобы облегчить жизнь своим клиентам. И она его сделала. Кому интересно – ищите по слову CyAPI. Это DLL-ка, предоставляющая ряд функций для прикладного программиста. Я как системщик старался обойтись без DLL, поэтому сделал себе библиотеку, работающую с драйвером на уровне IOCTL запросов.
Главный недостаток данной библиотеки заключается в её лицензионном соглашении. Её можно использовать только с контроллерами Cypress. А чтобы всё было убедительнее, начиная с некоторых версий, драйвер стал просто зависать, если он работает с контроллерами других производителей. По крайней мере, старые версии с AT90USB работали, а более свежие – нет. Поэтому я решил, что не буду пользоваться данным драйвером. Даже написал свой… Но вскоре обнаружился замечательный готовый вариант от Microsoft, и я перешёл на него.
1.1.3 WinUSB
Этот драйвер уходит своими корнями в инфраструктуру UMDF. Когда фирма Microsoft работала над возможностью запускать драйверы на пользовательском уровне защиты, они сделали специальный драйвер-прослойку WinUSB. Но через этот же драйвер можно работать и из обычных прикладных программ, а не только из UMDF-драйверов. Кому интересно – вбейте в поиск WinUSB API. Через эту функциональность можно делать то же самое, что и через CyUSB, но с контроллерами любых производителей.
Сам драйвер входит в состав Windows, поэтому в Win7 его можно было вообще ставить без каких-либо проблем с подписыванием. Можно было создать по инструкции от Microsoft или найти и скачать готовый inf файл, поменять в нём VID/PID на свои и установить. К сожалению, начиная с WIN8, обязательно надо подписывать не только сам драйвер, но и INF файл. Однако никто не мешает поправить VID/PID у устройства на тот, который будет найден. Вот у меня есть вот такой подписанный inf файл.
Посмотреть inf файл
; ; Android WinUsb driver installation. ; [Version] Signature = "$Windows NT$" Class = AndroidUsbDeviceClass ClassGuid = Provider = %ProviderName% DriverVer = 06/06/2017,2.0.0010.00003 CatalogFile.NTx86 = MT16_x86.cat CatalogFile.NTamd64 = MT16_x64.cat ; ; This section seems to be required for WinUsb driver installation. ; If this section is removed the installer will report an error ; "Required section not found in INF file". ; [ClassInstall32] Addreg = AndroidWinUsbClassReg [AndroidWinUsbClassReg] HKR. 0,%ClassName% HKR,,Icon,,"-26" [Manufacturer] %ProviderName% = Google, NTx86, NTamd64 [Google.NTx86] %CompositeAdbInterface1% = USB_Install, USB\VID_1234&PID_0001 %CompositeAdbInterface2% = USB_Install, USB\VID_1234&PID_0002 %CompositeAdbInterface3% = USB_Install, USB\VID_1234&PID_0003 %CompositeAdbInterface5% = USB_Install, USB\VID_1234&PID_0005 %OldBox% = USB_Install, USB\VID_4844&PID_8816 %HIDkey% = USB_Install, USB\VID_A1A2&PID_2001 [Google.NTamd64] %CompositeAdbInterface1% = USB_Install, USB\VID_1234&PID_0001 %CompositeAdbInterface2% = USB_Install, USB\VID_1234&PID_0002 %CompositeAdbInterface3% = USB_Install, USB\VID_1234&PID_0003 %CompositeAdbInterface5% = USB_Install, USB\VID_1234&PID_0005 %OldBox% = USB_Install, USB\VID_4844&PID_8816 %HIDkey% = USB_Install, USB\VID_A1A2&PID_2001 [USB_Install] Include = winusb.inf Needs = WINUSB.NT [USB_Install.Services] Include = winusb.inf AddService = WinUSB,0x00000002,WinUSB_ServiceInstall [WinUSB_ServiceInstall] DisplayName = %WinUSB_SvcDesc% ServiceType = 1 StartType = 3 ErrorControl = 1 ServiceBinary = %12%\WinUSB.sys [USB_Install.Wdf] KmdfService = WINUSB, WinUSB_Install [WinUSB_Install] KmdfLibraryVersion = 1.7 [USB_Install.HW] AddReg = Dev_AddReg [Dev_AddReg] HKR,,DeviceInterfaceGUIDs,0x10000,"" [USB_Install.CoInstallers] AddReg = CoInstallers_AddReg CopyFiles = CoInstallers_CopyFiles [CoInstallers_AddReg] HKR,,CoInstallers32,0x00010000,"WdfCoInstaller01009.dll,WdfCoInstaller","WinUSBCoInstaller2.dll" [CoInstallers_CopyFiles] WinUSBCoInstaller2.dll WdfCoInstaller01009.dll [DestinationDirs] CoInstallers_CopyFiles=11 [SourceDisksNames] 1 = %DISK_NAME%. \i386 2 = %DISK_NAME%. \amd64 [SourceDisksFiles.x86] WinUSBCoInstaller2.dll = 1 WdfCoInstaller01009.dll = 1 [SourceDisksFiles.amd64] WinUSBCoInstaller2.dll = 2 WdfCoInstaller01009.dll = 2 [Strings] ProviderName = "GM Software" CompositeAdbInterface1 = "MT16 Device" CompositeAdbInterface2 = "MT16 Ports 1-5" CompositeAdbInterface3 = "MT16 Ports 12-16" CompositeAdbInterface5 = "TBR Flasher" OldBox = "Old MT16 Box" HIDkey = "HID Dongle via WinUSB" WinUSB_SvcDesc = "MT16 COM Ports" DISK_NAME = "MT16 Driver Installation Directory" ClassName = "MT16 USB Devices"
Раньше таких inf файлов на просторах сети было много. Андроид-телефоны через них подключались. Сейчас надо искать по слову WinUSB.sys внутри. Ну, или «ServiceBinary = %12%\WinUSB.sys».
Я поправил «Прошивку» для FX3 вот так:
То же самое текстом.
const uint8_t CyFxUSB30DeviceDscr[] __attribute__ ((aligned (32))) = < 0x12, /* Descriptor size */ CY_U3P_USB_DEVICE_DESCR, /* Device descriptor type */ 0x00,0x03, /* USB 3.0 */ 0x00, /* Device class */ 0x00, /* Device sub-class */ 0x00, /* Device protocol */ 0x09, /* Maxpacket size for EP0 : 2^9 */ #ifdef CY_VID_PID 0xB4,0x04, /* Vendor ID */ 0xF1,0x00, /* Product ID */ #else 0x34,0x12, /* Vendor ID */ 0x05,0x00, /* Product ID */ #endif …
И теперь могу собирать варианты хоть под CyUSB, хоть под WinUSB с привязкой к имеющемуся у меня inf файлу. А так — можно перевести ОС в режим, не требующий подписывания драйверов, хоть это и не очень удобно.
1.1.4 Библиотека libusb
Вариант с WinUSB отличный, но не кроссплатформенный. Насколько мне известно, под Linux нет точно такого же API, который предоставляет Microsoft для Windows. Кроссплатформенный вариант – это использование библиотеки libusb. Причём под Windows эта библиотека по умолчанию опирается на всё тот же драйвер WinUSB. Нашли драйвер, накатили его на устройство. Скачали библиотеку, начали через неё работать с этим драйвером. Надо будет – через неё же можно будет работать и под Linux. Замечательно? Да. Особенно если мы разработали полностью своё устройство. Но, увы, я просто обязан указать недостаток данного метода для общего случая.
Когда мы устанавливаем на устройство драйвер WinUSB, мы убираем оригинальный драйвер. В рамках данного блока статей мы теряем возможность общаться с нашим устройством при помощи утилиты ControlCenter. Ну, и я не упоминал в статьях про утилиту Streamer, позволяющую измерять скорость устройства… В общем, ею мы тоже не сможем пользоваться, если заменим штатный драйвер на WinUSB.
В рамках другой задачи мне надо было экспериментировать с аудиоустройствами из своего приложения. При этом я не хотел постигать все тонкости работы с ними. Я хотел только некоторые команды подавать, а чтобы всё остальное за меня делала сама операционка. Но если бы я посадил устройства на WinUSB, ОС бы потеряла контроль над ними и не могла бы оказывать мне всемерное содействие.
Можно ли работать из прикладной программы с устройствами, не пересаживая их на специальный драйвер? В принципе, да (правда, это очень аккуратное утверждение). Давайте я покажу этот метод… Правда, в конце — сильно раскритикую его.
1.1.5 Драйвер UsbDk
Библиотека libusb существует в двух версиях. Версия 0.1 и версия 1.0. Обе версии в настоящее время развиваются, создавая некоторую путаницу. И вот версия 1.0 может работать не только через драйвер WinUSB, но и через драйвер UsbDk. Последний является фильтр-драйвером. Что такое фильтр-драйверы? Вспоминаем детство, сказку о царе Салтане:
Собственно, фильтр-драйвер встаёт на пути IRP-пакетов от прикладной программы к основному драйверу и обратно. IRP — это гонцы, которые бегают туда-сюда. А фильтр-драйвер может их пропустить, не изменяя, а может подменить их содержимое. Он придуман для исправления ошибок, чтобы не менять основной драйвер, а просто немножко подправить пакеты, дабы те не вызывали проблем. Их можно править на прямом и на обратном пути. Но в целом, никто не мешает через этот фильтр-драйвер запустить в основной драйвер запросы от приложения, которое общается именно с фильтром. И UsbDk этим и занимается.
Очень схематично, опустив ряд неважных подробностей, это можно показать так:
Вот тут мы видим, что фильтр-драйвер UsbDK подсел на пути пакетов к нашему устройству (на самом деле, он подсел на пути ко всем USB-устройствам, так как прицепился к драйверу класса USB):
Если при открытии библиотеки libusb 1.0 сказать:
libusb_init(&m_ctx); libusb_set_option(m_ctx, LIBUSB_OPTION_USE_USBDK);
то она будет использовать в качестве основы не WinUSB, а UsbDk. Ура? Не совсем. Приведу минимум две проблемы, создаваемые при использовании данного пути.
Первая проблема организационная. Если мы запустили программу, поработали, вышли, то всё будет хорошо. Но вот мы запустили программу, начали работать, а потом почему-то прервались. Да хоть у меня стояла точка останова, исполнение прервалось, я осмотрел переменные, увидел, что программа работает неверно, и завершил её. Могу я так сделать? Дело-то житейское при разработке программы. Или просто зациклилась она. В общем, мы её прервали. Снова запускаем – устройство уже не открывается. Смотрим код ошибки – он очень интересный.
Driver file operation error. DeviceIoControl failed (Cannot create a file when that file already exists. Error code = 183) Cannot Open USB Device
И всё. Выдёргивать-вставлять USB-кабель – бесполезно. Только полная перезагрузка Windows спасёт Отца Русской Демократии. Когда перезапускаешься третий-четвёртый раз за час – это начинает несколько раздражать. Поиск в сети не дал никаких результатов. Попытка бегло осмотреть исходники UsbDk – тоже, а на детальные разбирательства нет времени. Может, кто в комментариях чего подскажет…
Но на самом деле, эта проблема раздражает, но не является фатальной. Вторая проблема более серьёзная. Вот я поставил VirtualBox. Я просто запустил виртуальную машину и хочу подключить к ней, скажем, бластер. И что получаю?
Аналогично – любое другое устройство.
Поиск по сети даёт много вариантов типа: «У меня всё заработало после того, как я потёр заячьей лапкой по бубну из кожи тушканчика, спрыснутому кровью семидесятидвухлетней девственницы, полученной…» … Что там дальше в рецепте — сейчас уже не помню… Тем более, мне он не помог… Более осмысленные рекомендации требуют сносить фильтр-драйверы USB, пока не полегчает. Проблема уходит, когда сносишь именно UsbDK. Ну, значится, так тому и быть. Хотя для экспериментов с аудио, других приемлемых вариантов я не нашёл. Так что драйвер я снёс, но дистрибутив – оставил. Пригодится. Именно поэтому описываю эту методику. Ну, и вдруг кто в комментариях подскажет, как обходить эти две проблемы. Тогда станет совсем здорово.
Итого, сегодня мы будем работать через библиотеку libusb, посадив устройство на драйвер WinUSB. Да, мы потеряем возможность работать с устройством через стандартные приложения от Cypress. Зато всё будет стабильно и хорошо.
1.2 Linux
1.2.1 Драйвер
Я уже много раз писал, что не очень сильно разбираюсь в уходе за пингвинами, поэтому просто перескажу слова своего начальника, опрошенного специально для написания данной статьи.
Некоторые устройства уже поддержаны в Линуксе по классу, либо по VID/PID. Вот, скажем, я подключил макетную плату ICE40 с ПЛИС Latice и подал сначала команду lsusb, чтобы увидеть USB устройства, а затем – уже полюбившуюся нам по прошлым статьям команду:
ls –l /dev/serial/by-path, чтобы увидеть, что мост фирмы FTDI сам прикинулся двумя последовательными портами.С такими устройствами, если ничего не предпринимать, можно работать только на функциональном уровне. Однако, если функциональный драйвер не подключился, как уверяет начальник, в отличие от Windows такие устройства не станут неизвестными (а потому недоступными). Напротив, с ними можно сразу и без какой-либо подготовки работать через библиотеку libusb. А разработанное нами устройство относится к таковым. Поэтому никакой подготовки для начала работы не требуется. Надеюсь, начальник меня не обманул.
Правда, есть чисто организационная подготовка, которую мы вынесем в собственный раздел.
1.2.2 Отключение требований прав администратора при работе с USB-устройствами
Главная особенность USB-устройств в Linux состоит в том, что по умолчанию для доступа к ним надо обладать правами администратора. То есть, для сборки «прошивки» для ПЛИС ICE40 (к теме статьи они не относятся, но по проекту я сейчас их осваиваю, причём под Linux, так что скриншоты готовить проще для них) мне достаточно набрать make, а вот если для «прошивки» я наберу make prog, то получу такое сообщение:
Не хватает прав. Надо набирать sudo make prog.
Чтобы понизить требуемые права, надо прописать правила. А чтобы быстро выяснить, как их прописать, я обычно даю такой запрос Гуглю:
Usb blaster Linux
Ссылок будет много, все они разной степени шаманства. Вот более-менее подробная ссылка:
Using USB Blaster / USB Blaster II under Linux | Documentation | RocketBoards.orgЧто сразу бросается в глаза: имена файлов с правилами для Debian и для Ubuntu разные.
/etc/udev/rules.d/ 92 -usbblaster.rules и /etc/udev/rules.d/ 51 -usbblaster.rules, соответственно.Всё тот же начальник, а по совместительству – любитель Линукса, объяснил, что если в нескольких файлах есть правила для одного и того же устройства, число задаёт приоритет разбора файлов. Собственно, документ также говорит, что число 92 базируется на том, что в системе имеется файл / lib /udev/rules.d/ 91 -permissions.rules.
Вообще, мне стало интересно, и я вбил в Гугля строку поиска
/etc/udev/rules.d/Он нашёл мне много статей про udev. Некоторые более теоретические. Некоторые слишком практические. Пересказывать их не вижу смысла. При желании вы можете погуглить сами. Дам только ссылку на статью, которая мне кажется хорошо сбалансированной по теории и практике:
Igorka: Знакомство с udev в ubuntuИтак. Иду в каталог /etc/udev/rules.d. Вижу файл 70-snap.snapd.rules, в котором есть правило, относящееся ко всем FTDI чипам:
FTDI-based serial adapters:
# FTDI does USB to serial converter ICs; and it's very likely that they'll # never do modems themselves, so it should be safe to add a rule only based # on the vendor Id. ATTRS=="0403", ENV="1"
Не понимая до конца, что творю, запускаю не просто mc, а sudo mc и в его редакторе создаю файл /etc/udev/rules.d /71-ice40.rules со следующим содержимым:
#FTDI Programmer for latice SUBSYSTEM=="usb", ATTRS=="0403", ATTRS=="6010", MODE="0666"
Закрываю терминал с админскими правами, открываю новый, с правами обычными. Отключаю-включаю устройство, и… Вуаля! Оно уже доступно без прав администратора!
Поэтому можете просто повторить мои шаманства, можете – почитать теорию по ссылкам, после чего у вас всё получится уже с пониманием физики процесса. А так – в рамках данной статьи я буду работать только через Windows, но через кроссплатформенную библиотеку libusb версии 1.0 (не путать с 0.1). Поэтому в Линуксе прописывать правила для устройства FX3 не буду.
2 Практика
Ох, и огромный сегодня получился теоретический раздел! Но наконец, мы владеем достаточным количеством знаний, чтобы приступить к опытам. Напомню, я буду работать в ОС Windows, пользуясь библиотекой libusb 1.0, опираясь на драйвер WinUSB. Я сейчас осваиваю работу с кроссплатформенной библиотекой Qt, поэтому буду разрабатывать код под неё.
2.1 Добавляем libusb в проект
Я скачал библиотеку libusb и распаковал её в каталог своего проекта. Чтобы подключить её к проекту, в файл *.pro пришлось добавить блок:
win32: < LIBS += D:/Work/AS/2020/teensy/Qt/UsbSpeedTest/LibUSB/MinGW64/static/libusb-1.0.a >
Кто сказал, что абсолютные пути – зло? Золотые слова! Я тоже так считаю. Но я уйму времени убил на эксперименты с относительными путями в этом месте. Ничего не получалось. Поэтому пока сделал так. Если кто-то знает тайну, как в проект добавляются относительные пути, да ещё так, чтобы работали, буду премного благодарен за разъяснения. А пока – отмечаю, что такой вариант работает, но однозначно является злом, так как он работает только у меня и только, пока я не соберусь перенести проект куда-то. Собственно, всё. Библиотека добавлена и готова к работе.
2.2 Класс для доступа к библиотеке
Обычно примеры для статей я пишу в слитном стиле. Но сегодняшний код получился несколько запутанным, поэтому пришлось вынести работу с платой FX3 в примитивный класс. Вот его интерфейсная часть:
#ifndef CUSBTESTER_H #define CUSBTESTER_H #include "./LibUSB/libusb.h" class CUsbTester < public: CUsbTester(); ~CUsbTester(); virtual bool ConnectToDevice(); virtual void DisconnectFromDevice(); libusb_device_handle* m_hUsb; protected: libusb_context * m_ctx = NULL; >; #endif // CUSBTESTER_H
По функциям мы ещё пройдёмся, а пока я отмечу то, что у класса есть переменная-член, хранящая указатель на контекст, который будет нужен для вызова некоторых функций тонкой настройки библиотеки, и манипулятор (в простонародии — хэндл) устройства, необходимый для обращения к устройству.
В конструкторе происходит инициализация и тонкая настройка библиотеки:
//#define CY_VID_PID CUsbTester::CUsbTester()
Как видим, возможна работа библиотеки через драйвер CyUSB и фильтр UsbDk, но сейчас она отключена. И мы включаем расширенную диагностику работы библиотеки. Все сообщения о проблемах будут сыпаться в окно отладочного вывода. Помните, я показывал сообщение об ошибке при работе UsbDk? Без этой опции никто бы ничего не узнал. Ошибка и ошибка.
Деструктор, соответственно, всё деинициализирует. Класс тестовый, заботиться о наличии дополнительных пользователей библиотекой нет смысла. Так что просто деинициализируем и всё.
CUsbTester::~CUsbTester()
Подключение к устройству интересно лишь тем, что может работать по разным парам VID/PID. Как я уже говорил, я могу собирать «прошивку» под штатные VID/PID от Cypress, если идёт работа через UsbDk, и под те, на которые у меня нашёлся inf-файл, устанавливающий драйвер WinUSB. В остальном, ничем не примечательные типовые вызовы функции библиотеки libusb:
bool CUsbTester::ConnectToDevice() < #ifdef CY_VID_PID m_hUsb = libusb_open_device_with_vid_pid(m_ctx,0x4b4,0xf1); #else m_hUsb = libusb_open_device_with_vid_pid(m_ctx,0x1234,0x0005); #endif if (m_hUsb == 0) < qDebug()int res = libusb_claim_interface(m_hUsb,0); if (res != 0) < qDebug()return true; >
Ну, и отключаемся от устройства тоже типовым методом:
void CUsbTester::DisconnectFromDevice() < if (m_hUsb != 0) < libusb_release_interface(m_hUsb,0); libusb_close(m_hUsb); m_hUsb = 0; >>
Собственно, всё. Функцию чтения из устройства я буду вызывать напрямую. Это противоречит принципам проектирования классов, но для опытов сойдёт. Я просто заметил, что код инициализации сильно разросся и отделил его от основного кода, вынеся в класс. А чтение — оно в одну строку выполняется, его отделять было не нужно.
2.3 Тестовая программа
Программа состоит из функции main() и тестовой функции.
Тестовая функция делится на две части. Первая часть измеряет скорость передачи данных. Вторая — проверяет то, что данные из счётчика приходят с инкрементом. При обнаружении разрыва – сведения об этом выдаются в консоль отладочного вывода. Собственно, вот текст функции:
bool TestStep(CUsbTester& tester,uint16_t* pData, const int bytesCnt) < bool bResult = true; qDebug() quint64 after = timer.elapsed(); qDebug() prevData = pData[i]; > return bResult; >
В будущем я планирую вызывать эту функцию многократно, но пока — функция main() вызывает её один раз:
int main(int argc, char *argv[]) < QCoreApplication a(argc, argv); CUsbTester tester; if (tester.ConnectToDevice()) < QByteArray ar1; ar1.resize(128*1024*1024); for (int i=0;i<1;i++) < TestStep (tester,(uint16_t*)ar1.constData(),ar1.size()); >tester.DisconnectFromDevice(); > return a.exec(); >
Собственно, и вся программа.
2.4 Результат тестового прогона
2.4.1 Скорость
При тестовом прогоне мы видим, что скорость близка к требуемой. Напомню, что источник гонит 16-битные данные на скорости 60 МГц, так что нам требуется поток 120 миллионов байт в секунду. Когда на временных диаграммах наблюдался огромный дефицит колбасы, скорость была всего 30 Мегабайт в секунду. Даже меньше, чем практически достижимая скорость на шине USB 2.0. Так что текущие результаты вполне приемлемые.
Правда, чтобы окончательно успокоиться, я решил немного поэкспериментировать со скоростью. Чаще всего она была равна 119 0XX XXX байт в секунду. Изредка – 119 4XX XXX. Ну, и совсем редко – промежуточные значения, похожие на указанные выше. Сначала я решил, что это могут быть ошибки округления. У нас идёт округление показаний таймера, и возникают округления при делении. Тогда я переписал вычисление скорости так (перешёл на наносекунды и стал умножать перед делением, чтобы минимизировать ошибку округления):
QElapsedTimer timer; int actualLength; timer.start(); int res = libusb_bulk_transfer(tester.m_hUsb,0x81,(uint8_t*)pData,bytesCnt,&actualLength,10000); quint64 after = timer.nsecsElapsed(); if (res != 0) < qDebug() qDebug()
Результат ничуть не изменился. Следующее подозрение было, что источник имеет некоторую ошибку кварцевого резонатора и шлёт данные чуть медленнее, чем надо. Но другая плата даёт точно такие же показания! Значит, дело не в экземпляре. Мало того, осциллограф (правда, весьма дешёвый китайский) говорит, что тактовая частота нисколько не занижена, даже чуть завышена.
Тогда я полез в исходники библиотеки libusb и просто-таки утонул в коде, который исполняется при ожидании конца передачи данных. Там такая цепочка функций – просто закачаешься! И много, где может возникать задержка. Но давайте прикинем, какова задержка.
120 мегабайт в секунду… Округлим до ста. Это 1 мегабайт в 10 миллисекунд. А у нас просадка как раз на 1 мегабайт. Неужели начало и конец прокачки съедают так много времени? Как бы проверить хотя бы начерно? Я решил переписать на пробу код под прямой вызов WinUSB API. Полностью объяснять я его не стану, там устройство открывается хитро, через SetupDi API. Я просто воспользовался готовыми своими старыми классами, поэтому всё было сделано под Visual Studio. Но вместо страшных километровых текстов ожидания завершения библиотеки WinUSB, моя функция чтения выглядит вполне канонически:
int CWinUSBConnector::ReadViaBulk (void* pData,int count,int timeOut) < DWORD dwRead; ResetEvent (m_hEvRead); if ((!WinUsb_ReadPipe (m_hUsbDrive,m_nReadEP,(BYTE*)pData,count,&dwRead,&m_ovRead)) && (GetLastError() != ERROR_IO_PENDING)) < return -1; >if (WaitForSingleObject(m_hEvRead,timeOut)!=WAIT_OBJECT_0) < WinUsb_AbortPipe (m_hUsbDrive,m_nReadEP); return -2; >else < WinUsb_GetOverlappedResult (m_hUsbDrive,&m_ovRead,&dwRead,FALSE); >return dwRead; >
А тест теперь выглядит так:
#include #include #include "./USB/WinUSBConnector.h" CWinUSBConnector m_connector; int main() < std::cout LARGE_INTEGER Frequency; QueryPerformanceFrequency(&Frequency); static const UINT64 cnt = 128 * 1024 * 1024; BYTE* pData = new BYTE [cnt]; LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds; QueryPerformanceCounter(&StartingTime); UINT64 realSize = m_connector.ReadViaBulk(pData, (int)cnt, 10000); QueryPerformanceCounter(&EndingTime); if (realSize != cnt) < std::cerr ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart; ElapsedMicroseconds.QuadPart *= 1000000; ElapsedMicroseconds.QuadPart /= Frequency.QuadPart; UINT64 bytesPerSeconds = (cnt*1000000LL) / ElapsedMicroseconds.QuadPart; std::cout
Теперь скорость стабильно находится в районе 119 2XX XXX байт в секунду. Вот какой красивый результат я подловил для красного словца:
А вот результат нескольких прогонов подряд:
В общем, никто не запрещает просадке возникать и на входе-выходе в функцию чтения. Если разрывов в показаниях счётчика не будет, то и ладно.
2.4.2 Пропуски в показаниях счётчика
Но на тему разрывов у нас тоже имеется пара строк в выводе основной тестовой программы:
Имеется два нарушения последовательности счёта. Неужели мы нарвались на выпадение данных? К счастью, всё в порядке. Множественные прогоны говорят, что проблемы всегда в одном и том же месте. И мы с таким уже сталкивались в одной из старых статей. У нас есть две точки буферизации данных: буфер контроллера и FIFO в ПЛИС. Готовы ли мы принимать данные или нет, они с выхода счётчика будут заливаться в буфер FX3. Когда тот переполнится, заливка остановится. Кроме буфера FX3, есть ещё FIFO в ПЛИС. Вот у нас и имеется две ёмкости, которые заполнились, но счётчик продолжил работу. При чтении мы увидели разрывы в счёте.
Соответственно, мы наблюдаем явление переходных процессов. При реальной работе надо будет настроить источник так, чтобы он не заполнял буфер данными, пока мы не готовы их принимать (собственно, в статье про голову USB-Анализатора мы уже делали такую функцию через добавление бита «Go»), а пока – просто будем игнорировать ошибки в этой области. Считаем, что это – не баги, а фичи. Меняем проверку разрывов на такую:
То же самое текстом.
int from = 0xc001; uint16_t prevData = pData[from]; for (int i=from+1;i prevData = pData[i]; >
Делаем массовый прогон для такого варианта… И тут я понял, кто даёт задержку… Отладочный вывод. Вот так всё выглядит:
Масса вспомогательных текстов, выдаваемых библиотекой. Ну и отлично. Закомментируем в конструкторе класса, обслуживающего libusb, строку:
// libusb_set_option(m_ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
Получаем красоту, ничем не отличимую от того, что мы получали при прямом вызове WinUSB API (жаль только, что не идеальный результат):
Но главное – нет сообщений про разрывы в показаниях счётчика (известные точки разрывов мы игнорируем).
А что там нам про таймауты промежуточные говорили? Попробуем читать не 128, а 32 мегабайта! Получаем уже скорость вплоть до 119 8XX XXX мегабайт в секунду!
В общем, всё хорошо… Кроме одного. Я нашёл такой нестандартный вариант теста, при котором штатная «прошивка» FX3 подвисает. Но статья получилась такой большой, что как это найти, а главное – как исправить, я расскажу в следующий раз.
3 Заключение
Мы познакомились с теоретическими особенностями работы с USB устройствами в ОС Windows и Linux, а также получили практический навык работы с кроссплатформенной библиотекой libusb. Начерно, разработанное USB 3.0 устройство на базе контроллера FX обеспечивает требуемый поток данных для приёма данных из микросхемы ULPI без промежуточного их сохранения в SDRAM. В потоке не выявлено разрывов, то есть, протокол передачи с виду устойчивый. Автор утверждает, что выявил принципиальную проблему в системе, но выносит её обсуждение в следующую статью.
- Системное программирование
- FPGA
- Программирование микроконтроллеров
- Компьютерное железо