08.10.2011 Исходники модуля ядра для работы с платой USB выложены в SVN
Данная статья описывает модуль ядра Linux, предназначенный для передачи данных из радиочастотного блока через шину High speed USB в программный приёмник SR31
|
Зачем нужен модуль ядра?
В Linux есть два принципиально разных способа для работы с шиной USB.
libusb
Первый способ - работа через библиотеку libusb. В этом случае программа пользователя непосредственно обращается с помощью данной библиотеки к USB (работа в userspace). Достоинством данного метода является переносимость - libusb реализована на разных платформах, в т.ч. и на Windows.
Первоначально предполагалось реализовывать доступ программного приёмника к USB именно этим способом. Однако реализация показала, что библиотека libusb не очень хорошо подходит для работы в реальном времени. Периодически в работе данной библиотеки происходят существенные задержки (до 500 мс). Для работы с такими задержками нужен очень большой буфер данных в плате ввода данных, что сделать было нереально. В результате от работы по libusb отказались.
Модуль ядра
Второй способ - реализовать интерфейс в виде модуля ядра.
Ядро системы Linux модульное, разные функции могут быть реализованы в виде отдельных программ, модулей. Модули можно "на ходу" подключать и отключать от ядра.
Был реализован модуль ядра, названный FrontEnd.ko, позволяющий работать с нашей платой ввода данных. Модуль ядра выполняет следующие действия:
- регистрируется в ядре Linux;
- отслеживает подключение и отключение устройства;
- передаёт принимаемые из устройства данные.
Принцип действия модуля очень простой. У платы есть оконечная точка, по которой принимаются в компьютер данные. Всё, что плата передаёт по этой оконечной точке, модуль ядра передаёт в файл устройства /dev/FrontEnd<X>, где <X> - номер файла устройства.
Пользовательская программа просто открывает файл /dev/FrontEnd<X> для чтения, как обычный файл, и читает оттуда данные, как из обычного файла. Больше ничего не нужно!!!
В результате использовать плату usb может не только специально написанный для этого программный приёмник, но и любая программа, работающая с файлами. Например, можно сохранить выборку данных из платы USB с помощью стандартной программы dd:
dd if=/dev/FrontEnd0 of=/tmp/y.bin bs=1024 count=1024
Данная команда сохраняет 1 Мб данных из платы USB в файл /tmp/y.bin. Впоследствии данные из этого файла могут быть открыты, скажем, в Matlab. Хотя, Matlab может сразу читать данные из /dev/FrontEnd0.
Исследование работы в реальном времени показало, что использование данного модуля ядра позволяет передавать данные без разрывов в течении продолжительных периодов времени. Записанные на сервер выборки данных с файла получены именно таким методом.
Где взять модуль?
Модуль ядра выложен в SVN хранилище программного приёмника SR31, в подкаталоге kernel. Как через SVN получить исходники программного приёмника, описано здесь.
Исходники можно увидеть через WebSVN: SR31/trunk/kernel.
Работа с модулем
Внимание! Шаги 2,3,7 выполняются из-под root!
1. Сначала нужно скомпилировать модуль ядра. Для этого необходимо компилятор gcc и исходники ядра Linux. Если всё это есть, то в каталоге с исходниками модуля (SR31/work/kernel) нужно дать команду
make
и модуль будет собран.
2. Нужно настроить систему udev. Система udev в Linux создаёт файлы устройств в каталоге /dev и даёт им имена. Для настройки udev нужно взять их каталога исходников файл 96-FrontEnd.rules, поместить его в каталог /etc/udev/rules.d/. Название данного каталога может зависеть от дистрибутива Linux!
Затем нужно дать команду
udevadm control --reload_rules
3. После этого нужно загрузить модуль ядра:
cd SR31/bin/kernel insmod FrontEnd.ko
4. Далее нужно подключить плату USB.
5. После этого должен появиться файл /dev/FrontEnd0 (если воткнуть вторую плату, будет /dev/FrontEnd1 и т.д.).
6. Далее можно запускать программный приёмник. Работоспособность платы и модуля можно проверить так:
cat /dev/FrontEnd0
При этом на экран будет выдаваться куча мусора - данные, получаемые из платы.
Решение проблем
Модуль ядра не компилируется
Должен комплироваться. Проверьте наличие компилятора:
gcc --version
Проверьте наличие исходников ядра:
ls /usr/src/linux
Дальше - нужно читать сообщения об ошибках.
Модуль ядра не загружается
Пишет что-нибудь вроде UNKNOWN SYMBOLS.
В этом случае, скорее всего, ядро Linux, которое работает в данный момент в системе, не соответствует исходникам из /usr/src/linux
Можно проверить, например, так:
uname -r ls -d /usr/src/linux
Первая команда выдаст версию работающего ядра, вторая - реальное название каталога с исходниками (оно содержит версию). Версии должны совпадать.
Большинство дистрибутивов изначально содержат заранее скомпилированное ядро без исходников. Исходники ядра необходимы для сборки модуля, но они должны соответствовать ядру. Поэтому придётся собрать исходники ядра, запустить ядро и компилировать для него модуль. Конфигурация ядра задаётся файлом ".config", находящимся в каталоге с исходниками ядра (/usr/src/linux). Желательно раздобыть файл ".config", соответсвующий текущей системе и узнать точную версию ядра. Обычно для определённой версии любого дистрибутива можно скачать уже сконфигурированные исходники ядра, тогда всё будет очень просто.
Ничего страшного!!! Пересборка ядра под Linux - дело вполне рядовое. Только запускать новое ядро нужно с осторожностью, чтобы не нарушить загрузку Linux. По сборке ядра в сети есть множество руководств.
Модуль загрузился, но файл устройства не появляется
То есть после подключения платы USB не появился файл /dev/FrontEnd0. Причины тут могут быть разные, но самая вероятная - неправильная настройка udev.
Сначала нужно проверить, загрузился ли модуль. Сделать это можно так:
dmesg | grep FrontEnd
dmesg - команда, выводящая сообщения ядра. Команда "grep FrontEnd" находит среди них строки, содержащие название модуля FrontEnd. При запуске модуль должен выдать сообщение:
usbcore: registered new interface driver FrontEnd
>>>>>>>>>>>>>>> USB4 driver registered
Это означает, что модуль загружен верно. Если таких сообщений нет --- надо разбираться. Список загруженных модулей можно посмотреть командой:
lsmod
Среди них должен быть FrontEnd. Если нет - его нужно загрузить командой insmod (описано выше). Если не грузится - разбираться.
Далее нужно проверить, подключилась ли плата. Для просмотра устройств USB можно либо воспользоваться командой
lsusb
Либо запустить программу usbview. В данной программе можно также посмотреть, управляет ли платой ввода данных наш драйвер, там это написано.
В любом случае, нужно найти устройство с VID:PID=0x0471:0x0881 (Номера указаны для старой платы USB на чипе Philips ISP1581, в новой плате могут отличаться). Если оно есть, значит всё нормально.
Далее нужно проверить работу udev. Можно сделать так. Запустить команду:
udevmonitor
Эта команда выдаёт на экран события в udev. После этого нужно вставить плату USB (выдернуть и вставить) и посмотреть сообщения. Если udev не реагирует - это не правильно. Тогда надо разбираться с правилами udev (/etc/udev/rules.d/96-FrontEnd.rules) и перезапустить udev (команда "udevadm control --reload_rules).
Предупреждение
Данное описание сделано по памяти без проверки, т.к. под рукой не было платы ввода данных USB. Когда она появится, статью надо перепроверить - часть команд, возможно, неверная.
Если что, обращайтесь, поможем.
[ Хронологический вид ]Комментарии
Войдите, чтобы комментировать.