Статьи

USB CDC с малиновым пи

Для моего проекта домашней автоматизации с openHAB я хочу подключить платы FRDM ( Freedom ) Freescale (теперь NXP), чтобы они могли заботиться об аспектах реального времени и выступать в качестве шлюзов для других моих систем. Одним из способов является использование USB CDC (Serial over USB) в качестве канала связи. Преимущество USB в том, что он питает плату, плюс я могу подключить несколько устройств: до четырех на Raspberry Pi 2 и даже больше с помощью USB-концентратора. В стандартной конфигурации с USB WiFi и USB HID (мышь плюс клавиатура) я все еще могу прикрепить две платы Fesomcale Freescale (ahem, NXP) к Raspberry Pi:

FRDM-K22F и FRDM-K64F присоединены к Raspberry Pi 2

Контур

В этой статье описывается, как использовать Raspberry Pi с устройствами, подключенными к нему с помощью USB CDC. USB CDC — это класс устройств, который реализует протокол «последовательный через USB». Я использую USB CDC (см. « Учебник: USB CDC с платой свободы KL25Z ») во многих моих проектах, так что это элегантный способ связи между Raspberry Pi и встроенным микроконтроллером.

Где мой порт USB?

После подключения устройства USB CDC к Raspberry первая проблема заключается в том, чтобы узнать, какое устройство оно использует. Чтобы увидеть, какие USB-устройства подключены, я могу использовать команду lsusb :

lsusb

который показывает что-то такое:

pi@raspberrypi ~ $ lsusb
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 7392:7811 Edimax Technology Co., Ltd EW-7811Un 802.11n Wireless Adapter [Realtek RTL8188CUS]
Bus 001 Device 008: ID 1366:0105 SEGGER
Bus 001 Device 005: ID 046d:c52b Logitech, Inc. Unifying Receiver

С участием

Bus 001 Device 008: ID 1366:0105 SEGGER

Он показывает Segger OpenSDA, в котором реализован комбинированный USB CDC.

Если подключить USB-CDC Freescale (см. « USB-CDC с помощью FRDM-K64F, наконец-то! »), То оно будет отображаться как

Bus 001 Device 007: ID 2504:0300

Строка поставщика пуста, потому что я использую «общие» VID и PID, не зарегистрированные в консорциуме USB. См. Http://ubuntuforums.org/showthread.php?t=2234649.

Где 2504 — идентификатор поставщика (VID), а 0300 — идентификатор продукта (PID), сообщаемый устройством USB. Это значения, которые я указал в реализации устройства USB:

Конфигурация USB CDC

Так какое устройство Linux оно использует?

  1. Подключите USB-кабель
  2. Используйте команду dmesg

Команда dmesg выводит информацию отладки / журнала ядра:

dmesg

Я должен увидеть что-то подобное для моей реализации USB CDC на плате FRDM:

[23621.397305] usb 1-1.3: New USB device found, idVendor=2504, idProduct=0300
[23621.397337] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[23621.397354] usb 1-1.3: Product: FSL CDC DEVICE
[23621.397371] usb 1-1.3: Manufacturer: FREESCALE INC.
[23621.398717] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device

Или для Segger USB CDC (OpenSDA):

[  226.413679] usb 1-1.3: new full-speed USB device number 8 using dwc_otg
[  226.519865] usb 1-1.3: New USB device found, idVendor=1366, idProduct=1015
[  226.519890] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  226.519908] usb 1-1.3: Product: J-Link
[  226.519924] usb 1-1.3: Manufacturer: SEGGER
[  226.519940] usb 1-1.3: SerialNumber: 000000123456
[  226.524041] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device
[  226.527545] usb-storage 1-1.3:1.3: USB Mass Storage device detected
[  226.527989] scsi host0: usb-storage 1-1.3:1.3
[  227.525152] scsi 0:0:0:0: Direct-Access     SEGGER   MSD Volume       1.00 PQ: 0 ANSI: 4
[  227.527831] sd 0:0:0:0: [sda] 21829 512-byte logical blocks: (11.1 MB/10.6 MiB)
[  227.528693] sd 0:0:0:0: [sda] Write Protect is off
[  227.528721] sd 0:0:0:0: [sda] Mode Sense: 0b 00 00 08
[  227.529304] sd 0:0:0:0: [sda] No Caching mode page found
[  227.529327] sd 0:0:0:0: [sda] Assuming drive cache: write through
[  227.551467]  sda:
[  227.555561] sd 0:0:0:0: [sda] Attached SCSI removable disk
[  227.562302] sd 0:0:0:0: Attached scsi generic sg0 type 0
[  237.448489] usb 1-1.3: USB disconnect, device number 8
[  237.533960] FAT-fs (sda): unable to read boot sector to mark fs as dirty
[  245.623749] usb 1-1.3: new full-speed USB device number 9 using dwc_otg
[  245.729928] usb 1-1.3: New USB device found, idVendor=1366, idProduct=0105
[  245.729954] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  245.729971] usb 1-1.3: Product: J-Link
[  245.729988] usb 1-1.3: Manufacturer: SEGGER
[  245.730003] usb 1-1.3: SerialNumber: 000621000000
[  245.732360] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device

Поскольку OpenSDA Segger J-Link представляет собой композитное (несколько) USB-устройство, оно показывает несколько устройств: MSD (запоминающее устройство большой емкости), J-Link и USB CDC (ACM). Опять же, он использует ttyACMx в качестве устройства.

Это говорит мне о том, что устройство было распознано и обрабатывается драйвером USB CDC ttyACM0.

: idea: См. https://www.rfc1149.net/blog/2013/03/05/what-is-the-difference-between-devttyusbx-and-devttyacmx/ о разнице между ACMx и USBx.

Команда udevadm показывает мне детали для устройства:

udevadm info -a -n /dev/ttyACM0

Опция ‘-a’ печатает всю информацию в цепочке устройств, а опция ‘-n’ используется для указания устройства (/ dev / ttyACM0) здесь:

сведения об устройстве, и он показывает мои данные устройства USB CDC:

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3':
    KERNELS=="1-1.3"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{devpath}=="1.3"
    ATTRS{idVendor}=="2504"
    ATTRS{speed}=="12"
    ATTRS{bNumInterfaces}==" 2"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="16"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="9"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}=="100mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="c0"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="0"
    ATTRS{bcdDevice}=="0002"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="13"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="FREESCALE INC.              "
    ATTRS{removable}=="removable"
    ATTRS{idProduct}=="0300"
    ATTRS{bDeviceClass}=="02"
    ATTRS{product}=="FSL CDC DEVICE"

Какое устройство / порт (/ dev / ttyACM0, / dev / ttyACM1,…) зависит от порядка их подключения. Ниже приведен пример подключения Segger OpenSDA J-Link и USB CDC, где он использует ttyACM0 для Segger USB CDC и ttyACM1 для родного USB CDC:

[ 3753.941466] usb 1-1.3: Product: J-Link
[ 3753.941482] usb 1-1.3: Manufacturer: SEGGER
[ 3753.941499] usb 1-1.3: SerialNumber: 000621000000
[ 3753.943825] cdc_acm 1-1.3:1.0: ttyACM0: USB ACM device
[ 3763.815366] usb 1-1.2: new full-speed USB device number 9 using dwc_otg
[ 3763.919642] usb 1-1.2: New USB device found, idVendor=2504, idProduct=0300
[ 3763.919671] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 3763.919709] usb 1-1.2: Product: FSL CDC DEVICE
[ 3763.919727] usb 1-1.2: Manufacturer: FREESCALE INC.
[ 3763.921320] cdc_acm 1-1.2:1.0: ttyACM1: USB ACM device

Бег

udevadm info -a -n /dev/ttyACM1

показывает мне следующую информацию для Segger OpenSDA J-Link:

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3':
    KERNELS=="1-1.3"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="02"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{devpath}=="1.3"
    ATTRS{idVendor}=="1366"
    ATTRS{speed}=="12"
    ATTRS{bNumInterfaces}==" 3"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="8"
    ATTRS{configuration}=="Configuration"
    ATTRS{bMaxPower}=="100mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="80"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="0"
    ATTRS{bcdDevice}=="0100"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{serial}=="000621000000"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="586"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="SEGGER"
    ATTRS{removable}=="removable"
    ATTRS{idProduct}=="0105"
    ATTRS{bDeviceClass}=="ef"
    ATTRS{product}=="J-Link"

Нам понадобится эта информация позже.

Терминальная программа Minicom

Теперь, когда я знаю устройство, мне нужна терминальная программа для связи с устройством. Я нашел программу терминала minicom очень простой в использовании, и она работает как с удаленного SSH, так и локально на Raspberry Pi.

Если minicom еще не установлен, используйте следующую команду для его установки:

sudo apt-get install minicom

Запустите миником с

minicom -D /dev/ttyACM0 -b 38400

Где -D указывает устройство, которое будет использоваться, и -b скорость передачи устройства. Это запускает программу терминала:

Началась мини-сессия

Как указано в нижней части экрана, я могу нажать «CTRL + A» (нажатие «CTRL», затем нажать клавишу «a» (нижний регистр), отпустить обе клавиши и затем нажать «z» на клавиатуре), чтобы отобразить меню справки:

Справка Minicom

Я могу использовать это меню, например, для включения / выключения локального эха. Без меню я просто использовал бы «CTRL + E» и «e»:

Local Echo On

Теперь я могу использовать minicom как обычную терминальную программу для общения с моими приложениями через оболочку (как показано ниже, где я разговариваю с моим проектом беспилотного квадрокоптера на FRDM-K22F ):

терминальная сессия minicom

Чтобы оставить миником, я использую CTRL + A, за которым следует x . Это повесит сессию.

Постоянные имена устройств для устройств USB CDC

Остается одна проблема: какое устройство используется, зависит от порядка, в котором оно распознается. Позже, когда я захочу использовать плату с openHAB, мне нужно убедиться, что плата всегда подключена к одному и тому же устройству. Чтобы назначить фиксированное устройство, я могу использовать правила udev . С помощью этих правил я могу указать, что произойдет при подключении нового устройства. Смотрите также эту статью о том, как писать файлы правил udev.

В /etc/udev/rules.d я создаю новый файл с именем

99-usb-serial.rules

99-USB-serial.rules

Файл должен иметь расширение .rules. Число 99 объясняется тем, что правила> = 90 должны выполняться последними (см. Http://hackaday.com/2009/09/18/how-to-write-udev-rules/ ).

Теперь мне нужно найти атрибуты, чтобы различать несколько USB CDC-устройств. Для этого я использую команду udevadm, которую я использовал ранее.

Чтобы создать выделенное устройство для Segger J-Link, я могу добавить следующую строку в 99-usb-serial.rules :

SUBSYSTEM=="tty", ATTRS{idVendor}=="1366", ATTRS{product}=="J-Link", ATTRS{idProduct}=="0105", ATTRS{serial}=="000621000000", SYMLINK+="ttyUSB50"

В частности, я пытаюсь использовать набор соответствующих атрибутов для идентификации устройства, а затем создать символическую ссылку для него с помощью команды SYMLINK + = .

Таким же образом я добавляю следующую строку для идентификации моей реализации USB CDC:

SUBSYSTEM=="tty", ATTRS{idVendor}=="2504", ATTRS{product}=="FSL CDC DEVICE", ATTRS{manufacturer}=="FREESCALE INC.              ", SYMLINK+="ttyUSB51"

Это означает, что устройство по-прежнему будет использоваться как \ dev \ ttyACMx, но будет создана символическая ссылка / dev / ttyUSB50 или / dev / ttyUSB51.

Я использую следующую команду для проверки правил:

udevadm test /dev/ttyACM0

Это не создаст ссылки, но может быть полезно посмотреть, что происходит.

Правила Udev вступают в силу немедленно, но не сработают, если устройство уже подключено. Чтобы проверить мои новые правила, я должен отключить и повторно подключить устройства USB. Или использовать

udevadm trigger

С участием

ls -l /dev

Я должен видеть, что ссылка была создана:

lrwxrwxrwx 1 root root           7 Dec 26 19:23 ttyUSB50 -> ttyACM0
lrwxrwxrwx 1 root root           7 Dec 26 19:30 ttyUSB51 -> ttyACM1

Благодаря этому к Raspberry Pi можно подключить несколько плат, и они будут использовать фиксированное устройство:

Платы FRDM подключены к Raspberry Pi

Обратите внимание, что если у меня нет различий между устройствами, я не могу их различить. Это, например, проблема, например, с устройством USB CDC FSL, если я не меняю атрибуты по умолчанию. Я думаю о добавлении серийного номера в дескриптор устройства USB, чтобы я мог легко различать различные устройства таким образом.

Резюме

С некоторой работой я могу легко работать с устройствами USB CDC, подключенными к USB-портам Raspberry Pi. С помощью lsusb я вижу, какие устройства подключены, с помощью информации udevadm я могу проверить атрибуты устройства, а с помощью правил udev я могу назначить постоянные имена устройств на основе атрибутов. А с minicom у меня есть хорошая терминальная программа, которую я могу использовать для общения с USB-устройствами CDC.