Некоторое время назад мне предложили немного поработать с одноплатным ПК Orange Pi 2G-IOT (встроенный 2G и цена выглядят очень привлекательно). Прочитав пост об апельсиновом рае, я подумал, что без затруднений повторю этот путь, тем более, что с Linux я на «ты» (вернее, так я думал недели три назад) и уже имел опыт общения с Raspberry Pi 2 B+. На практике этот путь оказался намного длиннее. Создавалось ощущение, что наши китайские друзья намеренно создавали сложности (причём иногда с особым цинизмом). Если вы захотели сэкономить и купить эту плату, то сначала прочитайте этот пост и подумайте ещё раз.
По возможности, я постараюсь сдерживать эмоции или как минимум переводить их в юмор.
Итак, вот мне в руки попадает плата и SD карточка десятого класса. Поехали.
Всё ниже написанное относится к модели Orange Pi 2G-IOT, но в чате Телеграма (ищите «Orange Pi и не только») говорят, что модели 2G, 3G и 4G примерно одинаково себя ведут (одинаково плохо). Написанное НЕ относится к, например, Orange Pi PC и Orange Pi One, которые по отзывам ведут себя стабильно.
Мина №1 (учебная): скачивание образа ОС
Казалось бы, что может быть проще? Идём на сайт производителя и качаем. Однако все ссылки ведут на mega.nz, который собирает его прямо в браузере. Мой дешёвый ноутбук с 4 Гб ОЗУ не потянул такую задачу и вкладка упала. Можно было бы воспользоваться фирменной программой для скачивания с Меги, но он у меня не вызвал доверия (тем более, что в Интернетах некоторые пишут, что программа распознаётся антивирусами как вредоносное ПО). Варианты решения: скачать с неофициального сайта (например, здесь), развернуть виртуалку и поставить в ней клиент для скачивания с Меги, попросить кого-то с более современным ПК скачать образ.
Мина №2: выход в Интернет через модем
Дословно следуя настройке wvdial и pppd в Интернете, я внезапно обнаружил, что ping запросы проходят исправно, а вот обычные TCP пакеты ни в какую:
orangepi@OrangePi:~$ curl --interface ppp0 195.201.201.32
curl: (7) Failed to connect to 195.201.201.32 port 80: Connection timed out
orangepi@OrangePi:~$ curl --interface ppp0 195.201.201.32
curl: (7) Failed to connect to 195.201.201.32 port 80: Connection timed out
orangepi@OrangePi:~$ curl --interface ppp0 195.201.201.32
curl: (7) Failed to connect to 195.201.201.32 port 80: Connection timed out
orangepi@OrangePi:~$ curl --interface wlan0 195.201.201.32
46.0.208.54
orangepi@OrangePi:~$ ping 195.201.201.32 -I ppp0
PING 195.201.201.32 (195.201.201.32) from 10.33.64.21 ppp0: 56(84) bytes of data.
64 bytes from 195.201.201.32: icmp_seq=1 ttl=52 time=664 ms
64 bytes from 195.201.201.32: icmp_seq=2 ttl=52 time=240 ms
64 bytes from 195.201.201.32: icmp_seq=3 ttl=52 time=234 ms
64 bytes from 195.201.201.32: icmp_seq=4 ttl=52 time=246 ms
64 bytes from 195.201.201.32: icmp_seq=5 ttl=52 time=241 ms
64 bytes from 195.201.201.32: icmp_seq=6 ttl=52 time=237 ms
^C
--- 195.201.201.32 ping statistics ---
7 packets transmitted, 6 received, 14% packet loss, time 6032ms
rtt min/avg/max/mdev = 234.634/310.971/664.998/158.370 ms
orangepi@OrangePi:~$
Решение подсказал edtun: https://www.linux.org.ru/forum/admin/12135523, хотя допускаю, что можно было как-то проще.
Сразу насторожило, что IMEI модема забит нулями. Благо, красно-белый оператор связи не обращает на это внимание. (Кстати, у встроенного WiFi аналогично нет МАС-адреса: при каждом передёргивании питания он генерируется случайным образом.)
Мина №3: USB порт
Втыкаем WiFi свисток в USB разъём и… Ничего не происходит. lsusb отобразил пустой USB порт. Небольшое копание показало, что в плате реально всего один USB. И по умолчанию он подключен к microUSB порту. Для переключения его на обычный USB HOST необходимо переключить на плате джамперы, которые находятся рядом с перемычкой для выбора загрузки. Их описание есть на 4pda:
Решение: переключить джамперы в положение: 1234 вниз, 5678 вверх.
Только потом я нашёл небольшое упоминание об этом нюансе в мануале к Orange Pi.
Мина №4: Драйверы
Теперь устройство определяется в системе, lsusb отображает производителя и код продукта, но беспроводной сетевой интерфейс в системе не определяется. Потому что разработчики не завезли на апельсинку драйвера для WiFi адаптеров. Причём вообще никаких. Есть драйвер только для встроенного WiFi, не больше и не меньше. А что мы делаем, когда у нас нет драйвера под наше железо? Правильно, идём собирать их из исходного кода!
Мина №5: Подготовка к сборке
В переписке bad__day предложил сборку непосредственно на Orange Pi. Может быть, это возможно, но мне не удалось.
Для Orange Pi разработчики сделали специальную Orange Pi Build System, с помощью которой в теории для сборки ядра или модулей к нему достаточно просто следовать указаниям на экране. Подробная инструкция изложена в мануале начиная с 61-й страницы. Казалось бы, просто следуй, и всё будет хорошо, но нет.
Во-первых, чтобы вручную не править все зависимости на своём компьютере (я регулярно обновляю ПО, это здорово, но не в этот раз), я развернул виртуалку с Ubuntu 16.04 и все действия проводил там. Во-вторых, в скриптах где-то вкралась ошибка, и Build System не ставила тулчейн для кроссплатформенной компиляции. Решается это таким костылём:
- Вручную apt-get'ом ставим тулчейн для кросскомпиляции под ARM.
- Делаем симлинки:
mkdir $HOME/OrangePiRDA/toolchain/bin ln -s $(which arm-linux-gnueabi-ld) $HOME/OrangePiRDA/toolchain/bin/arm-linux-gnueabi-ld ln -s $(which arm-linux-gnueabi-gcc-4.9) $HOME/OrangePiRDA/toolchain/bin/arm-linux-gnueabi-gcc ln -s $(which arm-linux-gnueabi-g++-4.9) $HOME/OrangePiRDA/toolchain/bin/arm-linux-gnueabi-g++ ln -s $(which arm-linux-gnueabi-ar) $HOME/OrangePiRDA/toolchain/bin/arm-linux-gnueabi-ar ln -s $(which arm-linux-gnueabi-nm) $HOME/OrangePiRDA/toolchain/bin/arm-linux-gnueabi-nm ln -s $(which arm-linux-gnueabi-objcopy) $HOME/OrangePiRDA/toolchain/bin/arm-linux-gnueabi-objcopy ln -s $(which arm-linux-gnueabi-size) $HOME/OrangePiRDA/toolchain/bin/arm-linux-gnueabi-size
Обратите внимание: компилятор берётся версии 4.9, на версиях выше ничего не соберётся.
- Открываем OrangePiRDA/scripts/Prepare_toolchain.sh и на всякий случай комментируем строки, упоминающие тулчейн.
На самом деле все эти скрипты просто вызывают apt-get install -y… и make. Скрипт не предлагает пользователю как-либо изменять конфигурацию (или я не нашёл?).
Но ведь нам ничего не мешает самим вызвать
make menuconfig
и отметить нужные драйверы. Делаем это и снова собираем (теперь можно только модули) и…
Мина №6 (с прикрученным ИК датчиком движения и запасным детонатором): Сборка драйвера
… И тут скрипт приветливо стал задавать вопросы, как ему конфигурировать ядро. Он вызвал старомодный конфигуратор ядра, но почему?! Что не так?
Оказалось, что в Makefile прописано проверять ВРЕМЯ(!!!) изменения конфига!
В комментарии дословно написано «кто-то копался». (На скриншоте уже изменённый Makefile, я прописал menuconfig.) Пробовал вызывать make oldconfig, не заметил, чтобы это что-то где-то изменило. Ладно, теперь ведь при сборке вызовется menuconfig, это не страшно. Снова вызываю сборку, сборка замечает, что «кто-то копался в конфиге», вызывает menuconfig, я выхожу и жду завершения. А теперь представьте моё удивление, когда я не нашёл выбранный мною драйвер.
Что ж, лезем разбираться. Оказывается, make создаёт файл modules.order, где описаны все модули, которые будут скомпилированы. И даже после всех изменений конфига и его сохранения этот файл заполняется одинаковым набором. Я не придумал ничего лучшего, чем вручную дописать в него строки (мой свисток собран на чипсете RTL8192CU):
kernel/driver/net/wireless/rtlwifi.ko
kernel/driver/net/wireless/rtlwifi/rtl8192cu.ko
Все упоминания этого файла в Makefile заменил на modules.order.fake. Запускаю сборку. На этот раз сборка пошла, но оборвалась, так как аналогичного файла нет в папке с исходным кодом rtlwifi. Я переименовал в этой папке и подпапках файлы modules.order.fake на modules.order, и это стало моим последним приключением при сборке драйвера. После этого система ещё два раза выводила мне menuconfig, как будто спрашивая меня «ты точно этого хочешь?», но всё же собрала дополнительно три заветных .ko файла, которые завелись как положено.
Мина №7: Совместная работа внешнего WiFi и модема
Немного поигравшись с airodump'ом и убедившись, что как минимум ловить пакеты в режиме монитора устройство умеет, я решил проверить модем ещё раз. Выполняю
sudo wvdial
И светодиод на внешнем WiFi адаптере гаснет, а SSH отваливается. В логах потом прочитал, что адаптер был отключен. Первая мысль — проблема с питанием. До этого момента я использовал свой зарядник на 1,5 Ампера, а производитель рекомендует аж целых 3 (куда столько? Она и одного Ампера даже не ест). Под рукой был зарядник на 2 Ампера, который годами исправно питал Raspberry Pi.
На данный момент я не нашёл какого-либо стабильного решения данной проблемы. Вот некоторые попытки решения:
- С вероятностью 80% можно отключить внешний WiFi с помощью:
chmod 777 /sys/bus/usb/drivers/usb/unbind echo 1-1 > /sys/bus/usb/drivers/usb/unbind
а затем запустить wvdial, который с 1-3 попытки установит соединение и можно выйти в Интернет. В 20% разного рода зависания и глюки.
- Однажды случайно оказалась такая ситуация, что был убит wvdial, но pppd остался работать (как так может быть?), после которого поднялся внешний WiFi (см. выше, только вместо unbind пишем bind) и связь через модем была. Воспроизвести ситуацию не удалось.
- Оказалось, что можно без пересборки ядра отключать питание на USB с помощью такой утилиты командой
./hub-ctrl -h 0 -P 1 -p 0
и включить питание
./hub-ctrl -h 0 -P 1 -p 1
На 2G-IOT поведение непредсказуемое: отключение питания может быть либо на одну секунду, либо до перезагрузки. При некоторых фазах Луны попытка вернуть питание приводит к зависанию платы.
- Переключить джамперы на OTG (1234 вверх, 5678 вниз), питание подать на ноги GPIO 2 и 6 (прозванивал, они напрямую соединены с питанием microUSB)
Распиновка
подключить WiFi адаптер через USB-OTG переходник от смартфона. Система не видит USB устройства вообще. Возможно, надо настойчивее поиграться с джамперами.
Не проверялось, но может сработать (в планах опробовать все эти варианты):
- Другой WiFi адаптер.
- Очень стабильный источник питания с максимальным током 3 Ампера.
- Дополнительное питание к ногам USB.
- Бензин и спички.
В общем, задача выглядит как натягивание треугольного одеяла на четырёхугольный апельсин.
На этом пока всё. To be continued...
Автор: id_potassium_chloride